I'd like a user to be able to create a custom format in QtWidgets.QPlainTextEdit() and it would format the string and split out the results in another QtWidgets.QPlainTextEdit().
For example:
movie = {
"Title":"The Shawshank Redemption",
"Year":"1994",
"Rated":"R",
"Released":"14 Oct 1994",
"Runtime":"142 min",
"Genre":"Drama",
"Director":"Frank Darabont",
"Writer":"Stephen King (short story \"Rita Hayworth and Shawshank Redemption\"),Frank Darabont (screenplay)",
"Actors":"Tim Robbins, Morgan Freeman, Bob Gunton, William Sadler",
"Plot":"Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.",
"Language":"English",
"Country":"USA",
"Awards":"Nominated for 7 Oscars. Another 21 wins & 36 nominations.",
"Poster":"https://m.media-amazon.com/images/M/MV5BMDFkYTc0MGEtZmNhMC00ZDIzLWFmNTEtODM1ZmRlYWMwMWFmXkEyXkFqcGdeQXVyMTMxODk2OTU#._V1_SX300.jpg",
"Ratings": [
{
"Source":"Internet Movie Database",
"Value":"9.3/10"
},
{
"Source":"Rotten Tomatoes",
"Value":"91%"
},
{
"Source":"Metacritic",
"Value":"80/100"
}
],
"Metascore":"80",
"imdbRating":"9.3",
"imdbVotes":"2,367,380",
"imdbID":"tt0111161",
"Type":"movie",
"DVD":"15 Aug 2008",
"BoxOffice":"$28,699,976",
"Production":"Columbia Pictures, Castle Rock Entertainment",
"Website":"N/A"
}
custom_format = '[ {Title} | ⌚ {Runtime} | ⭐ {Genre} | 📅 {Released} | {Rated} ]'.format(Title=movie['Title'], Runtime=movie['Runtime'], Genre=movie['Genre'],Released=movie['Released'],Rated=movie['Rated'])
print(custom_format)
This code above, would easily print [ The Shawshank Redemption | ⌚ 142 min | ⭐ Drama | 📅 14 Oct 1994 | R ].
However, if I change this code from:
custom_format = '[ {Title} | ⌚ {Runtime} | ⭐ {Genre} | 📅 {Released} | {Rated} ]'.format(Title=movie['Title'], Runtime=movie['Runtime'], Genre=movie['Genre'],Released=movie['Released'],Rated=movie['Rated'])
To:
custom_format = "'[ {Title} | ⌚ {Runtime} | ⭐ {Genre} | 📅 {Released} | {Rated} ]'.format(Title=movie['Title'], Runtime=movie['Runtime'], Genre=movie['Genre'],Released=movie['Released'],Rated=movie['Rated'])"
Notice, that the whole thing is wrapped in "". Therefor its a string. Now doing this will not print out the format that I want.
The reason I wrapped it in "" is because when I add my original custom_format into a QtWidgets.QPlainTextEdit(), it converts it into a string it wont format later on.
So my original idea was, the user creates a custom format for themselves in a QtWidgets.QPlainTextEdit(). Then I copy that format, open a new window wher the movie json variable is contained and paste the format into another QtWidgets.QPlainTextEdit() where it would hopefuly show it formatted correctly.
Any help on this would be appreciated.
ADDITIONAL INFORMATION:
User creates their format inside QtWidgets.QPlainTextEdit().
Then the user clicks Test Format which should display [ The Shawshank Redemption | ⌚ 142 min | ⭐ Drama | 📅 14 Oct 1994 | R ] but instead it displays
Trying to use the full format command would require an eval(), which is normally considered not only bad practice, but also a serious security issue, especially when the input argument is completely set by the user.
Since the fields are known, I see little point in providing the whole format line, and it is better to parse the format string looking for keywords, then use keyword lookup to create the output.
class Formatter(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QVBoxLayout(self)
self.formatBase = QtWidgets.QPlainTextEdit(
'[ {Title} | ⌚ {Runtime} | ⭐ {Genre} | 📅 {Released} | {Rated} ]')
self.formatOutput = QtWidgets.QPlainTextEdit()
layout.addWidget(self.formatBase)
layout.addWidget(self.formatOutput)
self.formatBase.textChanged.connect(self.processFormat)
self.processFormat()
def processFormat(self):
format_str = self.formatBase.toPlainText()
# escape double braces
clean = re.sub('{{', '', re.sub('}}', '', format_str))
# capture keyword arguments
tokens = re.split(r'\{(.*?)\}', clean)
keywords = tokens[1::2]
try:
# build the dictionary with given arguments, unrecognized keywords
# are just printed back in the {key} form, in order let the
# user know that the key wasn't valid;
values = {k:movie.get(k, '{{{}}}'.format(k)) for k in keywords}
self.formatOutput.setPlainText(format_str.format(**values))
except (ValueError, KeyError):
# exception for unmatching braces
pass
I have an xml with a structure like this one:
<cat>
<foo>
<fooID>1</fooID>
<fooName>One</fooName>
<bar>
<barID>a</barID>
<barName>small_a</barName>
<barClass>
<baz>
<qux>
<corge>
<corgeName>...</corgeName>
<corgeType>
<corgeReport>
<corgeReportRes Reference="x" Channel="High">
<Pos>1</Pos>
</corgeReportRes>
</corgeReport>
</corgeType>
</corge>
</qux>
</baz>
</barClass>
</bar>
<bar>
<barID>b</barID>
<barName>small_b</barName>
<barClass>
<baz>
<qux>
<corge>
<corgeName>...</corgeName>
<corgeType>
<corgeReport>
<corgeReportRes Reference="y" Channel="High">
<Pos>1</Pos>
</corgeReportRes>
</corgeReport>
</corgeType>
</corge>
</qux>
</baz>
</barClass>
</bar>
</foo>
<foo>
<fooID>2</fooID>
<fooName>Two</fooName>
<bar>
<barID>c</barID>
<barName>small_c</barName>
<barClass>
<baz>
<qux>
<corge>
<corgeName>...</corgeName>
<corgeType>
<corgeReport>
<corgeReportRes Reference="z" Channel="High">
<Pos>1</Pos>
</corgeReportRes>
</corgeReport>
</corgeType>
</corge>
</qux>
</baz>
</barClass>
</bar>
</foo>
</cat>
And, I would like to obtain the values of specific parent/grand parent/grand grand parent tags that have a node with attribute Channel="High". I would like to obtain only fooID value, fooName value, barID value, barName value.
I have the following code in Python 3:
import xml.etree.ElementTree as xmlET
root = xmlET.parse('file.xml').getroot()
test = root.findall(".//*[#Channel='High']")
Which is actually giving me a list of elements that match, however, I still need the information of the specific parents/grand parents/grand grand parents.
How could I do that?
fooID | fooName | barID | barName
- - - - - - - - - - - - - - - - -
1 | One | a | small_a <-- This is the information I'm interested
1 | One | b | small_b <-- Also this
2 | Two | c | small_c <-- And this
Edit: fooID and fooName nodes are siblings of the grand-grand-parent bar, the one that contains the Channel="High". It's almost the same case for barID and barName, they are siblings of the grand-parent barClass, the one that contains the Channel="High". Also, what I want to obtain is the values 1, One, a and small_a, not filtering by it, since there will be multiple foo blocks.
If I understand you correctly, you are probably looking for something like this (using python):
from lxml import etree
foos = """[your xml above]"""
items = []
for entry in doc.xpath('//foo[.//corgeReportRes[#Channel="High"]]'):
items.append(entry.xpath('./fooID/text()')[0])
items.append(entry.xpath('./fooName/text()')[0])
items.append(entry.xpath('./bar/barID/text()')[0])
items.append(entry.xpath('./bar/barName/text()')[0])
print('fooID | fooName | barID | barName')
print(' | '.join(items))
Output:
fooID | fooName | barID | barName
1 | One | a | small_a
I want to automate an action and here is the code that I'm using:
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="ir_cron_scheduler_demo_action" model="ir.cron">
<field name="name">Demo scheduler</field>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">2</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall"/>
<field eval="'note.admin'" name="model"/>
<field eval="'process_demo_scheduler_queue'" name="function"/>
</record>
</data>
</openerp>
#api.model
def process_demo_scheduler_queue(self):
for note in self.env['note.admin']:
if datetime.strptime(note.date, DEFAULT_SERVER_DATETIME_FORMAT).date() == datetime.now().date():
note.write({'is_visible': True})
What I want to do is to set the value is_visible on True when the field note.date == current date
here is the log on server:
2016-05-25 01:20:17,658 3680 INFO test3 werkzeug: 127.0.0.1 - -
[25/May/2016 01:20:17] "POST
/web/dataset/call_kw/note.admin/message_get_subscription_data
HTTP/1.1" 200 -
but it is not working!
SOLVED:
#api.model
def process_demo_scheduler_queue(self):
notes = self.search([('date', '=', fields.Date.today())])
notes.write({'is_visible': True})
You have to write like below code,
#api.model
def process_demo_scheduler_queue(self):
for note in self.env['note.admin'].search([]):
if datetime.strptime(note.date, DEFAULT_SERVER_DATETIME_FORMAT).date() == datetime.now().date():
note.write({'is_visible': True})
First you have to search for all notes in your database, and second try to use odoo's date logic:
#api.model
def process_demo_scheduler_queue(self):
for note in self.search([]):
if note.date == openerp.fields.Date.context_today(self):
note.is_visible = True
Or maybe faster:
#api.model
def process_demo_scheduler_queue(self):
notes = self.search([('date', '=', openerp.fields.Date.context_today(self))])
notes.write({'is_visible': True})
I've been trying to read an xml file and convert it to json using groovy's JsonBuilder. The problem is that when I print with
def builder = new JsonBuilder(jsonObject)
println builder.toPrettyString()
I got a Caught: java.lang.StackOverflowError
Here is the whole stacktrace
Exception in thread "main" java.lang.StackOverflowError
at groovy.json.JsonOutput.writeObject(JsonOutput.java:259)
at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
Here the code.
package firstgroovyproject
import groovy.json.JsonBuilder
class XmlToJsonII {
static void main(def args){
def carRecords = '''
<records>
<car name='HSV Maloo' make='Holden' year='2006'>
<countries>
<country>
Austria
</country>
<country>
Spain
</country>
</countries>
<record type='speed'>Production Pickup Truck with speed of 271kph
</record>
</car>
<car name='P50' make='Peel' year='1962'>
<countries>
<country>
Monaco
</country>
</countries>
<record type='size'>Smallest Street-Legal Car at 99cm wide and 59 kg
in weight</record>
</car>
<car name='Royale' make='Bugatti' year='1931'>
<record type='price'>Most Valuable Car at $15 million</record>
<countries>
<country>
Italia
</country>
</countries>
</car>
<car name='Seat' make='Ibiza' year='1985'>
<record type='price'>barato</record>
<countries>
<country>
Spain
</country>
</countries>
</car>
</records>
'''
def xmlRecords = new XmlSlurper().parseText(carRecords)
def jsonObject = [:]
jsonObject.records = []
def records = jsonObject.records
xmlRecords.car.each {xmlCar ->
records.add([
countries:
xmlCar.countries.children().each{ country ->
println "country : ${country.text()}"
[country: country.text()]
},
])
}
def builder = new JsonBuilder(jsonObject)
println builder.toPrettyString()
//println builder.toString()
}
}
tl;dr: Your second (inner) each should be a collect instead.
The real answer: The return value of each is the original Iterable that invoked it. In this case that would be the XML object collection defined by the expression xmlCar.countries.children(). Since the objects in that collection contain references back to their own parents your JSON build causes an infinite regress that results in a stack overflow.
This doesn't happen with your first (outer) use of each, because you are not using the return value. Instead you are adding to a preexisting list (records).
By changing the second (inner) each into a collect, you are still iterating through the children of the countries elements. However, instead of returning the original XML children (the result of each) you are compiling and returning a list of maps of the form [country:"country_string_from_xml"], which seems to be the desired behavior.
Confusing each and collect is a common rookie mistake in Groovy... which only made it all the more galling when it happened to ME last week. :-)
I have an xml structure like this
<JJJ version="2.0" >
<Data >
<Object class="classX">
<k name="constname1">variable1</p>
<k name="constname2">variable2</p>
<k name="constname3">variable3</p>
</Object>
<Object class="classY">
<k name="constname1">variable11</p>
<k name="constname2">variable12</p>
<k name="constname3">variable13</p>
</Object>
I need to select ClassX node and in that value of atttribute containing constname1 (ie variable1
def parser = new XmlSlurper()
def mymo=records.'Data'.'Object';
def mytest = mymo.findAll{it.#class.text()=="ClassX"};
mytest.each{
it.'p'.each{
println it.#name.text() +'-'+ it.text() }
}
This is working. But instead of then comapring text in the loop I need to do something like this
def testme= mytest.'k'.find{ it.#name.text()=="constname1"}
This I am not getting right
However the below is right
println mymo.'k'.find{it.#name.text()=="constname1"}
But I want to restrict selection to the node for classX
Correcting your xml so it's valid, gives:
def xml = '''<JJJ version="2.0" >
| <Data >
| <Object class="classX">
| <k name="constname1">variable1</k>
| <k name="constname2">variable2</k>
| <k name="constname3">variable3</k>
| </Object>
| <Object class="classY">
| <k name="constname1">variable14</k>
| <k name="constname2">variable15</k>
| <k name="constname3">variable16</k>
| </Object>
| <Object class="classX">
| <k name="constname1">variable7</k>
| <k name="constname2">variable8</k>
| <k name="constname3">variable9</k>
| </Object>
| </Data>
|</JJJ>'''.stripMargin()
List var = new XmlSlurper().parseText( xml ).'**'.grep {
it.#name == 'constname1' && it.parent().#class == 'classX'
}
assert var == [ 'variable1', 'variable7' ]
is that what you wanted?
I guess the correct way was
mytest.'k'.find{ it.['#name']=="constname1"}
Did similar for some other xml Link -->GPath Groovy