[imp] big improvements to context handling

bzr revid: nicolas.vanhoren@openerp.com-20110617160849-zevutg246ns1ghrk
This commit is contained in:
niv-openerp 2011-06-17 18:08:49 +02:00
parent 157273f15a
commit 23dbe20028
4 changed files with 92 additions and 110 deletions

View File

@ -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}

View File

@ -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 {})

View File

@ -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
#----------------------------------------------------------

View File

@ -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')]
)