[imp] big improvements to context handling
bzr revid: nicolas.vanhoren@openerp.com-20110617160849-zevutg246ns1ghrk
This commit is contained in:
parent
157273f15a
commit
23dbe20028
|
@ -101,7 +101,8 @@ 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", {})
|
||||
return req.session.model('ir.ui.view_sc').get_sc(req.session._uid, "ir.ui.menu",
|
||||
req.session.eval_context(req.context))
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get_databases_list(self, req):
|
||||
|
@ -170,7 +171,25 @@ class Session(openerpweb.Controller):
|
|||
a list of fields to group by, potentially empty (in which case
|
||||
no group by should be performed)
|
||||
"""
|
||||
return _eval_domain_and_context(req, contexts, domains, group_by_seq)
|
||||
context = req.session.eval_context(openerpweb.nonliterals.CompoundContext(*contexts))
|
||||
domain = req.session.eval_domain(openerpweb.nonliterals.CompoundDomain(*(domains or [])), context)
|
||||
|
||||
group_by_sequence = []
|
||||
for candidate in (group_by_seq or []):
|
||||
ctx = req.session.eval_context(candidate, context)
|
||||
group_by = ctx.get('group_by')
|
||||
if not group_by:
|
||||
continue
|
||||
elif isinstance(group_by, basestring):
|
||||
group_by_sequence.append(group_by)
|
||||
else:
|
||||
group_by_sequence.extend(group_by)
|
||||
|
||||
return {
|
||||
'context': context,
|
||||
'domain': domain,
|
||||
'group_by': group_by_sequence
|
||||
}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def save_session_action(self, req, the_action):
|
||||
|
@ -212,26 +231,11 @@ class Session(openerpweb.Controller):
|
|||
return None
|
||||
return saved_actions["actions"].get(key)
|
||||
|
||||
def _eval_domain_and_context(req, contexts, domains, group_by_seq=None):
|
||||
context = req.session.eval_contexts(contexts)
|
||||
domain = req.session.eval_domains(domains, context)
|
||||
def eval_context_and_domain(session, context, domain=None):
|
||||
e_context = session.eval_context(context)
|
||||
e_domain = session.eval_domain(domain or [], e_context)
|
||||
|
||||
group_by_sequence = []
|
||||
for candidate in (group_by_seq or []):
|
||||
ctx = req.session.eval_context(candidate, context)
|
||||
group_by = ctx.get('group_by')
|
||||
if not group_by:
|
||||
continue
|
||||
elif isinstance(group_by, basestring):
|
||||
group_by_sequence.append(group_by)
|
||||
else:
|
||||
group_by_sequence.extend(group_by)
|
||||
|
||||
return {
|
||||
'context': context,
|
||||
'domain': domain,
|
||||
'group_by': group_by_sequence
|
||||
}
|
||||
return (e_context, e_domain)
|
||||
|
||||
def load_actions_from_ir_values(req, key, key2, models, meta, context):
|
||||
Values = req.session.model('ir.values')
|
||||
|
@ -307,8 +311,9 @@ class Menu(openerpweb.Controller):
|
|||
Menus = req.session.model('ir.ui.menu')
|
||||
# menus are loaded fully unlike a regular tree view, cause there are
|
||||
# less than 512 items
|
||||
menu_ids = Menus.search([])
|
||||
menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id'])
|
||||
context = req.session.eval_context(req.context)
|
||||
menu_ids = Menus.search([], 0, False, False, context)
|
||||
menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id'], context)
|
||||
menu_root = {'id': False, 'name': 'root', 'parent_id': [-1, '']}
|
||||
menu_items.append(menu_root)
|
||||
|
||||
|
@ -333,7 +338,10 @@ class Menu(openerpweb.Controller):
|
|||
@openerpweb.jsonrequest
|
||||
def action(self, req, menu_id):
|
||||
actions = load_actions_from_ir_values(req,'action', 'tree_but_open',
|
||||
[('ir.ui.menu', menu_id)], False, {})
|
||||
[('ir.ui.menu', menu_id)], False,
|
||||
#TODO niv fme: make it support context
|
||||
#req.session.eval_context(req.context))
|
||||
{})
|
||||
|
||||
return {"action": actions}
|
||||
|
||||
|
@ -342,7 +350,8 @@ class DataSet(openerpweb.Controller):
|
|||
|
||||
@openerpweb.jsonrequest
|
||||
def fields(self, req, model):
|
||||
return {'fields': req.session.model(model).fields_get()}
|
||||
return {'fields': req.session.model(model).fields_get(False,
|
||||
req.session.eval_context(req.context))}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def search_read(self, request, model, fields=False, offset=0, limit=False, domain=None, context=None, sort=None):
|
||||
|
@ -364,21 +373,23 @@ class DataSet(openerpweb.Controller):
|
|||
:rtype: list
|
||||
"""
|
||||
Model = request.session.model(model)
|
||||
|
||||
ids = Model.search(domain or [], offset or 0, limit or False,
|
||||
sort or False, request.context)
|
||||
context, domain = eval_context_and_domain(request.session, request.context, domain)
|
||||
|
||||
ids = Model.search(domain, offset or 0, limit or False,
|
||||
sort or False, context)
|
||||
|
||||
if fields and fields == ['id']:
|
||||
# shortcut read if we only want the ids
|
||||
return map(lambda id: {'id': id}, ids)
|
||||
|
||||
reads = Model.read(ids, fields or False, request.context)
|
||||
reads = Model.read(ids, fields or False, context)
|
||||
reads.sort(key=lambda obj: ids.index(obj['id']))
|
||||
return reads
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def read(self, request, model, ids, fields=False):
|
||||
return self.do_search_read(request, model, ids, fields)
|
||||
return self.do_search_read(request, model, ids, fields,
|
||||
request.session.eval_context(request.context))
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get(self, request, model, ids, fields=False):
|
||||
|
@ -403,47 +414,47 @@ class DataSet(openerpweb.Controller):
|
|||
:rtype: list
|
||||
"""
|
||||
Model = request.session.model(model)
|
||||
records = Model.read(ids, fields, request.context)
|
||||
records = Model.read(ids, fields, request.session.eval_context(request.context))
|
||||
|
||||
record_map = dict((record['id'], record) for record in records)
|
||||
|
||||
return [record_map[id] for id in ids if record_map.get(id)]
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
|
||||
def load(self, req, model, id, fields):
|
||||
m = req.session.model(model)
|
||||
value = {}
|
||||
r = m.read([id])
|
||||
r = m.read([id], False, req.session.eval_context(req.context))
|
||||
if r:
|
||||
value = r[0]
|
||||
return {'value': value}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def create(self, req, model, data, context={}):
|
||||
def create(self, req, model, data):
|
||||
m = req.session.model(model)
|
||||
r = m.create(data, context)
|
||||
r = m.create(data, req.session.eval_context(req.context))
|
||||
return {'result': r}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def save(self, req, model, id, data, context={}):
|
||||
def save(self, req, model, id, data):
|
||||
m = req.session.model(model)
|
||||
r = m.write([id], data, context)
|
||||
r = m.write([id], data, req.session.eval_context(req.context))
|
||||
return {'result': r}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def unlink(self, request, model, ids=[]):
|
||||
Model = request.session.model(model)
|
||||
return Model.unlink(ids)
|
||||
return Model.unlink(ids, request.session.eval_context(request.context))
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def call(self, req, model, method, args, domain_id=None, context_id=None):
|
||||
domain = args[domain_id] if domain_id and len(args) - 1 >= domain_id else []
|
||||
context = args[context_id] if context_id and len(args) - 1 >= context_id else {}
|
||||
res = _eval_domain_and_context(req, [context], [domain]);
|
||||
c, d = eval_context_and_domain(req.session, context, domain);
|
||||
if(domain_id and len(args) - 1 >= domain_id):
|
||||
args[context_id] = res["context"]
|
||||
args[domain_id] = d
|
||||
if(context_id and len(args) - 1 >= context_id):
|
||||
args[domain_id] = res["domain"]
|
||||
args[context_id] = c
|
||||
|
||||
m = req.session.model(model)
|
||||
r = getattr(m, method)(*args)
|
||||
|
@ -457,8 +468,7 @@ class DataSet(openerpweb.Controller):
|
|||
@openerpweb.jsonrequest
|
||||
def default_get(self, req, model, fields):
|
||||
m = req.session.model(model)
|
||||
ctx = _eval_domain_and_context(req, [req.context], [])["context"]
|
||||
r = m.default_get(fields, ctx)
|
||||
r = m.default_get(fields, req.session.eval_context(req.context))
|
||||
return {'result': r}
|
||||
|
||||
class DataGroup(openerpweb.Controller):
|
||||
|
@ -466,10 +476,11 @@ class DataGroup(openerpweb.Controller):
|
|||
@openerpweb.jsonrequest
|
||||
def read(self, request, model, group_by_fields, domain=None):
|
||||
Model = request.session.model(model)
|
||||
context, domain = eval_context_and_domain(request.session, request.context, domain)
|
||||
|
||||
return Model.read_group(
|
||||
domain or [], False, group_by_fields, 0, False,
|
||||
dict(request.context, group_by=group_by_fields))
|
||||
dict(context, group_by=group_by_fields))
|
||||
|
||||
class View(openerpweb.Controller):
|
||||
_cp_path = "/base/view"
|
||||
|
@ -477,9 +488,10 @@ class View(openerpweb.Controller):
|
|||
def fields_view_get(self, request, model, view_id, view_type,
|
||||
transform=True, toolbar=False, submenu=False):
|
||||
Model = request.session.model(model)
|
||||
fvg = Model.fields_view_get(view_id, view_type, request.context,
|
||||
toolbar, submenu)
|
||||
self.process_view(request.session, fvg, request.context, transform)
|
||||
context = request.session.eval_context(request.context)
|
||||
fvg = Model.fields_view_get(view_id, view_type, context, toolbar, submenu)
|
||||
# todo fme?: check that we should pass the evaluated context here
|
||||
self.process_view(request.session, fvg, context, transform)
|
||||
return fvg
|
||||
|
||||
def process_view(self, session, fvg, context, transform):
|
||||
|
@ -501,18 +513,20 @@ class View(openerpweb.Controller):
|
|||
'user_id': request.session._uid,
|
||||
'ref_id': view_id,
|
||||
'arch': arch
|
||||
})
|
||||
}, request.session.eval_context(request.context))
|
||||
return {'result': True}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def undo_custom(self, request, view_id, reset=False):
|
||||
CustomView = request.session.model('ir.ui.view.custom')
|
||||
vcustom = CustomView.search([('user_id', '=', request.session._uid), ('ref_id' ,'=', view_id)])
|
||||
context = request.session.eval_context(request.context)
|
||||
vcustom = CustomView.search([('user_id', '=', request.session._uid), ('ref_id' ,'=', view_id)],
|
||||
0, False, False, context)
|
||||
if vcustom:
|
||||
if reset:
|
||||
CustomView.unlink(vcustom)
|
||||
CustomView.unlink(vcustom, context)
|
||||
else:
|
||||
CustomView.unlink([vcustom[0]])
|
||||
CustomView.unlink([vcustom[0]], context)
|
||||
return {'result': True}
|
||||
return {'result': False}
|
||||
|
||||
|
@ -649,7 +663,7 @@ class SearchView(View):
|
|||
@openerpweb.jsonrequest
|
||||
def fields_get(self, req, model):
|
||||
Model = req.session.model(model)
|
||||
fields = Model.fields_get()
|
||||
fields = Model.fields_get(False, req.session.eval_context(req.context))
|
||||
return {'fields': fields}
|
||||
|
||||
class Binary(openerpweb.Controller):
|
||||
|
@ -659,11 +673,12 @@ class Binary(openerpweb.Controller):
|
|||
def image(self, request, session_id, model, id, field, **kw):
|
||||
cherrypy.response.headers['Content-Type'] = 'image/png'
|
||||
Model = request.session.model(model)
|
||||
context = request.session.eval_context(request.context)
|
||||
try:
|
||||
if not id:
|
||||
res = Model.default_get([field], request.context).get(field, '')
|
||||
res = Model.default_get([field], context).get(field, '')
|
||||
else:
|
||||
res = Model.read([int(id)], [field], request.context)[0].get(field, '')
|
||||
res = Model.read([int(id)], [field], context)[0].get(field, '')
|
||||
return base64.decodestring(res)
|
||||
except: # TODO: what's the exception here?
|
||||
return self.placeholder()
|
||||
|
@ -673,7 +688,8 @@ class Binary(openerpweb.Controller):
|
|||
@openerpweb.httprequest
|
||||
def saveas(self, request, session_id, model, id, field, fieldname, **kw):
|
||||
Model = request.session.model(model)
|
||||
res = Model.read([int(id)], [field, fieldname])[0]
|
||||
context = request.session.eval_context(request.context)
|
||||
res = Model.read([int(id)], [field, fieldname], context)[0]
|
||||
filecontent = res.get(field, '')
|
||||
if not filecontent:
|
||||
raise cherrypy.NotFound
|
||||
|
@ -715,6 +731,7 @@ class Binary(openerpweb.Controller):
|
|||
@openerpweb.httprequest
|
||||
def upload_attachment(self, request, session_id, callback, model, id, ufile=None):
|
||||
cherrypy.response.timeout = 500
|
||||
context = request.session.eval_context(request.context)
|
||||
Model = request.session.model('ir.attachment')
|
||||
try:
|
||||
out = """<script language="javascript" type="text/javascript">
|
||||
|
@ -729,7 +746,7 @@ class Binary(openerpweb.Controller):
|
|||
'datas': base64.encodestring(ufile.file.read()),
|
||||
'res_model': model,
|
||||
'res_id': int(id)
|
||||
})
|
||||
}, context)
|
||||
args = {
|
||||
'filename': ufile.filename,
|
||||
'id': attachment_id
|
||||
|
@ -745,9 +762,13 @@ class Action(openerpweb.Controller):
|
|||
def load(self, req, action_id):
|
||||
Actions = req.session.model('ir.actions.actions')
|
||||
value = False
|
||||
action_type = Actions.read([action_id], ['type'], req.session.context)
|
||||
context = req.session.eval_context(req.context)
|
||||
action_type = Actions.read([action_id], ['type'], context)
|
||||
if action_type:
|
||||
action = req.session.model(action_type[0]['type']).read([action_id], False, req.session.context)
|
||||
action = req.session.model(action_type[0]['type']).read([action_id], False,
|
||||
#TODO fme: check why does not work with context
|
||||
#context)
|
||||
{})
|
||||
if action:
|
||||
value = clean_action(action[0], req.session)
|
||||
return {'result': value}
|
||||
|
|
|
@ -160,9 +160,11 @@ class Context(object):
|
|||
ctx)
|
||||
|
||||
class CompoundDomain:
|
||||
def __init__(self):
|
||||
def __init__(self, *domains):
|
||||
self.domains = []
|
||||
self.session = None
|
||||
for domain in domains:
|
||||
self.add(domain)
|
||||
|
||||
def evaluate(self, context=None):
|
||||
final_domain = []
|
||||
|
@ -187,9 +189,11 @@ class CompoundDomain:
|
|||
return self
|
||||
|
||||
class CompoundContext:
|
||||
def __init__(self):
|
||||
def __init__(self, *contexts):
|
||||
self.contexts = []
|
||||
self.session = None
|
||||
for context in contexts:
|
||||
self.add(context)
|
||||
|
||||
def evaluate(self, context=None):
|
||||
ctx = dict(context or {})
|
||||
|
|
|
@ -201,7 +201,9 @@ class OpenERPSession(object):
|
|||
if isinstance(context_to_eval, dict):
|
||||
return context_to_eval
|
||||
|
||||
ctx = dict(context or {})
|
||||
ctx = dict(
|
||||
self.base_eval_context,
|
||||
**(context or {}))
|
||||
ctx['context'] = ctx
|
||||
|
||||
# if the domain was unpacked from JSON, it needs the current
|
||||
|
@ -209,32 +211,6 @@ class OpenERPSession(object):
|
|||
context_to_eval.session = self
|
||||
return context_to_eval.evaluate(ctx)
|
||||
|
||||
def eval_contexts(self, contexts, context=None):
|
||||
""" Evaluates a sequence of contexts to build a single final result
|
||||
|
||||
:param list contexts: a list of Context or dict contexts
|
||||
:param dict context: a base context, if needed
|
||||
:returns: the final combination of all provided contexts
|
||||
:rtype: dict
|
||||
"""
|
||||
# This is the context we use to evaluate stuff
|
||||
current_context = dict(
|
||||
self.base_eval_context,
|
||||
**(context or {}))
|
||||
# this is our result, it should not contain the values
|
||||
# of the base context above
|
||||
final_context = {}
|
||||
for ctx in contexts:
|
||||
# evaluate the current context in the sequence, merge it into
|
||||
# the result
|
||||
final_context.update(
|
||||
self.eval_context(
|
||||
ctx, current_context))
|
||||
# update the current evaluation context so that future
|
||||
# evaluations can use the results we just gathered
|
||||
current_context.update(final_context)
|
||||
return final_context
|
||||
|
||||
def eval_domain(self, domain, context=None):
|
||||
""" Evaluates the provided domain using the provided context
|
||||
(merged with the session's evaluation context)
|
||||
|
@ -265,25 +241,6 @@ class OpenERPSession(object):
|
|||
domain.session = self
|
||||
return domain.evaluate(ctx)
|
||||
|
||||
def eval_domains(self, domains, context=None):
|
||||
""" Evaluates and concatenates the provided domains using the
|
||||
provided context for all of them.
|
||||
|
||||
Returns the final, concatenated result.
|
||||
|
||||
:param list domains: a list of Domain or list domains
|
||||
:param dict context: the context in which the domains
|
||||
should be evaluated (if evaluations need
|
||||
to happen)
|
||||
:returns: the final combination of all domains in the sequence
|
||||
:rtype: list
|
||||
"""
|
||||
final_domain = []
|
||||
for domain in domains:
|
||||
final_domain.extend(
|
||||
self.eval_domain(domain, context))
|
||||
return final_domain
|
||||
|
||||
#----------------------------------------------------------
|
||||
# OpenERP Web RequestHandler
|
||||
#----------------------------------------------------------
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import unittest2
|
||||
from openerpweb.nonliterals import Domain
|
||||
from openerpweb.nonliterals import Domain, Context, CompoundDomain, CompoundContext
|
||||
import openerpweb.openerpweb
|
||||
|
||||
class TestOpenERPSession(unittest2.TestCase):
|
||||
|
@ -77,7 +77,7 @@ class TestOpenERPSession(unittest2.TestCase):
|
|||
|
||||
def test_eval_empty_domains(self):
|
||||
self.assertEqual(
|
||||
self.session.eval_domains([]),
|
||||
self.session.eval_domain(CompoundDomain(*[])),
|
||||
[])
|
||||
|
||||
def test_eval_literal_domains(self):
|
||||
|
@ -89,7 +89,7 @@ class TestOpenERPSession(unittest2.TestCase):
|
|||
('c', 'in', ['a', 'b', 'c'])]
|
||||
]
|
||||
self.assertEqual(
|
||||
self.session.eval_domains(domains),
|
||||
self.session.eval_domain(CompoundDomain(*domains)),
|
||||
[
|
||||
('a', 'is', 3),
|
||||
('b', 'ilike', 'foo'),
|
||||
|
@ -104,7 +104,7 @@ class TestOpenERPSession(unittest2.TestCase):
|
|||
"['|', ('date', '<', current_date),"
|
||||
" ('date', '>', current_date)]")]
|
||||
self.assertEqual(
|
||||
self.session.eval_domains(domains),
|
||||
self.session.eval_domain(CompoundDomain(*domains)),
|
||||
[('uid', '=', -1),
|
||||
'|', ('date', '<', '1945-08-05'), ('date', '>', '1945-08-05')]
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue