Print a list of lists of dicts in Python - python

I have the following list of lists of dicts:
l = [[{'close': 'TRUE'}], [{'error': 'FALSE'}], [{'close': 'TRUE', 'error': 'TRUE'}, {'close': 'TRUE', 'error': 'FALSE'}]]
and I would like to print it this way:
(close = TRUE) & (error = FALSE) & ((close = TRUE & error = TRUE) | (close = TRUE & error = FALSE))
For the moment, I have the following function which nearly do the job:
def pretty_string(l):
print ' & '.join('({0})'
.format(' | '
.join('({0})'
.format(' & '
.join('{0} = {1}'
.format(key, value)
for key, value
in disjuncts.items()))
for disjuncts
in conjuncts))
for conjuncts
in l)
But it gives me:
((close = TRUE)) & ((error = FALSE)) & ((close = TRUE & error = TRUE) | (close = TRUE & error = FALSE))
Notice the extra parentheses around "(close = TRUE)" and "(error = FALSE)".
How can these be removed?

Just use if statement to change format string (('({0})' if len(disjuncts) > 1 else '{0}')) depending on the length of your internal list. Like this:
def pretty_string(l):
print ' & '.join(
'({0})'.format(
' | '.join(
('({0})' if len(disjuncts) > 1 else '{0}').format(
' & '.join(
'{0} = {1}'.format(key, value) for key, value in disjuncts.items()
)
) for disjuncts in conjuncts
)
) for conjuncts in l
)

def conv(item):
if(isinstance(item, dict)):
yield '(' + ' & '.join("{} = {}".format(*i) for i in item.items()) + ')'
elif(isinstance(item, list)):
for i in item:
for s in conv(i):
yield s
def pretty_string(l):
return ' | '.join(conv(l))

Related

Postback, filters and sorting data in an App using Django and AJAX

I keep having this problem where I can't order some tables by date. I'm reading this code, I didn't write it so it will be useful if anyone can give me some tips. If I miss some information, just ask me, please.
The ListView code:
def poll_ajax(request, poll_id, user_url, venue_id=None):
cursor = connections['default'].cursor()
start = request.GET['start']
length = int(request.GET['length'])
page = int(request.GET['draw'])
poll = Poll.objects.get(id=poll_id)
if not can_access_poll(request, poll):
return JsonResponse({"error": "An error occurred"})
date_from = None
period = None
date_condition_shown = ''
if request.GET.get("period"):
period = request.GET['period']
if period and period != 'Total':
date_condition, date_condition_shown, date_previous_condition, days_difference, date_from, date_to, filtering_by_date, date_from_previous, date_to_previous, date_from_string, date_from_previous_string = build_dates(
period, None)
if 'venue_id' in request.GET and request.GET['venue_id'] != '0' and request.GET['venue_id'] != 'undefined':
filter_venue_id = request.GET['venue_id']
elif venue_id:
filter_venue_id = venue_id
else:
filter_venue_id = None
try:
total = PollUser.objects.filter(poll=poll, completed=True).count()
query = 'Select v.shown_on, v.source, u.first_name, u.last_name, p.id, v.id, ve.name ' \
'From app_polluser v ' \
'Inner join app_customuser u on u.id = v.user_id ' \
'Inner join app_userprofile p on p.user_id = u.id '
query += 'Left join app_session s on v.session_id = s.id '
query += 'Left join app_router r on s.router_id = r.id '
query += 'Left join app_venue ve on r.venue_id = ve.id '
query += 'Where v.completed = 1 and v.poll_id = ' + poll_id
if filter_venue_id:
query += ' and ve.id = ' + filter_venue_id
if date_condition_shown != '':
query += date_condition_shown
cursor.execute(query)
result = cursor.fetchall()
result = [(humanize_timesince(r[0]),
translate_source(r[1]),
(('<a href=\'/profile/%s/' + user_url + '\'>%s %s</a>') % (r[4], r[2], r[3])),
r[6],
r[5]) for r in result]
result = [list(x[:4]) + get_votes(poll, x[4]) for x in result]
total_filtered = total
if filter_venue_id:
count_filtered = 'Select Count(*) From app_polluser v '
count_filtered += 'Left join app_session s on v.session_id = s.id '
count_filtered += 'Left join app_router r on s.router_id = r.id '
count_filtered += 'Where v.completed = 1 and v.poll_id = ' + poll_id + ' and r.venue_id = ' + filter_venue_id
cursor.execute(count_filtered)
total_filtered = int(cursor.fetchone()[0])
And the server response is this:
"[02/Oct/2019 14:59:11]'GET
/poll_ajax/268/customer/33?period=Total&venue_id=0&draw=1&columns%5B0%5D%5Bdata%5D=0&columns%5B0%5D%5Bname%5D=&columns%5B0%5D%5Bsearchable%5D=true&columns%5B0%5D%5Borderable%5D=true&columns%5B0%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B0%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B1%5D%5Bdata%5D=1&columns..."
HTTP/1.1' 200 801"
If you have any advise, even if my post didn't bring many information, just tell me, I just want to know what is the problem here.
Additionaly the database that the app is using is in MySQL and is local.

