[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:
parent
b94e9c30a7
commit
e6b77eb820
|
@ -997,75 +997,6 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
||||||
this.server = this.origin; // keep chs happy
|
this.server = this.origin; // keep chs happy
|
||||||
this.rpc_function = (this.origin == window_origin) ? this.rpc_json : this.rpc_jsonp;
|
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.
|
* Executes an RPC call, registering the provided callbacks.
|
||||||
*
|
*
|
||||||
|
@ -1098,13 +1029,17 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
||||||
this.trigger('request', url, payload);
|
this.trigger('request', url, payload);
|
||||||
var aborter = params.aborter;
|
var aborter = params.aborter;
|
||||||
delete params.aborter;
|
delete params.aborter;
|
||||||
var request = this.rpc_function(url, payload).then(
|
var request;
|
||||||
function (response, textStatus, jqXHR) {
|
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);
|
self.trigger('response', response);
|
||||||
if (!response.error) {
|
if (!response.error) {
|
||||||
if (url.url === '/web/session/eval_domain_and_context') {
|
|
||||||
self.test_eval(params, response.result);
|
|
||||||
}
|
|
||||||
deferred.resolve(response["result"], textStatus, jqXHR);
|
deferred.resolve(response["result"], textStatus, jqXHR);
|
||||||
} else if (response.error.data.type === "session_invalid") {
|
} else if (response.error.data.type === "session_invalid") {
|
||||||
self.uid = false;
|
self.uid = false;
|
||||||
|
|
|
@ -61,8 +61,10 @@ instance.web.Query = instance.web.Class.extend({
|
||||||
return instance.session.rpc('/web/dataset/search_read', {
|
return instance.session.rpc('/web/dataset/search_read', {
|
||||||
model: this._model.name,
|
model: this._model.name,
|
||||||
fields: this._fields || false,
|
fields: this._fields || false,
|
||||||
domain: this._model.domain(this._filter),
|
domain: instance.web.pyeval.eval('domains',
|
||||||
context: this._model.context(this._context),
|
[this._model.domain(this._filter)]),
|
||||||
|
context: instance.web.pyeval.eval('contexts',
|
||||||
|
[this._model.context(this._context)]),
|
||||||
offset: this._offset,
|
offset: this._offset,
|
||||||
limit: this._limit,
|
limit: this._limit,
|
||||||
sort: instance.web.serialize_sort(this._order_by)
|
sort: instance.web.serialize_sort(this._order_by)
|
||||||
|
@ -280,6 +282,7 @@ instance.web.Model = instance.web.Class.extend({
|
||||||
kwargs = args;
|
kwargs = args;
|
||||||
args = [];
|
args = [];
|
||||||
}
|
}
|
||||||
|
instance.web.pyeval.ensure_evaluated(args, kwargs);
|
||||||
return instance.session.rpc('/web/dataset/call_kw', {
|
return instance.session.rpc('/web/dataset/call_kw', {
|
||||||
model: this.name,
|
model: this.name,
|
||||||
method: method,
|
method: method,
|
||||||
|
@ -291,7 +294,7 @@ instance.web.Model = instance.web.Class.extend({
|
||||||
* Fetches a Query instance bound to this model, for searching
|
* Fetches a Query instance bound to this model, for searching
|
||||||
*
|
*
|
||||||
* @param {Array<String>} [fields] fields to ultimately fetch during the search
|
* @param {Array<String>} [fields] fields to ultimately fetch during the search
|
||||||
* @returns {openerp.web.Query}
|
* @returns {instance.web.Query}
|
||||||
*/
|
*/
|
||||||
query: function (fields) {
|
query: function (fields) {
|
||||||
return new instance.web.Query(this, fields);
|
return new instance.web.Query(this, fields);
|
||||||
|
@ -339,9 +342,11 @@ instance.web.Model = instance.web.Class.extend({
|
||||||
* FIXME: remove when evaluator integrated
|
* FIXME: remove when evaluator integrated
|
||||||
*/
|
*/
|
||||||
call_button: function (method, args) {
|
call_button: function (method, args) {
|
||||||
|
instance.web.pyeval.ensure_evaluated(args, {});
|
||||||
return instance.session.rpc('/web/dataset/call_button', {
|
return instance.session.rpc('/web/dataset/call_button', {
|
||||||
model: this.name,
|
model: this.name,
|
||||||
method: method,
|
method: method,
|
||||||
|
// Should not be necessary anymore. Integrate remote in this?
|
||||||
domain_id: null,
|
domain_id: null,
|
||||||
context_id: args.length - 1,
|
context_id: args.length - 1,
|
||||||
args: args || []
|
args: args || []
|
||||||
|
@ -599,9 +604,12 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
||||||
* @returns {$.Deferred}
|
* @returns {$.Deferred}
|
||||||
*/
|
*/
|
||||||
call_and_eval: function (method, args, domain_index, context_index) {
|
call_and_eval: function (method, args, domain_index, context_index) {
|
||||||
|
instance.web.pyeval.ensure_evaluated(args, {});
|
||||||
return instance.session.rpc('/web/dataset/call', {
|
return instance.session.rpc('/web/dataset/call', {
|
||||||
model: this.model,
|
model: this.model,
|
||||||
method: method,
|
method: method,
|
||||||
|
// Should not be necessary anymore as ensure_evaluated traverses
|
||||||
|
// all of the args array
|
||||||
domain_id: domain_index == undefined ? null : domain_index,
|
domain_id: domain_index == undefined ? null : domain_index,
|
||||||
context_id: context_index == undefined ? null : context_index,
|
context_id: context_index == undefined ? null : context_index,
|
||||||
args: args || []
|
args: args || []
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* py.js helpers and setup
|
* py.js helpers and setup
|
||||||
*/
|
*/
|
||||||
openerp.web.pyeval = function (instance) {
|
openerp.web.pyeval = function (instance) {
|
||||||
|
var _t = instance.web._t;
|
||||||
instance.web.pyeval = {};
|
instance.web.pyeval = {};
|
||||||
|
|
||||||
var obj = function () {};
|
var obj = function () {};
|
||||||
|
@ -317,4 +318,60 @@ openerp.web.pyeval = function (instance) {
|
||||||
}
|
}
|
||||||
throw new Error("Unknow evaluation type " + type)
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue