[IMP] shortcut call to eval_domain_and_context to be evaluated on the JS side, also add some offline-evaluation of contexts and domains in rpc call methods

bzr revid: xmo@openerp.com-20121011100532-5ihje0maslp37zpf
This commit is contained in:
Xavier Morel 2012-10-11 12:05:32 +02:00
parent b94e9c30a7
commit e6b77eb820
3 changed files with 77 additions and 77 deletions

View File

@ -997,75 +997,6 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
this.server = this.origin; // keep chs happy
this.rpc_function = (this.origin == window_origin) ? this.rpc_json : this.rpc_jsonp;
},
/**
* FIXME: Huge testing hack, especially the evaluation context, rewrite + test for real before switching
*/
test_eval: function (source, expected) {
var match_template = '<ul>' +
'<li>Source: %(source)s</li>' +
'<li>Local: %(local)s</li>' +
'<li>Remote: %(remote)s</li>' +
'</ul>',
fail_template = '<ul>' +
'<li>Error: %(error)s</li>' +
'<li>Source: %(source)s</li>' +
'</ul>';
try {
// see Session.eval_context in Python
var ctx = instance.web.pyeval.eval('contexts',
([this.context] || []).concat(source.contexts));
if (!_.isEqual(ctx, expected.context)) {
instance.webclient.notification.warn('Context mismatch, report to xmo',
_.str.sprintf(match_template, {
source: JSON.stringify(source.contexts),
local: JSON.stringify(ctx),
remote: JSON.stringify(expected.context)
}), true);
}
} catch (e) {
instance.webclient.notification.warn('Context fail, report to xmo',
_.str.sprintf(fail_template, {
error: e.message,
source: JSON.stringify(source.contexts)
}), true);
}
try {
var dom = instance.web.pyeval.eval('domains', source.domains);
if (!_.isEqual(dom, expected.domain)) {
instance.webclient.notification.warn('Domains mismatch, report to xmo',
_.str.sprintf(match_template, {
source: JSON.stringify(source.domains),
local: JSON.stringify(dom),
remote: JSON.stringify(expected.domain)
}), true);
}
} catch (e) {
instance.webclient.notification.warn('Domain fail, report to xmo',
_.str.sprintf(fail_template, {
error: e.message,
source: JSON.stringify(source.domains)
}), true);
}
try {
var groups = instance.web.pyeval.eval('groupbys', source.group_by_seq);
if (!_.isEqual(groups, expected.group_by)) {
instance.webclient.notification.warn('GroupBy mismatch, report to xmo',
_.str.sprintf(match_template, {
source: JSON.stringify(source.group_by_seq),
local: JSON.stringify(groups),
remote: JSON.stringify(expected.group_by)
}), true);
}
} catch (e) {
instance.webclient.notification.warn('GroupBy fail, report to xmo',
_.str.sprintf(fail_template, {
error: e.message,
source: JSON.stringify(source.group_by_seq)
}), true);
}
},
/**
* Executes an RPC call, registering the provided callbacks.
*
@ -1098,13 +1029,17 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
this.trigger('request', url, payload);
var aborter = params.aborter;
delete params.aborter;
var request = this.rpc_function(url, payload).then(
function (response, textStatus, jqXHR) {
var request;
if (url.url === '/web/session/eval_domain_and_context') {
// intercept eval_domain_and_context
request = instance.web.pyeval.eval_domains_and_contexts(
params)
} else {
request = this.rpc_function(url, payload);
}
request.then(function (response, textStatus, jqXHR) {
self.trigger('response', response);
if (!response.error) {
if (url.url === '/web/session/eval_domain_and_context') {
self.test_eval(params, response.result);
}
deferred.resolve(response["result"], textStatus, jqXHR);
} else if (response.error.data.type === "session_invalid") {
self.uid = false;

View File

@ -61,8 +61,10 @@ instance.web.Query = instance.web.Class.extend({
return instance.session.rpc('/web/dataset/search_read', {
model: this._model.name,
fields: this._fields || false,
domain: this._model.domain(this._filter),
context: this._model.context(this._context),
domain: instance.web.pyeval.eval('domains',
[this._model.domain(this._filter)]),
context: instance.web.pyeval.eval('contexts',
[this._model.context(this._context)]),
offset: this._offset,
limit: this._limit,
sort: instance.web.serialize_sort(this._order_by)
@ -280,6 +282,7 @@ instance.web.Model = instance.web.Class.extend({
kwargs = args;
args = [];
}
instance.web.pyeval.ensure_evaluated(args, kwargs);
return instance.session.rpc('/web/dataset/call_kw', {
model: this.name,
method: method,
@ -291,7 +294,7 @@ instance.web.Model = instance.web.Class.extend({
* Fetches a Query instance bound to this model, for searching
*
* @param {Array<String>} [fields] fields to ultimately fetch during the search
* @returns {openerp.web.Query}
* @returns {instance.web.Query}
*/
query: function (fields) {
return new instance.web.Query(this, fields);
@ -339,9 +342,11 @@ instance.web.Model = instance.web.Class.extend({
* FIXME: remove when evaluator integrated
*/
call_button: function (method, args) {
instance.web.pyeval.ensure_evaluated(args, {});
return instance.session.rpc('/web/dataset/call_button', {
model: this.name,
method: method,
// Should not be necessary anymore. Integrate remote in this?
domain_id: null,
context_id: args.length - 1,
args: args || []
@ -599,9 +604,12 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
* @returns {$.Deferred}
*/
call_and_eval: function (method, args, domain_index, context_index) {
instance.web.pyeval.ensure_evaluated(args, {});
return instance.session.rpc('/web/dataset/call', {
model: this.model,
method: method,
// Should not be necessary anymore as ensure_evaluated traverses
// all of the args array
domain_id: domain_index == undefined ? null : domain_index,
context_id: context_index == undefined ? null : context_index,
args: args || []

View File

@ -2,6 +2,7 @@
* py.js helpers and setup
*/
openerp.web.pyeval = function (instance) {
var _t = instance.web._t;
instance.web.pyeval = {};
var obj = function () {};
@ -317,4 +318,60 @@ openerp.web.pyeval = function (instance) {
}
throw new Error("Unknow evaluation type " + type)
};
var eval_arg = function (arg) {
if (typeof arg !== 'object' || !arg.__ref) { return arg; }
switch(arg.__ref) {
case 'domain': case 'compound_domain':
return instance.web.pyeval.eval('domains', [arg]);
case 'context': case 'compound_context':
return instance.web.pyeval.eval('contexts', [arg]);
default:
throw new Error(_t("Unknown nonliteral type " + arg.__ref));
}
};
/**
* If args or kwargs are unevaluated contexts or domains (compound or not),
* evaluated them in-place.
*
* Potentially mutates both parameters.
*
* @param args
* @param kwargs
*/
instance.web.pyeval.ensure_evaluated = function (args, kwargs) {
for (var i=0; i<args.length; ++i) {
args[i] = eval_arg(args[i]);
}
for (var k in kwargs) {
if (!kwargs.hasOwnProperty(k)) { continue; }
kwargs[k] = eval_arg(kwargs[k]);
}
};
instance.web.pyeval.eval_domains_and_contexts = function (source) {
var d = new $.Deferred();
setTimeout(function () {
try {
var contexts = ([instance.session.context] || []).concat(source.contexts);
// see Session.eval_context in Python
d.resolve({result: {
context: instance.web.pyeval.eval('contexts', contexts),
domain: instance.web.pyeval.eval('domains', source.domains),
group_by: instance.web.pyeval.eval('groupbys', source.group_by_seq)
}}, 'success', {});
} catch (e) {
d.resolve({ error: {
code: 400,
message: _t("Evaluation Error"),
data: {
type: 'local_exception',
debug: _.str.sprintf(
_t("Local evaluation failure\n%s\n\n%s"),
e.message, JSON.stringify(source))
}
}});
}
}, 0);
return d;
}
};