[REM] EVALPOCALYPSE PART ONE
bzr revid: xmo@openerp.com-20121126105450-0f6xowd3dhj4jmbl
This commit is contained in:
parent
5939aeb9d0
commit
eb9a1c7d55
|
@ -355,40 +355,15 @@ def set_cookie_and_redirect(req, redirect_url):
|
|||
redirect.set_cookie('instance0|session_id', cookie_val)
|
||||
return redirect
|
||||
|
||||
def eval_context_and_domain(session, context, domain=None):
|
||||
e_context = session.eval_context(context)
|
||||
# should we give the evaluated context as an evaluation context to the domain?
|
||||
e_domain = session.eval_domain(domain or [])
|
||||
|
||||
return e_context, e_domain
|
||||
|
||||
def load_actions_from_ir_values(req, key, key2, models, meta):
|
||||
context = req.session.eval_context(req.context)
|
||||
Values = req.session.model('ir.values')
|
||||
actions = Values.get(key, key2, models, meta, context)
|
||||
actions = Values.get(key, key2, models, meta, req.context)
|
||||
|
||||
return [(id, name, clean_action(req, action))
|
||||
for id, name, action in actions]
|
||||
|
||||
def clean_action(req, action, do_not_eval=False):
|
||||
def clean_action(req, action):
|
||||
action.setdefault('flags', {})
|
||||
|
||||
context = req.session.eval_context(req.context)
|
||||
eval_ctx = req.session.evaluation_context(context)
|
||||
|
||||
if not do_not_eval:
|
||||
# values come from the server, we can just eval them
|
||||
if action.get('context') and isinstance(action.get('context'), basestring):
|
||||
action['context'] = eval( action['context'], eval_ctx ) or {}
|
||||
|
||||
if action.get('domain') and isinstance(action.get('domain'), basestring):
|
||||
action['domain'] = eval( action['domain'], eval_ctx ) or []
|
||||
else:
|
||||
if 'context' in action:
|
||||
action['context'] = parse_context(action['context'], req.session)
|
||||
if 'domain' in action:
|
||||
action['domain'] = parse_domain(action['domain'], req.session)
|
||||
|
||||
action_type = action.setdefault('type', 'ir.actions.act_window_close')
|
||||
if action_type == 'ir.actions.act_window':
|
||||
return fix_view_modes(action)
|
||||
|
@ -905,7 +880,7 @@ class Session(openerpweb.Controller):
|
|||
@openerpweb.jsonrequest
|
||||
def sc_list(self, req):
|
||||
return req.session.model('ir.ui.view_sc').get_sc(
|
||||
req.session._uid, "ir.ui.menu", req.session.eval_context(req.context))
|
||||
req.session._uid, "ir.ui.menu", req.context)
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get_lang_list(self, req):
|
||||
|
@ -988,18 +963,19 @@ class Menu(openerpweb.Controller):
|
|||
:rtype: list(int)
|
||||
"""
|
||||
s = req.session
|
||||
context = s.eval_context(req.context)
|
||||
Menus = s.model('ir.ui.menu')
|
||||
# If a menu action is defined use its domain to get the root menu items
|
||||
user_menu_id = s.model('res.users').read([s._uid], ['menu_id'], context)[0]['menu_id']
|
||||
user_menu_id = s.model('res.users').read([s._uid], ['menu_id'],
|
||||
req.context)[0]['menu_id']
|
||||
|
||||
menu_domain = [('parent_id', '=', False)]
|
||||
if user_menu_id:
|
||||
domain_string = s.model('ir.actions.act_window').read([user_menu_id[0]], ['domain'], context)[0]['domain']
|
||||
domain_string = s.model('ir.actions.act_window').read([user_menu_id[0]], ['domain'],
|
||||
req.context)[0]['domain']
|
||||
if domain_string:
|
||||
menu_domain = ast.literal_eval(domain_string)
|
||||
|
||||
return Menus.search(menu_domain, 0, False, False, context)
|
||||
return Menus.search(menu_domain, 0, False, False, req.context)
|
||||
|
||||
def do_load(self, req):
|
||||
""" Loads all menu items (all applications and their sub-menus).
|
||||
|
@ -1009,23 +985,30 @@ class Menu(openerpweb.Controller):
|
|||
:return: the menu root
|
||||
:rtype: dict('children': menu_nodes)
|
||||
"""
|
||||
context = req.session.eval_context(req.context)
|
||||
Menus = req.session.model('ir.ui.menu')
|
||||
|
||||
menu_roots = Menus.read(self.do_get_user_roots(req), ['name', 'sequence', 'parent_id', 'action', 'needaction_enabled', 'needaction_counter'], context)
|
||||
menu_root = {'id': False, 'name': 'root', 'parent_id': [-1, ''], 'children' : menu_roots}
|
||||
fields = ['name', 'sequence', 'parent_id', 'action',
|
||||
'needaction_enabled', 'needaction_counter']
|
||||
menu_roots = Menus.read(self.do_get_user_roots(req), fields, req.context)
|
||||
menu_root = {
|
||||
'id': False,
|
||||
'name': 'root',
|
||||
'parent_id': [-1, ''],
|
||||
'children': menu_roots
|
||||
}
|
||||
|
||||
# menus are loaded fully unlike a regular tree view, cause there are a
|
||||
# limited number of items (752 when all 6.1 addons are installed)
|
||||
menu_ids = Menus.search([], 0, False, False, context)
|
||||
menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id', 'action', 'needaction_enabled', 'needaction_counter'], context)
|
||||
menu_ids = Menus.search([], 0, False, False, req.context)
|
||||
menu_items = Menus.read(menu_ids, fields, req.context)
|
||||
# adds roots at the end of the sequence, so that they will overwrite
|
||||
# equivalent menu items from full menu read when put into id:item
|
||||
# mapping, resulting in children being correctly set on the roots.
|
||||
menu_items.extend(menu_roots)
|
||||
|
||||
# make a tree using parent_id
|
||||
menu_items_map = dict((menu_item["id"], menu_item) for menu_item in menu_items)
|
||||
menu_items_map = dict(
|
||||
(menu_item["id"], menu_item) for menu_item in menu_items)
|
||||
for menu_item in menu_items:
|
||||
if menu_item['parent_id']:
|
||||
parent = menu_item['parent_id'][0]
|
||||
|
@ -1075,12 +1058,10 @@ class DataSet(openerpweb.Controller):
|
|||
"""
|
||||
Model = req.session.model(model)
|
||||
|
||||
context, domain = eval_context_and_domain(
|
||||
req.session, req.context, domain)
|
||||
|
||||
ids = Model.search(domain, offset or 0, limit or False, sort or False, context)
|
||||
ids = Model.search(domain, offset or 0, limit or False, sort or False,
|
||||
req.context)
|
||||
if limit and len(ids) == limit:
|
||||
length = Model.search_count(domain, context)
|
||||
length = Model.search_count(domain, req.context)
|
||||
else:
|
||||
length = len(ids) + (offset or 0)
|
||||
if fields and fields == ['id']:
|
||||
|
@ -1090,7 +1071,7 @@ class DataSet(openerpweb.Controller):
|
|||
'records': [{'id': id} for id in ids]
|
||||
}
|
||||
|
||||
records = Model.read(ids, fields or False, context)
|
||||
records = Model.read(ids, fields or False, req.context)
|
||||
records.sort(key=lambda obj: ids.index(obj['id']))
|
||||
return {
|
||||
'length': length,
|
||||
|
@ -1101,37 +1082,15 @@ class DataSet(openerpweb.Controller):
|
|||
def load(self, req, model, id, fields):
|
||||
m = req.session.model(model)
|
||||
value = {}
|
||||
r = m.read([id], False, req.session.eval_context(req.context))
|
||||
r = m.read([id], False, req.context)
|
||||
if r:
|
||||
value = r[0]
|
||||
return {'value': value}
|
||||
|
||||
def call_common(self, req, model, method, args, domain_id=None, context_id=None):
|
||||
has_domain = domain_id is not None and domain_id < len(args)
|
||||
has_context = context_id is not None and context_id < len(args)
|
||||
|
||||
domain = args[domain_id] if has_domain else []
|
||||
context = args[context_id] if has_context else {}
|
||||
c, d = eval_context_and_domain(req.session, context, domain)
|
||||
if has_domain:
|
||||
args[domain_id] = d
|
||||
if has_context:
|
||||
args[context_id] = c
|
||||
|
||||
return self._call_kw(req, model, method, args, {})
|
||||
|
||||
def _call_kw(self, req, model, method, args, kwargs):
|
||||
for i in xrange(len(args)):
|
||||
if isinstance(args[i], nonliterals.BaseContext):
|
||||
args[i] = req.session.eval_context(args[i])
|
||||
elif isinstance(args[i], nonliterals.BaseDomain):
|
||||
args[i] = req.session.eval_domain(args[i])
|
||||
for k in kwargs.keys():
|
||||
if isinstance(kwargs[k], nonliterals.BaseContext):
|
||||
kwargs[k] = req.session.eval_context(kwargs[k])
|
||||
elif isinstance(kwargs[k], nonliterals.BaseDomain):
|
||||
kwargs[k] = req.session.eval_domain(kwargs[k])
|
||||
|
||||
def _call_kw(self, req, model, method, args, kwargs):
|
||||
# Temporary implements future display_name special field for model#read()
|
||||
if method == 'read' and kwargs.get('context') and kwargs['context'].get('future_display_name'):
|
||||
if 'display_name' in args[1]:
|
||||
|
@ -1164,19 +1123,11 @@ class DataSet(openerpweb.Controller):
|
|||
arguments
|
||||
:return: result of the onchange call with all domains parsed
|
||||
"""
|
||||
result = self.call_common(req, model, method, args, context_id=context_id)
|
||||
if not result or 'domain' not in result:
|
||||
return result
|
||||
|
||||
result['domain'] = dict(
|
||||
(k, parse_domain(v, req.session))
|
||||
for k, v in result['domain'].iteritems())
|
||||
|
||||
return result
|
||||
return self._call_kw(req, model, method, args, {})
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def call(self, req, model, method, args, domain_id=None, context_id=None):
|
||||
return self.call_common(req, model, method, args, domain_id, context_id)
|
||||
return self._call_kw(req, model, method, args, {})
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def call_kw(self, req, model, method, args, kwargs):
|
||||
|
@ -1184,7 +1135,7 @@ class DataSet(openerpweb.Controller):
|
|||
|
||||
@openerpweb.jsonrequest
|
||||
def call_button(self, req, model, method, args, domain_id=None, context_id=None):
|
||||
action = self.call_common(req, model, method, args, domain_id, context_id)
|
||||
action = self._call_kw(req, model, method, args, {})
|
||||
if isinstance(action, dict) and action.get('type') != '':
|
||||
return clean_action(req, action)
|
||||
return False
|
||||
|
@ -1222,10 +1173,9 @@ class View(openerpweb.Controller):
|
|||
def fields_view_get(self, req, model, view_id, view_type,
|
||||
transform=True, toolbar=False, submenu=False):
|
||||
Model = req.session.model(model)
|
||||
context = req.session.eval_context(req.context)
|
||||
fvg = Model.fields_view_get(view_id, view_type, context, toolbar, submenu)
|
||||
fvg = Model.fields_view_get(view_id, view_type, req.context, toolbar, submenu)
|
||||
# todo fme?: check that we should pass the evaluated context here
|
||||
self.process_view(req.session, fvg, context, transform, (view_type == 'kanban'))
|
||||
self.process_view(req.session, fvg, req.context, transform, (view_type == 'kanban'))
|
||||
if toolbar and transform:
|
||||
self.process_toolbar(req, fvg['toolbar'])
|
||||
return fvg
|
||||
|
@ -1289,20 +1239,19 @@ class View(openerpweb.Controller):
|
|||
'user_id': req.session._uid,
|
||||
'ref_id': view_id,
|
||||
'arch': arch
|
||||
}, req.session.eval_context(req.context))
|
||||
}, req.context)
|
||||
return {'result': True}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def undo_custom(self, req, view_id, reset=False):
|
||||
CustomView = req.session.model('ir.ui.view.custom')
|
||||
context = req.session.eval_context(req.context)
|
||||
vcustom = CustomView.search([('user_id', '=', req.session._uid), ('ref_id' ,'=', view_id)],
|
||||
0, False, False, context)
|
||||
0, False, False, req.context)
|
||||
if vcustom:
|
||||
if reset:
|
||||
CustomView.unlink(vcustom, context)
|
||||
CustomView.unlink(vcustom, req.context)
|
||||
else:
|
||||
CustomView.unlink([vcustom[0]], context)
|
||||
CustomView.unlink([vcustom[0]], req.context)
|
||||
return {'result': True}
|
||||
return {'result': False}
|
||||
|
||||
|
@ -1353,50 +1302,6 @@ class TreeView(View):
|
|||
req,'action', 'tree_but_open',[(model, id)],
|
||||
False)
|
||||
|
||||
class SearchView(View):
|
||||
_cp_path = "/web/searchview"
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def load(self, req, model, view_id):
|
||||
fields_view = self.fields_view_get(req, model, view_id, 'search')
|
||||
return {'fields_view': fields_view}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def fields_get(self, req, model):
|
||||
Model = req.session.model(model)
|
||||
fields = Model.fields_get(False, req.session.eval_context(req.context))
|
||||
for field in fields.values():
|
||||
# shouldn't convert the views too?
|
||||
if field.get('domain'):
|
||||
field["domain"] = parse_domain(field["domain"], req.session)
|
||||
if field.get('context'):
|
||||
field["context"] = parse_context(field["context"], req.session)
|
||||
return {'fields': fields}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get_filters(self, req, model):
|
||||
logger = logging.getLogger(__name__ + '.SearchView.get_filters')
|
||||
Model = req.session.model("ir.filters")
|
||||
filters = Model.get_filters(model)
|
||||
for filter in filters:
|
||||
try:
|
||||
parsed_context = parse_context(filter["context"], req.session)
|
||||
filter["context"] = (parsed_context
|
||||
if not isinstance(parsed_context, nonliterals.BaseContext)
|
||||
else req.session.eval_context(parsed_context))
|
||||
|
||||
parsed_domain = parse_domain(filter["domain"], req.session)
|
||||
filter["domain"] = (parsed_domain
|
||||
if not isinstance(parsed_domain, nonliterals.BaseDomain)
|
||||
else req.session.eval_domain(parsed_domain))
|
||||
except Exception:
|
||||
logger.exception("Failed to parse custom filter %s in %s",
|
||||
filter['name'], model)
|
||||
filter['disabled'] = True
|
||||
del filter['context']
|
||||
del filter['domain']
|
||||
return filters
|
||||
|
||||
class Binary(openerpweb.Controller):
|
||||
_cp_path = "/web/binary"
|
||||
|
||||
|
@ -1404,7 +1309,6 @@ class Binary(openerpweb.Controller):
|
|||
def image(self, req, model, id, field, **kw):
|
||||
last_update = '__last_update'
|
||||
Model = req.session.model(model)
|
||||
context = req.session.eval_context(req.context)
|
||||
headers = [('Content-Type', 'image/png')]
|
||||
etag = req.httprequest.headers.get('If-None-Match')
|
||||
hashed_session = hashlib.md5(req.session_id).hexdigest()
|
||||
|
@ -1415,22 +1319,22 @@ class Binary(openerpweb.Controller):
|
|||
if not id and hashed_session == etag:
|
||||
return werkzeug.wrappers.Response(status=304)
|
||||
else:
|
||||
date = Model.read([id], [last_update], context)[0].get(last_update)
|
||||
date = Model.read([id], [last_update], req.context)[0].get(last_update)
|
||||
if hashlib.md5(date).hexdigest() == etag:
|
||||
return werkzeug.wrappers.Response(status=304)
|
||||
|
||||
retag = hashed_session
|
||||
try:
|
||||
if not id:
|
||||
res = Model.default_get([field], context).get(field)
|
||||
res = Model.default_get([field], req.context).get(field)
|
||||
image_base64 = res
|
||||
else:
|
||||
res = Model.read([id], [last_update, field], context)[0]
|
||||
res = Model.read([id], [last_update, field], req.context)[0]
|
||||
retag = hashlib.md5(res.get(last_update)).hexdigest()
|
||||
image_base64 = res.get(field)
|
||||
|
||||
if kw.get('resize'):
|
||||
resize = kw.get('resize').split(',');
|
||||
resize = kw.get('resize').split(',')
|
||||
if len(resize) == 2 and int(resize[0]) and int(resize[1]):
|
||||
width = int(resize[0])
|
||||
height = int(resize[1])
|
||||
|
@ -1472,14 +1376,13 @@ class Binary(openerpweb.Controller):
|
|||
:returns: :class:`werkzeug.wrappers.Response`
|
||||
"""
|
||||
Model = req.session.model(model)
|
||||
context = req.session.eval_context(req.context)
|
||||
fields = [field]
|
||||
if filename_field:
|
||||
fields.append(filename_field)
|
||||
if id:
|
||||
res = Model.read([int(id)], fields, context)[0]
|
||||
res = Model.read([int(id)], fields, req.context)[0]
|
||||
else:
|
||||
res = Model.default_get(fields, context)
|
||||
res = Model.default_get(fields, req.context)
|
||||
filecontent = base64.b64decode(res.get(field, ''))
|
||||
if not filecontent:
|
||||
return req.not_found()
|
||||
|
@ -1498,9 +1401,8 @@ class Binary(openerpweb.Controller):
|
|||
field = jdata['field']
|
||||
id = jdata.get('id', None)
|
||||
filename_field = jdata.get('filename_field', None)
|
||||
context = jdata.get('context', dict())
|
||||
context = jdata.get('context', {})
|
||||
|
||||
context = req.session.eval_context(context)
|
||||
Model = req.session.model(model)
|
||||
fields = [field]
|
||||
if filename_field:
|
||||
|
@ -1539,7 +1441,6 @@ class Binary(openerpweb.Controller):
|
|||
|
||||
@openerpweb.httprequest
|
||||
def upload_attachment(self, req, callback, model, id, ufile):
|
||||
context = req.session.eval_context(req.context)
|
||||
Model = req.session.model('ir.attachment')
|
||||
try:
|
||||
out = """<script language="javascript" type="text/javascript">
|
||||
|
@ -1552,7 +1453,7 @@ class Binary(openerpweb.Controller):
|
|||
'datas_fname': ufile.filename,
|
||||
'res_model': model,
|
||||
'res_id': int(id)
|
||||
}, context)
|
||||
}, req.context)
|
||||
args = {
|
||||
'filename': ufile.filename,
|
||||
'id': attachment_id
|
||||
|
@ -1568,8 +1469,6 @@ class Action(openerpweb.Controller):
|
|||
def load(self, req, action_id, do_not_eval=False):
|
||||
Actions = req.session.model('ir.actions.actions')
|
||||
value = False
|
||||
context = req.session.eval_context(req.context)
|
||||
|
||||
try:
|
||||
action_id = int(action_id)
|
||||
except ValueError:
|
||||
|
@ -1580,13 +1479,13 @@ class Action(openerpweb.Controller):
|
|||
except Exception:
|
||||
action_id = 0 # force failed read
|
||||
|
||||
base_action = Actions.read([action_id], ['type'], context)
|
||||
base_action = Actions.read([action_id], ['type'], req.context)
|
||||
if base_action:
|
||||
ctx = {}
|
||||
action_type = base_action[0]['type']
|
||||
if action_type == 'ir.actions.report.xml':
|
||||
ctx.update({'bin_size': True})
|
||||
ctx.update(context)
|
||||
ctx.update(req.context)
|
||||
action = req.session.model(action_type).read([action_id], False, ctx)
|
||||
if action:
|
||||
value = clean_action(req, action[0], do_not_eval)
|
||||
|
@ -1595,7 +1494,7 @@ class Action(openerpweb.Controller):
|
|||
@openerpweb.jsonrequest
|
||||
def run(self, req, action_id):
|
||||
return_action = req.session.model('ir.actions.server').run(
|
||||
[action_id], req.session.eval_context(req.context))
|
||||
[action_id], req.context)
|
||||
if return_action:
|
||||
return clean_action(req, return_action)
|
||||
else:
|
||||
|
@ -1620,7 +1519,7 @@ class Export(View):
|
|||
|
||||
def fields_get(self, req, model):
|
||||
Model = req.session.model(model)
|
||||
fields = Model.fields_get(False, req.session.eval_context(req.context))
|
||||
fields = Model.fields_get(False, req.context)
|
||||
return fields
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
|
@ -1770,12 +1669,11 @@ class Export(View):
|
|||
'import_compat')(
|
||||
simplejson.loads(data))
|
||||
|
||||
context = req.session.eval_context(req.context)
|
||||
Model = req.session.model(model)
|
||||
ids = ids or Model.search(domain, 0, False, False, context)
|
||||
ids = ids or Model.search(domain, 0, False, False, req.context)
|
||||
|
||||
field_names = map(operator.itemgetter('name'), fields)
|
||||
import_data = Model.export_data(ids, field_names, context).get('datas',[])
|
||||
import_data = Model.export_data(ids, field_names, req.context).get('datas',[])
|
||||
|
||||
if import_compat:
|
||||
columns_headers = field_names
|
||||
|
@ -1880,9 +1778,8 @@ class Reports(View):
|
|||
action = simplejson.loads(action)
|
||||
|
||||
report_srv = req.session.proxy("report")
|
||||
context = req.session.eval_context(
|
||||
nonliterals.CompoundContext(
|
||||
req.context or {}, action[ "context"]))
|
||||
context = dict(req.context)
|
||||
context.update(action["context"])
|
||||
|
||||
report_data = {}
|
||||
report_ids = context["active_ids"]
|
||||
|
|
|
@ -100,7 +100,7 @@ class WebRequest(object):
|
|||
# Determine self.lang
|
||||
lang = self.params.get('lang', None)
|
||||
if lang is None:
|
||||
lang = self.session.eval_context(self.context).get('lang')
|
||||
lang = self.context.get('lang')
|
||||
if lang is None:
|
||||
lang = self.httprequest.cookies.get('lang')
|
||||
if lang is None:
|
||||
|
@ -402,8 +402,10 @@ def session_context(request, session_store, session_lock, sid):
|
|||
for k, v in request.session.iteritems():
|
||||
stored = in_store.get(k)
|
||||
if stored and isinstance(v, session.OpenERPSession):
|
||||
v.contexts_store.update(stored.contexts_store)
|
||||
v.domains_store.update(stored.domains_store)
|
||||
if hasattr(v, 'contexts_store'):
|
||||
del v.contexts_store
|
||||
if hasattr(v, 'domains_store'):
|
||||
del v.domains_store
|
||||
if not hasattr(v, 'jsonp_requests'):
|
||||
v.jsonp_requests = {}
|
||||
v.jsonp_requests.update(getattr(
|
||||
|
|
|
@ -4,16 +4,10 @@
|
|||
but still need to be safely round-tripped to and from the browser (and thus
|
||||
can't be sent there themselves).
|
||||
"""
|
||||
import binascii
|
||||
import hashlib
|
||||
import simplejson.encoder
|
||||
|
||||
__all__ = ['Domain', 'Context', 'NonLiteralEncoder', 'non_literal_decoder', 'CompoundDomain', 'CompoundContext']
|
||||
|
||||
#: 48 bits should be sufficient to have almost no chance of collision
|
||||
#: with a million hashes, according to hg@67081329d49a
|
||||
SHORT_HASH_BYTES_SIZE = 6
|
||||
|
||||
class NonLiteralEncoder(simplejson.encoder.JSONEncoder):
|
||||
def default(self, object):
|
||||
if not isinstance(object, (BaseDomain, BaseContext)):
|
||||
|
@ -21,56 +15,19 @@ class NonLiteralEncoder(simplejson.encoder.JSONEncoder):
|
|||
if isinstance(object, Domain):
|
||||
return {
|
||||
'__ref': 'domain',
|
||||
'__id': object.key,
|
||||
'__debug': object.get_domain_string()
|
||||
'__debug': object.domain_string
|
||||
}
|
||||
elif isinstance(object, Context):
|
||||
return {
|
||||
'__ref': 'context',
|
||||
'__id': object.key,
|
||||
'__debug': object.get_context_string()
|
||||
}
|
||||
elif isinstance(object, CompoundDomain):
|
||||
return {
|
||||
'__ref': 'compound_domain',
|
||||
'__domains': object.domains,
|
||||
'__eval_context': object.get_eval_context()
|
||||
}
|
||||
elif isinstance(object, CompoundContext):
|
||||
return {
|
||||
'__ref': 'compound_context',
|
||||
'__contexts': object.contexts,
|
||||
'__eval_context': object.get_eval_context()
|
||||
'__debug': object.context_string
|
||||
}
|
||||
raise TypeError('Could not encode unknown non-literal %s' % object)
|
||||
|
||||
_ALLOWED_KEYS = frozenset(['__ref', "__id", '__domains', '__debug',
|
||||
'__contexts', '__eval_context'])
|
||||
|
||||
def non_literal_decoder(dct):
|
||||
""" Decodes JSON dicts into :class:`Domain` and :class:`Context` based on
|
||||
magic attribute tags.
|
||||
"""
|
||||
if '__ref' in dct:
|
||||
for x in dct:
|
||||
if x not in _ALLOWED_KEYS:
|
||||
raise ValueError("'%s' key not allowed in non literal domain/context" % x)
|
||||
if dct['__ref'] == 'domain':
|
||||
return Domain(None, key=dct['__id'])
|
||||
elif dct['__ref'] == 'context':
|
||||
return Context(None, key=dct['__id'])
|
||||
elif dct["__ref"] == "compound_domain":
|
||||
cdomain = CompoundDomain()
|
||||
for el in dct["__domains"]:
|
||||
cdomain.domains.append(el)
|
||||
cdomain.set_eval_context(dct.get("__eval_context"))
|
||||
return cdomain
|
||||
elif dct["__ref"] == "compound_context":
|
||||
ccontext = CompoundContext()
|
||||
for el in dct["__contexts"]:
|
||||
ccontext.contexts.append(el)
|
||||
ccontext.set_eval_context(dct.get("__eval_context"))
|
||||
return ccontext
|
||||
raise ValueError(
|
||||
"Non literal contexts can not be sent to the server anymore (%r)" % (dct,))
|
||||
return dct
|
||||
|
||||
# TODO: use abstract base classes if 2.6+?
|
||||
|
@ -83,7 +40,7 @@ class BaseContext(object):
|
|||
raise NotImplementedError('Non literals must implement evaluate()')
|
||||
|
||||
class Domain(BaseDomain):
|
||||
def __init__(self, session, domain_string=None, key=None):
|
||||
def __init__(self, session, domain_string):
|
||||
""" Uses session information to store the domain string and map it to a
|
||||
domain key, which can be safely round-tripped to the client.
|
||||
|
||||
|
@ -95,25 +52,9 @@ class Domain(BaseDomain):
|
|||
:param session: the OpenERP Session to use when evaluating the domain
|
||||
:type session: web.common.session.OpenERPSession
|
||||
:param str domain_string: a non-literal domain in string form
|
||||
:param str key: key used to retrieve the domain string
|
||||
"""
|
||||
if domain_string and key:
|
||||
raise ValueError("A nonliteral domain can not take both a key "
|
||||
"and a domain string")
|
||||
|
||||
self.session = session
|
||||
if domain_string:
|
||||
self.key = binascii.hexlify(
|
||||
hashlib.sha256(domain_string).digest()[:SHORT_HASH_BYTES_SIZE])
|
||||
self.session.domains_store[self.key] = domain_string
|
||||
elif key:
|
||||
self.key = key
|
||||
|
||||
def get_domain_string(self):
|
||||
""" Retrieves the domain string linked to this non-literal domain in
|
||||
the provided session.
|
||||
"""
|
||||
return self.session.domains_store[self.key]
|
||||
self.domain_string = domain_string
|
||||
|
||||
def evaluate(self, context=None):
|
||||
""" Forces the evaluation of the linked domain, using the provided
|
||||
|
@ -123,12 +64,12 @@ class Domain(BaseDomain):
|
|||
ctx = self.session.evaluation_context(context)
|
||||
|
||||
try:
|
||||
return eval(self.get_domain_string(), SuperDict(ctx))
|
||||
return eval(self.domain_string, SuperDict(ctx))
|
||||
except NameError as e:
|
||||
raise ValueError('Error during evaluation of this domain: "%s", message: "%s"' % (self.get_domain_string(), e.message))
|
||||
raise ValueError('Error during evaluation of this domain: "%s", message: "%s"' % (self.domain_string, e.message))
|
||||
|
||||
class Context(BaseContext):
|
||||
def __init__(self, session, context_string=None, key=None):
|
||||
def __init__(self, session, context_string):
|
||||
""" Uses session information to store the context string and map it to
|
||||
a key (stored in a secret location under a secret mountain), which can
|
||||
be safely round-tripped to the client.
|
||||
|
@ -141,26 +82,9 @@ class Context(BaseContext):
|
|||
:param session: the OpenERP Session to use when evaluating the context
|
||||
:type session: web.common.session.OpenERPSession
|
||||
:param str context_string: a non-literal context in string form
|
||||
:param str key: key used to retrieve the context string
|
||||
"""
|
||||
if context_string and key:
|
||||
raise ValueError("A nonliteral domain can not take both a key "
|
||||
"and a domain string")
|
||||
|
||||
self.session = session
|
||||
|
||||
if context_string:
|
||||
self.key = binascii.hexlify(
|
||||
hashlib.sha256(context_string).digest()[:SHORT_HASH_BYTES_SIZE])
|
||||
self.session.contexts_store[self.key] = context_string
|
||||
elif key:
|
||||
self.key = key
|
||||
|
||||
def get_context_string(self):
|
||||
""" Retrieves the context string linked to this non-literal context in
|
||||
the provided session.
|
||||
"""
|
||||
return self.session.contexts_store[self.key]
|
||||
self.context_string = context_string
|
||||
|
||||
def evaluate(self, context=None):
|
||||
""" Forces the evaluation of the linked context, using the provided
|
||||
|
@ -170,9 +94,9 @@ class Context(BaseContext):
|
|||
ctx = self.session.evaluation_context(context)
|
||||
|
||||
try:
|
||||
return eval(self.get_context_string(), SuperDict(ctx))
|
||||
return eval(self.context_string, SuperDict(ctx))
|
||||
except NameError as e:
|
||||
raise ValueError('Error during evaluation of this context: "%s", message: "%s"' % (self.get_context_string(), e.message))
|
||||
raise ValueError('Error during evaluation of this context: "%s", message: "%s"' % (self.context_string, e.message))
|
||||
|
||||
class SuperDict(dict):
|
||||
def __getattr__(self, name):
|
||||
|
@ -185,83 +109,3 @@ class SuperDict(dict):
|
|||
if isinstance(tmp, dict):
|
||||
return SuperDict(tmp)
|
||||
return tmp
|
||||
|
||||
class CompoundDomain(BaseDomain):
|
||||
def __init__(self, *domains):
|
||||
self.domains = []
|
||||
self.session = None
|
||||
self.eval_context = None
|
||||
for domain in domains:
|
||||
self.add(domain)
|
||||
|
||||
def evaluate(self, context=None):
|
||||
ctx = dict(context or {})
|
||||
eval_context = self.get_eval_context()
|
||||
if eval_context:
|
||||
eval_context = self.session.eval_context(eval_context)
|
||||
ctx.update(eval_context)
|
||||
final_domain = []
|
||||
for domain in self.domains:
|
||||
if not isinstance(domain, (list, BaseDomain)):
|
||||
raise TypeError(
|
||||
"Domain %r is not a list or a nonliteral Domain" % domain)
|
||||
|
||||
if isinstance(domain, list):
|
||||
final_domain.extend(domain)
|
||||
continue
|
||||
|
||||
domain.session = self.session
|
||||
final_domain.extend(domain.evaluate(ctx))
|
||||
return final_domain
|
||||
|
||||
def add(self, domain):
|
||||
self.domains.append(domain)
|
||||
return self
|
||||
|
||||
def set_eval_context(self, eval_context):
|
||||
self.eval_context = eval_context
|
||||
return self
|
||||
|
||||
def get_eval_context(self):
|
||||
return self.eval_context
|
||||
|
||||
class CompoundContext(BaseContext):
|
||||
def __init__(self, *contexts):
|
||||
self.contexts = []
|
||||
self.eval_context = None
|
||||
self.session = None
|
||||
for context in contexts:
|
||||
self.add(context)
|
||||
|
||||
def evaluate(self, context=None):
|
||||
ctx = dict(context or {})
|
||||
eval_context = self.get_eval_context()
|
||||
if eval_context:
|
||||
eval_context = self.session.eval_context(eval_context)
|
||||
ctx.update(eval_context)
|
||||
final_context = {}
|
||||
for context_to_eval in self.contexts:
|
||||
if not isinstance(context_to_eval, (dict, BaseContext)):
|
||||
raise TypeError(
|
||||
"Context %r is not a dict or a nonliteral Context" % context_to_eval)
|
||||
|
||||
if isinstance(context_to_eval, dict):
|
||||
final_context.update(context_to_eval)
|
||||
continue
|
||||
|
||||
ctx.update(final_context)
|
||||
|
||||
context_to_eval.session = self.session
|
||||
final_context.update(context_to_eval.evaluate(ctx))
|
||||
return final_context
|
||||
|
||||
def add(self, context):
|
||||
self.contexts.append(context)
|
||||
return self
|
||||
|
||||
def set_eval_context(self, eval_context):
|
||||
self.eval_context = eval_context
|
||||
return self
|
||||
|
||||
def get_eval_context(self):
|
||||
return self.eval_context
|
||||
|
|
|
@ -81,8 +81,6 @@ class OpenERPSession(object):
|
|||
self._password = False
|
||||
self._suicide = False
|
||||
self.context = {}
|
||||
self.contexts_store = {}
|
||||
self.domains_store = {}
|
||||
self.jsonp_requests = {} # FIXME use a LRU
|
||||
|
||||
def send(self, service_name, method, *args):
|
||||
|
@ -222,49 +220,4 @@ class OpenERPSession(object):
|
|||
d['context'] = d
|
||||
return d
|
||||
|
||||
def eval_context(self, context_to_eval, context=None):
|
||||
""" Evaluates the provided context_to_eval in the context (haha) of
|
||||
the context. Also merges the evaluated context with the session's context.
|
||||
|
||||
:param context_to_eval: a context to evaluate. Must be a dict or a
|
||||
non-literal context. If it's a dict, will be
|
||||
returned as-is
|
||||
:type context_to_eval: openerpweb.nonliterals.Context
|
||||
:returns: the evaluated context
|
||||
:rtype: dict
|
||||
|
||||
:raises: ``TypeError`` if ``context_to_eval`` is neither a dict nor
|
||||
a Context
|
||||
"""
|
||||
ctx = dict(
|
||||
self.base_eval_context,
|
||||
**(context or {}))
|
||||
|
||||
# adding the context of the session to send to the openerp server
|
||||
ccontext = nonliterals.CompoundContext(self.context, context_to_eval or {})
|
||||
ccontext.session = self
|
||||
return ccontext.evaluate(ctx)
|
||||
|
||||
def eval_domain(self, domain, context=None):
|
||||
""" Evaluates the provided domain using the provided context
|
||||
(merged with the session's evaluation context)
|
||||
|
||||
:param domain: an OpenERP domain as a list or as a
|
||||
:class:`openerpweb.nonliterals.Domain` instance
|
||||
|
||||
In the second case, it will be evaluated and returned.
|
||||
:type domain: openerpweb.nonliterals.Domain
|
||||
:param dict context: the context to use in the evaluation, if any.
|
||||
:returns: the evaluated domain
|
||||
:rtype: list
|
||||
|
||||
:raises: ``TypeError`` if ``domain`` is neither a list nor a Domain
|
||||
"""
|
||||
if isinstance(domain, list):
|
||||
return domain
|
||||
|
||||
cdomain = nonliterals.CompoundDomain(domain)
|
||||
cdomain.session = self
|
||||
return cdomain.evaluate(context or {})
|
||||
|
||||
# vim:et:ts=4:sw=4:
|
||||
|
|
|
@ -878,7 +878,11 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
|
|||
nested: true,
|
||||
}
|
||||
};
|
||||
this.session.get_file({ url: '/web/report', data: {action: JSON.stringify(action)}, complete: instance.web.unblockUI });
|
||||
this.session.get_file({
|
||||
url: '/web/report',
|
||||
data: {action: JSON.stringify(action)},
|
||||
complete: instance.web.unblockUI
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1074,7 +1078,8 @@ instance.web.Sidebar = instance.web.Widget.extend({
|
|||
}, context);
|
||||
self.rpc("/web/action/load", {
|
||||
action_id: item.action.id,
|
||||
context: additional_context
|
||||
context: instance.web.pyeval.eval(
|
||||
'context', additional_context)
|
||||
}).done(function(result) {
|
||||
result.context = _.extend(result.context || {},
|
||||
additional_context);
|
||||
|
@ -1126,7 +1131,6 @@ instance.web.Sidebar = instance.web.Widget.extend({
|
|||
}
|
||||
},
|
||||
on_attachment_delete: function(e) {
|
||||
var self = this;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var self = this;
|
||||
|
@ -1171,7 +1175,8 @@ instance.web.View = instance.web.Widget.extend({
|
|||
"view_id": this.view_id,
|
||||
"view_type": this.view_type,
|
||||
toolbar: !!this.options.$sidebar,
|
||||
context: this.dataset.get_context(context)
|
||||
context: instance.web.pyeval.eval(
|
||||
'context', this.dataset.get_context(context))
|
||||
});
|
||||
}
|
||||
return view_loaded.then(function(r) {
|
||||
|
@ -1262,7 +1267,11 @@ instance.web.View = instance.web.Widget.extend({
|
|||
args.push(context);
|
||||
return dataset.call_button(action_data.name, args).done(handler);
|
||||
} else if (action_data.type=="action") {
|
||||
return this.rpc('/web/action/load', { action_id: action_data.name, context: context, do_not_eval: true}).done(handler);
|
||||
return this.rpc('/web/action/load', {
|
||||
action_id: action_data.name,
|
||||
context: instance.web.pyeval.eval('context', context),
|
||||
do_not_eval: true
|
||||
}).done(handler);
|
||||
} else {
|
||||
return dataset.exec_workflow(record_id, action_data.name).done(handler);
|
||||
}
|
||||
|
|
|
@ -18,14 +18,14 @@ class TestDataSetController(unittest2.TestCase):
|
|||
self.dataset.do_search_read(self.request, 'fake.model'),
|
||||
{'records': [], 'length': 0})
|
||||
self.read.assert_called_once_with(
|
||||
[], False, self.request.session.eval_context())
|
||||
[], False, self.request.context)
|
||||
|
||||
def test_regular_find(self):
|
||||
self.search.return_value = [1, 2, 3]
|
||||
|
||||
self.dataset.do_search_read(self.request, 'fake.model')
|
||||
self.read.assert_called_once_with(
|
||||
[1, 2, 3], False,self.request.session.eval_context())
|
||||
[1, 2, 3], False,self.request.context)
|
||||
|
||||
def test_ids_shortcut(self):
|
||||
self.search.return_value = [1, 2, 3]
|
||||
|
|
|
@ -4,7 +4,6 @@ import mock
|
|||
import unittest2
|
||||
|
||||
from ..controllers import main
|
||||
from ..session import OpenERPSession
|
||||
|
||||
class Placeholder(object):
|
||||
def __init__(self, **kwargs):
|
||||
|
@ -40,11 +39,11 @@ class LoadTest(unittest2.TestCase):
|
|||
root = self.menu.do_load(self.request)
|
||||
|
||||
self.MockMenus.search.assert_called_with(
|
||||
[], 0, False, False, self.request.session.eval_context())
|
||||
[], 0, False, False, self.request.context)
|
||||
self.MockMenus.read.assert_called_with(
|
||||
[], ['name', 'sequence', 'parent_id',
|
||||
'action', 'needaction_enabled', 'needaction_counter'],
|
||||
self.request.session.eval_context())
|
||||
self.request.context)
|
||||
|
||||
self.assertListEqual(
|
||||
root['children'],
|
||||
|
@ -63,7 +62,7 @@ class LoadTest(unittest2.TestCase):
|
|||
self.MockMenus.read.assert_called_with(
|
||||
[1, 2, 3], ['name', 'sequence', 'parent_id',
|
||||
'action', 'needaction_enabled', 'needaction_counter'],
|
||||
self.request.session.eval_context())
|
||||
self.request.context)
|
||||
|
||||
self.assertEqual(
|
||||
root['children'],
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import copy
|
||||
import xml.etree.ElementTree
|
||||
import mock
|
||||
|
||||
import unittest2
|
||||
import simplejson
|
||||
|
||||
import openerp.addons.web.controllers.main
|
||||
from .. import nonliterals, session as s
|
||||
|
@ -46,20 +43,14 @@ class DomainsAndContextsTest(unittest2.TestCase):
|
|||
)
|
||||
|
||||
def test_retrieve_nonliteral_domain(self):
|
||||
session = mock.Mock(spec=s.OpenERPSession)
|
||||
session.domains_store = {}
|
||||
domain_string = ("[('month','=',(datetime.date.today() - "
|
||||
"datetime.timedelta(365/12)).strftime('%%m'))]")
|
||||
e = xml.etree.ElementTree.Element(
|
||||
'field', domain=domain_string)
|
||||
|
||||
self.view.parse_domains_and_contexts(e, session)
|
||||
self.view.parse_domains_and_contexts(e, None)
|
||||
|
||||
self.assertIsInstance(e.get('domain'), nonliterals.Domain)
|
||||
self.assertEqual(
|
||||
nonliterals.Domain(
|
||||
session, key=e.get('domain').key).get_domain_string(),
|
||||
domain_string)
|
||||
|
||||
def test_convert_literal_context(self):
|
||||
e = xml.etree.ElementTree.Element(
|
||||
|
@ -89,20 +80,14 @@ class DomainsAndContextsTest(unittest2.TestCase):
|
|||
)
|
||||
|
||||
def test_retrieve_nonliteral_context(self):
|
||||
session = mock.Mock(spec=s.OpenERPSession)
|
||||
session.contexts_store = {}
|
||||
context_string = ("{'month': (datetime.date.today() - "
|
||||
"datetime.timedelta(365/12)).strftime('%%m')}")
|
||||
e = xml.etree.ElementTree.Element(
|
||||
'field', context=context_string)
|
||||
|
||||
self.view.parse_domains_and_contexts(e, session)
|
||||
self.view.parse_domains_and_contexts(e, None)
|
||||
|
||||
self.assertIsInstance(e.get('context'), nonliterals.Context)
|
||||
self.assertEqual(
|
||||
nonliterals.Context(
|
||||
session, key=e.get('context').key).get_context_string(),
|
||||
context_string)
|
||||
|
||||
class AttrsNormalizationTest(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
|
|
Loading…
Reference in New Issue