Get correct brace grouping from string

I have files with incorrect JSON that I want to start fixing by getting it into properly grouped chunks.
The brace grouping {{ {} {} } } {{}} {{{}}} should already be correct
How can I grab all the top-level braces, correctly grouped, as separate strings?
If you don't want to install any extra modules simple function will do:
def top_level(s):
depth = 0
start = -1
for i, c in enumerate(s):
if c == '{':
if depth == 0:
start = i
depth += 1
elif c == '}' and depth:
depth -= 1
if depth == 0:
yield s[start:i+1]
print(list(top_level('{{ {} {} } } {{}} {{{}}}')))
Output:
['{{ {} {} } }', '{{}}', '{{{}}}']
It will skip invalid braces but could be easily modified to report an error when they are spotted.
Using the regex module:
In [1]: import regex
In [2]: braces = regex.compile(r"\{(?:[^{}]++|(?R))*\}")
In [3]: braces.findall("{{ {} {} } } {{}} {{{}}}")
Out[3]: ['{{ {} {} } }', '{{}}', '{{{}}}']
pyparsing can be really helpful here. It will handle pathological cases where you have braces inside strings, etc. It might be a little tricky to do all of this work yourself, but fortunately, somebody (the author of the library) has already done the hard stuff for us.... I'll reproduce the code here to prevent link-rot:
# jsonParser.py
#
# Implementation of a simple JSON parser, returning a hierarchical
# ParseResults object support both list- and dict-style data access.
#
# Copyright 2006, by Paul McGuire
#
# Updated 8 Jan 2007 - fixed dict grouping bug, and made elements and
# members optional in array and object collections
#
json_bnf = """
object
{ members }
{}
members
string : value
members , string : value
array
[ elements ]
[]
elements
value
elements , value
value
string
number
object
array
true
false
null
"""
from pyparsing import *
TRUE = Keyword("true").setParseAction( replaceWith(True) )
FALSE = Keyword("false").setParseAction( replaceWith(False) )
NULL = Keyword("null").setParseAction( replaceWith(None) )
jsonString = dblQuotedString.setParseAction( removeQuotes )
jsonNumber = Combine( Optional('-') + ( '0' | Word('123456789',nums) ) +
Optional( '.' + Word(nums) ) +
Optional( Word('eE',exact=1) + Word(nums+'+-',nums) ) )
jsonObject = Forward()
jsonValue = Forward()
jsonElements = delimitedList( jsonValue )
jsonArray = Group(Suppress('[') + Optional(jsonElements) + Suppress(']') )
jsonValue << ( jsonString | jsonNumber | Group(jsonObject) | jsonArray | TRUE | FALSE | NULL )
memberDef = Group( jsonString + Suppress(':') + jsonValue )
jsonMembers = delimitedList( memberDef )
jsonObject << Dict( Suppress('{') + Optional(jsonMembers) + Suppress('}') )
jsonComment = cppStyleComment
jsonObject.ignore( jsonComment )
def convertNumbers(s,l,toks):
n = toks[0]
try:
return int(n)
except ValueError, ve:
return float(n)
jsonNumber.setParseAction( convertNumbers )
Phew! That's a lot ... Now how do we use it? The general strategy here will be to scan the string for matches and then slice those matches out of the original string. Each scan result is a tuple of the form (lex-tokens, start_index, stop_index). For our use, we don't care about the lex-tokens, just the start and stop. We could do: string[result[1], result[2]] and it would work. We can also do string[slice(*result[1:])] -- Take your pick.
results = jsonObject.scanString(testdata)
for result in results:
print '*' * 80
print testdata[slice(*result[1:])]

Filter in sale.order list

In odoo, I need to list all the orders are paid, but not entirely (so all orders with a first facture).
I extended sale_order class with this code, but it does not works (I have no error message)
class sale(osv.osv):
def _invoiced_search(self, cursor, user, obj, name, args, context=None):
if not len(args):
return []
clause = ''
sale_clause = ''
no_invoiced = False
for arg in args:
if (arg[1] == '=' and arg[2]) or (arg[1] == '!=' and not arg[2]):
clause += 'AND inv.state = \'open\' AND inv.residual != \'0.0\' AND inv.residual != inv.amount_total '
else:
clause += 'AND inv.state != \'cancel\' AND sale.state != \'cancel\' AND inv.state = \'paid\' AND rel.order_id = sale.id '
clause += 'AND inv.state = \'open\' AND inv.residual != \'0.0\' AND inv.residual != inv.amount_total '
sale_clause = ', sale_order AS sale '
clause += 'AND inv.state = \'open\' AND inv.residual = inv.amount_total'
no_invoiced = True
cursor.execute('SELECT rel.order_id ' \
'FROM sale_order_invoice_rel AS rel, account_invoice AS inv '+ sale_clause + \
'WHERE rel.invoice_id = inv.id ' + clause)
res = cursor.fetchall()
if no_invoiced:
cursor.execute('SELECT sale.id ' \
'FROM sale_order AS sale ' \
'WHERE sale.id NOT IN ' \
'(SELECT rel.order_id ' \
'FROM sale_order_invoice_rel AS rel) ' \
'AND sale.state != \'cancel\'')
res.extend(cursor.fetchall())
if not res:
return [('id', '=', 0)]
return [('id', 'in', [x[0] for x in res])]
def _partial_invoiced(self, cursor, user, ids, name, arg, context=None):
res = {}
for sale in self.browse(cursor, user, ids, context=context):
res[sale.id] = False
invoice_existence = False
for invoice in sale.invoice_ids:
if invoice.state!='cancel':
invoice_existence = True
if invoice.state == 'open' and invoice.residual != '0.0':
res[sale.id] = True
break
if not invoice_existence or sale.state == 'manual':
res[sale.id] = False
return res
_inherit = 'sale.order'
_columns = {
'partially_invoiced': fields.function(_partial_invoiced, string='Paid',
fnct_search=_invoiced_search, type='boolean', help="It indicates that an invoice is partially paid."),
}
Help ;)

Parse C-like declarations using pyparsing

I would like to parse declarations using pyparsing in a C-like source (GLSL code) such that I get a list of (type, name, value).
For example:
int a[3];
int b=1, c=2.0;
float d = f(z[2], 2) + 3*g(4,a), e;
Point f = {1,2};
I would like to obtain something like:
[ ('int', 'a[3]', ''),
('int', 'b', '1'),
('int', 'c', '2.0'),
('float', 'd', 'f(z[2], 2) + 3*g(4,a)'),
('float', 'e', ''),
('Point', 'f', '{1,2}') ]
I've played with Forward() and operatorPrecedence() to try to parse the rhs expression but I suspect it is not necessary in my case.
So far I have:
IDENTIFIER = Regex('[a-zA-Z_][a-zA-Z_0-9]*')
INTEGER = Regex('([+-]?(([1-9][0-9]*)|0+))')
EQUAL = Literal("=").suppress()
SEMI = Literal(";").suppress()
SIZE = INTEGER | IDENTIFIER
VARNAME = IDENTIFIER
TYPENAME = IDENTIFIER
VARIABLE = Group(VARNAME.setResultsName("name")
+ Optional(EQUAL + Regex("[^,;]*").setResultsName("value")))
VARIABLES = delimitedList(VARIABLE.setResultsName("variable",listAllMatches=True))
DECLARATION = (TYPENAME.setResultsName("type")
+ VARIABLES.setResultsName("variables", listAllMatches=True) + SEMI)
code = """
float a=1, b=3+f(2), c;
float d=1.0, e;
float f = z(3,4);
"""
for (token, start, end) in DECLARATION.scanString(code):
for variable in token.variable:
print token.type, variable.name, variable.value
but the last expression (f=z(3,4)) is not parsed because of the ,.
There is a C struct parser on the pyparsing wiki that might give you a good start.
This seems to work.
IDENTIFIER = Word(alphas+"_", alphas+nums+"_" )
INT_DECIMAL = Regex('([+-]?(([1-9][0-9]*)|0+))')
INT_OCTAL = Regex('(0[0-7]*)')
INT_HEXADECIMAL = Regex('(0[xX][0-9a-fA-F]*)')
INTEGER = INT_HEXADECIMAL | INT_OCTAL | INT_DECIMAL
FLOAT = Regex('[+-]?(((\d+\.\d*)|(\d*\.\d+))([eE][-+]?\d+)?)|(\d*[eE][+-]?\d+)')
LPAREN, RPAREN = Literal("(").suppress(), Literal(")").suppress()
LBRACK, RBRACK = Literal("[").suppress(), Literal("]").suppress()
LBRACE, RBRACE = Literal("{").suppress(), Literal("}").suppress()
SEMICOLON, COMMA = Literal(";").suppress(), Literal(",").suppress()
EQUAL = Literal("=").suppress()
SIZE = INTEGER | IDENTIFIER
VARNAME = IDENTIFIER
TYPENAME = IDENTIFIER
OPERATOR = oneOf("+ - * / [ ] . & ^ ! { }")
PART = nestedExpr() | nestedExpr('{','}') | IDENTIFIER | INTEGER | FLOAT | OPERATOR
EXPR = delimitedList(PART, delim=Empty()).setParseAction(keepOriginalText)
VARIABLE = (VARNAME("name") + Optional(LBRACK + SIZE + RBRACK)("size")
+ Optional(EQUAL + EXPR)("value"))
VARIABLES = delimitedList(VARIABLE.setResultsName("variables",listAllMatches=True))
DECLARATION = (TYPENAME("type") + VARIABLES + SEMICOLON)
code = """
int a[3];
int b=1, c=2.0;
float d = f(z[2], 2) + 3*g(4,a), e;
Point f = {1,2};
"""
for (token, start, end) in DECLARATION.scanString(code):
vtype = token.type
for variable in token.variables:
name = variable.name
size = variable.size
value = variable.value
s = "%s / %s" % (vtype,name)
if size: s += ' [%s]' % size[0]
if value: s += ' / %s' % value[0]
s += ";"
print s

