Anup (OpenERP) has proposed merging
lp:~openerp-commiter/openobject-client/trunk-ach-branch into
lp:openobject-client.
Requested reviews:
Olivier Dony (OpenERP) (odo)
OpenERP sa GTK client R&D (openerp-dev-gtk)
Related bugs:
#491817 support for 'or' in attrs keyword
https://bugs.launchpad.net/bugs/491817
Hello
This branch contains the changes in the existing parser of attrs.
It contains the newly created logic which works according to the standard
parsing for pre order notation using stack.
The new parser is faster, efficient and fulfilling all the required
conditions.
Thanks
--
https://code.launchpad.net/~openerp-commiter/openobject-client/trunk-ach-branch/+merge/42617
Your team OpenERP sa GTK client R&D is requested to review the proposed merge
of lp:~openerp-commiter/openobject-client/trunk-ach-branch into
lp:openobject-client.
=== modified file 'bin/tools/__init__.py'
--- bin/tools/__init__.py 2010-10-12 16:53:15 +0000
+++ bin/tools/__init__.py 2010-12-03 13:01:00 +0000
@@ -20,6 +20,7 @@
##############################################################################
import datetime
+import operator
import logging
import locale
import os
@@ -80,38 +81,77 @@
return attrs
#FIXME use spaces
-def calc_condition(self,model,con):
- if model and (con[0] in model.mgroup.fields):
- val = model[con[0]].get(model)
- if con[1]=="=" or con[1]=="==":
- if val==con[2]:
- return True
- elif con[1]=="!=" or con[1]=="<>":
- if val!=con[2]:
- return True
- elif con[1]=="<":
- if val<con[2]:
- return True
- elif con[1]==">":
- if val>con[2]:
- return True
- elif con[1]=="<=":
- if val<=con[2]:
- return True
- elif con[1]==">=":
- if val>=con[2]:
- return True
- elif con[1].lower()=="in":
- for cond in con[2]:
- if val == cond:
+def calc_condition(self, model, cond):
+ cond_main = cond[:]
+ try:
+ return ConditionExpr(cond).eval(model)
+ except:
+ import common
+ common.error('Wrong attrs Implementation!','You have wrongly specified conditions in attrs %s' %(cond_main,))
+
+class ConditionExpr(object):
+
+ OPERAND_MAPPER = {'<>': '!=', '==': '='}
+
+ def __init__(self, condition):
+ self.cond = condition
+
+ def eval(self, model):
+ if model:
+ eval_stack = [] # Stack used for evaluation
+ ops = ['=','!=','<','>','<=','>=','in','not in','<>','==']
+
+ def is_operand(cond): # Method to check the Operands
+ if (len(cond)==3 and cond[1] in ops) or isinstance(cond,bool):
return True
- elif con[1].lower()=="not in":
- for cond in con[2]:
- if val == cond:
+ else:
return False
- return True
- return False
+
+ def evaluate(cond): # Method to evaluate the conditions
+ if isinstance(cond,bool):
+ return cond
+ left, oper, right = cond
+ oper = self.OPERAND_MAPPER.get(oper.lower(), oper)
+ if oper == '=':
+ res = operator.eq(model[left].get(model),right)
+ elif oper == '!=':
+ res = operator.ne(model[left].get(model),right)
+ elif oper == '<':
+ res = operator.lt(model[left].get(model),right)
+ elif oper == '>':
+ res = operator.gt(model[left].get(model),right)
+ elif oper == '<=':
+ res = operator.le(model[left].get(model),right)
+ elif oper == '>=':
+ res = operator.ge(model[left].get(model),right)
+ elif oper == 'in':
+ res = operator.contains(right, model[left].get(model))
+ elif oper == 'not in':
+ res = operator.contains(right, model[left].get(model))
+ res = operator.not_(res)
+ return res
+ orig_stack = self.cond
+ orig_stack.reverse()
+ for condition in orig_stack:
+ if is_operand(condition): # If operand Push on Stack
+ eval_stack.append(condition)
+ elif condition in ['|','&','!']: # If operator pop necessary operands from stack and evaluate and store the result back to stack
+ if condition in ('|','&'):
+ elem_1 = eval_stack.pop()
+ elem_2 = eval_stack.pop()
+ if condition=='|':
+ result = any((evaluate(elem_1), evaluate(elem_2)))
+ else:
+ result = all((evaluate(elem_1), evaluate(elem_2)))
+ elif condition == '!':
+ elem_1 = eval_stack.pop()
+ result = not evaluate(elem_1)
+ eval_stack.append(result)
+
+ res = all(evaluate(expr) for expr in eval_stack) # evaluate all the remaining elments if any
+ return res
+
def call_log(fun):
"""Debug decorator
TODO: Add optionnal execution time
=== modified file 'bin/widget/model/field.py'
--- bin/widget/model/field.py 2010-11-16 13:11:20 +0000
+++ bin/widget/model/field.py 2010-12-03 13:01:00 +0000
@@ -138,8 +138,7 @@
attrs_changes[k][i]=cond
for k,v in attrs_changes.items():
result = True
- for condition in v:
- result = result and tools.calc_condition(self,model,condition)
+ result = tools.calc_condition(self, model, v)
if result:
self.get_state_attrs(model)[k]=True
=== modified file 'bin/widget/view/form.py'
--- bin/widget/view/form.py 2010-12-03 09:31:10 +0000
+++ bin/widget/view/form.py 2010-12-03 13:01:00 +0000
@@ -353,9 +353,7 @@
cond=v[i][0],v[i][1],v[i][2][0]
attrs_changes[k][i]=cond
for k,v in attrs_changes.items():
- result = True
- for condition in v:
- result = result and tools.calc_condition(self,model,condition)
+ result = tools.calc_condition(self, model, v)
if result:
if k=='invisible':
obj.hide()
=== modified file 'bin/widget/view/form_gtk/parser.py'
--- bin/widget/view/form_gtk/parser.py 2010-11-10 12:47:34 +0000
+++ bin/widget/view/form_gtk/parser.py 2010-12-03 13:01:00 +0000
@@ -152,9 +152,7 @@
attrs_changes = eval(sa.get('attrs',"{}"),{'uid':rpc.session.uid})
for k,v in attrs_changes.items():
result = True
- for condition in v:
- result = result and tools.calc_condition(self,model,condition)
-
+ result = result and tools.calc_condition(self, model, v)
if k == 'invisible':
func = ['show', 'hide'][bool(result)]
getattr(self.widget, func)()
@@ -214,7 +212,7 @@
def create_label(self, name, markup=False, align=1.0, wrap=False,
angle=None, width=None, fname=None, help=None, detail_tooltip=False):
-
+
label = gtk.Label(name)
eb = gtk.EventBox()
eb.set_events(gtk.gdk.BUTTON_PRESS_MASK)
@@ -222,12 +220,11 @@
label.set_use_markup(True)
self.trans_box_label.append((eb, name, fname))
eb.add(label)
-
+
def size_allocate(label, allocation):
label.set_size_request( allocation.width - 2, -1 )
if fname is None and name and len(name) > 50:
label.connect( "size-allocate", size_allocate )
-
uid = rpc.session.uid
tooltip = ''
if help:
@@ -399,13 +396,13 @@
visval = eval(attrs['invisible'], {'context':self.screen.context})
if visval:
continue
-
+
if 'default_focus' in attrs and not self.default_focus_button:
attrs['focus_button'] = attrs['default_focus']
self.default_focus_button = True
-
+
button = Button(attrs)
-
+
states = [e for e in attrs.get('states','').split(',') if e]
saw_list.append(StateAwareWidget(button, states=states))
container.wid_add(button.widget, colspan=int(attrs.get('colspan', 1)))
=== modified file 'bin/widget/view/list.py'
--- bin/widget/view/list.py 2010-12-03 11:17:56 +0000
+++ bin/widget/view/list.py 2010-12-03 13:01:00 +0000
@@ -474,8 +474,7 @@
attrs_changes = eval(path.attrs.get('attrs',"{}"),{'uid':rpc.session.uid})
for k,v in attrs_changes.items():
result = True
- for condition in v:
- result = tools.calc_condition(self,model,condition)
+ result = tools.calc_condition(self,model,v)
if result:
if k=='invisible':
return False
=== modified file 'bin/widget/view/tree_gtk/parser.py'
--- bin/widget/view/tree_gtk/parser.py 2010-11-26 11:24:56 +0000
+++ bin/widget/view/tree_gtk/parser.py 2010-12-03 13:01:00 +0000
@@ -245,8 +245,7 @@
attrs_changes = eval(self.attrs.get('attrs',"{}"),{'uid':rpc.session.uid})
for k,v in attrs_changes.items():
result = False
- for condition in v:
- result = tools.calc_condition(self,model,condition)
+ result = tools.calc_condition(self,model,v)
model[self.field_name].get_state_attrs(model)[k] = result
def state_set(self, model, state='draft'):
@@ -657,8 +656,7 @@
attrs_changes = eval(self.attrs.get('attrs',"{}"),{'uid':rpc.session.uid})
for k,v in attrs_changes.items():
result = False
- for condition in v:
- result = tools.calc_condition(self,model,condition)
+ result = tools.calc_condition(self,model,v)
if result:
if k == 'invisible':
return 'hide'
_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help : https://help.launchpad.net/ListHelp