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)
@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):
: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).
: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]
"""
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']:
'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,
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]:
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):
@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
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
'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}
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"
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()
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])
: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()
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:
@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">
'datas_fname': ufile.filename,
'res_model': model,
'res_id': int(id)
- }, context)
+ }, req.context)
args = {
'filename': ufile.filename,
'id': attachment_id
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:
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)
@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:
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
'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
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"]
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)):
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+?
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.
: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
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.
: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
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):
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