Change from Combine(Literal('#') + 'spec') to Keyword('#spec') removes whitespace

Why does using Combine(...) preserve the whitespace, whereas Keyword(...) removes thes whitespace?
I need to preserve the whitespace after the matched token.
The test is as follows:
from pyparsing import *
def parse(string, refpattern):
print refpattern.searchString(string)
pattern = StringStart() \
+ SkipTo(refpattern)('previous') \
+ refpattern('ref') \
+ SkipTo(StringEnd())('rest')
print pattern.parseString(string)
string = "With #ref to_something"
identifier = Combine(Word(alphas + '_', alphanums + '_') + Optional('.' + Word(alphas)))
pattern_without_space = (CaselessKeyword('#ref') | CaselessKeyword(r'\ref')).setParseAction(lambda s, l, t: ['ref']) \
+ White().suppress() + identifier
pattern_with_space = Combine((Literal('#') | Literal('\\')).suppress() + 'ref') + White().suppress() + identifier
parse(string, pattern_without_space)
parse(string, pattern_with_space)
will output:
[['ref', 'to_something']]
['With', 'ref', 'to_something', '']
[['ref', 'to_something']]
['With ', 'ref', 'to_something', '']
# ^ space i need is preserved here
The problem happens when using alternation (the | operator) with CaselessKeyword. See these examples:
from pyparsing import *
theString = 'This is #Foo Bar'
identifier = Combine(Word(alphas + '_', alphanums + '_') + Optional('.' + Word(alphas)))
def testParser(p):
q = StringStart() + SkipTo(p)("previous") + p("body") + SkipTo(StringEnd())("rest")
return q.parseString(theString)
def test7():
p0 = (CaselessKeyword('#Foo') | Literal('#qwe')) + White().suppress() + identifier
p1 = (CaselessKeyword('#Foo') | CaselessKeyword('#qwe')) + White().suppress() + identifier
p2 = (Literal('#qwe') | CaselessKeyword('#Foo')) + White().suppress() + identifier
p3 = (CaselessKeyword('#Foo')) + White().suppress() + identifier
p4 = Combine((Literal('#') | Literal('\\')).suppress() + 'Foo') + White().suppress() + identifier
print "p0:", testParser(p0)
print "p1:", testParser(p1)
print "p2:", testParser(p2)
print "p3:", testParser(p3)
print "p4:", testParser(p4)
test7()
The output is:
p0: ['This is', '#Foo', 'Bar', '']
p1: ['This is', '#Foo', 'Bar', '']
p2: ['This is', '#Foo', 'Bar', '']
p3: ['This is ', '#Foo', 'Bar', '']
p4: ['This is ', 'Foo', 'Bar', '']
Perhaps this is a bug?
Update: This is how you could define your own parser to match either #Foo or \Foo as a keyword:
from pyparsing import *
import string
class FooKeyWord(Token):
alphas = string.ascii_lowercase + string.ascii_uppercase
nums = "0123456789"
alphanums = alphas + nums
def __init__(self):
super(FooKeyWord,self).__init__()
self.identChars = alphanums+"_$"
self.name = "#Foo"
def parseImpl(self, instring, loc, doActions = True):
if (instring[loc] in ['#', '\\'] and
instring.startswith('Foo', loc+1) and
(loc+4 >= len(instring) or instring[loc+4] not in self.identChars) and
(loc == 0 or instring[loc-1].upper() not in self.identChars)):
return loc+4, instring[loc] + 'Foo'
raise ParseException(instring, loc, self.errmsg, self)
def test8():
p = FooKeyWord() + White().suppress() + identifier
q = StringStart() + SkipTo(p)("previous") + p("body") + SkipTo(StringEnd())("rest")
print "with #Foo:", q.parseString("This is #Foo Bar")
print "with \\Foo:", q.parseString("This is \\Foo Bar")
And the output:
with #Foo: ['This is ', '#Foo', 'Bar', '']
with \Foo: ['This is ', '\\Foo', 'Bar', '']

Categories