summaryrefslogtreecommitdiff
path: root/addons/web/static
diff options
context:
space:
mode:
authorXavier Morel <xmo@openerp.com>2012-08-06 11:46:27 +0200
committerXavier Morel <xmo@openerp.com>2012-08-06 11:46:27 +0200
commit6f4abdfbd519e8f8a416e24fdb541a88ef3104c6 (patch)
tree4ae85fde3c41ecb0df7adea45c6f5cd429276dd3 /addons/web/static
parent44b662b5bb799f46ee9ce948de26b6e06cea8e6e (diff)
[IMP] move eval functions for domains, groupbys and contexts outside of corelib, as well as the standard evaluation context building (and related objects)
bzr revid: xmo@openerp.com-20120806094627-8c9lwtfkbfws2bmj
Diffstat (limited to 'addons/web/static')
-rw-r--r--addons/web/static/src/js/boot.js2
-rw-r--r--addons/web/static/src/js/corelib.js229
-rw-r--r--addons/web/static/src/js/pyeval.js244
-rw-r--r--addons/web/static/test/evals.js13
-rw-r--r--addons/web/static/test/test.html1
-rw-r--r--addons/web/static/test/testing.js3
6 files changed, 257 insertions, 235 deletions
diff --git a/addons/web/static/src/js/boot.js b/addons/web/static/src/js/boot.js
index 844dd88a0ac..dd014846884 100644
--- a/addons/web/static/src/js/boot.js
+++ b/addons/web/static/src/js/boot.js
@@ -48,7 +48,7 @@
* OpenERP Web web module split
*---------------------------------------------------------*/
openerp.web = function(session) {
- var files = ["corelib","coresetup","dates","formats","chrome","data","views","search","list","form","list_editable","web_mobile","view_tree","data_export","data_import"];
+ var files = ["pyeval", "corelib","coresetup","dates","formats","chrome","data","views","search","list","form","list_editable","web_mobile","view_tree","data_export","data_import"];
for(var i=0; i<files.length; i++) {
if(openerp.web[files[i]]) {
openerp.web[files[i]](session);
diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js
index a46d6314ebe..bc506161db5 100644
--- a/addons/web/static/src/js/corelib.js
+++ b/addons/web/static/src/js/corelib.js
@@ -991,154 +991,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;
},
- test_eval_get_context: function () {
- var asJS = function (arg) {
- if (arg instanceof py.object) {
- return arg.toJSON();
- }
- return arg;
- };
-
- var datetime = new py.object();
- datetime.datetime = new py.type(function datetime() {
- throw new Error('datetime.datetime not implemented');
- });
- var date = datetime.date = new py.type(function date(y, m, d) {
- if (y instanceof Array) {
- d = y[2];
- m = y[1];
- y = y[0];
- }
- this.year = asJS(y);
- this.month = asJS(m);
- this.day = asJS(d);
- }, py.object, {
- strftime: function (args) {
- var f = asJS(args[0]), self = this;
- return new py.str(f.replace(/%([A-Za-z])/g, function (m, c) {
- switch (c) {
- case 'Y': return self.year;
- case 'm': return _.str.sprintf('%02d', self.month);
- case 'd': return _.str.sprintf('%02d', self.day);
- }
- throw new Error('ValueError: No known conversion for ' + m);
- }));
- }
- });
- date.__getattribute__ = function (name) {
- if (name === 'today') {
- return date.today;
- }
- throw new Error("AttributeError: object 'date' has no attribute '" + name +"'");
- };
- date.today = new py.def(function () {
- var d = new Date();
- return new date(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate());
- });
- datetime.time = new py.type(function time() {
- throw new Error('datetime.time not implemented');
- });
-
- var time = new py.object();
- time.strftime = new py.def(function (args) {
- return date.today.__call__().strftime(args);
- });
-
- var relativedelta = new py.type(function relativedelta(args, kwargs) {
- if (!_.isEmpty(args)) {
- throw new Error('Extraction of relative deltas from existing datetimes not supported');
- }
- this.ops = kwargs;
- }, py.object, {
- __add__: function (other) {
- if (!(other instanceof datetime.date)) {
- return py.NotImplemented;
- }
- // TODO: test this whole mess
- var year = asJS(this.ops.year) || asJS(other.year);
- if (asJS(this.ops.years)) {
- year += asJS(this.ops.years);
- }
-
- var month = asJS(this.ops.month) || asJS(other.month);
- if (asJS(this.ops.months)) {
- month += asJS(this.ops.months);
- // FIXME: no divmod in JS?
- while (month < 1) {
- year -= 1;
- month += 12;
- }
- while (month > 12) {
- year += 1;
- month -= 12;
- }
- }
-
- var lastMonthDay = new Date(year, month, 0).getDate();
- var day = asJS(this.ops.day) || asJS(other.day);
- if (day > lastMonthDay) { day = lastMonthDay; }
- var days_offset = ((asJS(this.ops.weeks) || 0) * 7) + (asJS(this.ops.days) || 0);
- if (days_offset) {
- day = new Date(year, month-1, day + days_offset).getDate();
- }
- // TODO: leapdays?
- // TODO: hours, minutes, seconds? Not used in XML domains
- // TODO: weekday?
- return new datetime.date(year, month, day);
- },
- __radd__: function (other) {
- return this.__add__(other);
- },
-
- __sub__: function (other) {
- if (!(other instanceof datetime.date)) {
- return py.NotImplemented;
- }
- // TODO: test this whole mess
- var year = asJS(this.ops.year) || asJS(other.year);
- if (asJS(this.ops.years)) {
- year -= asJS(this.ops.years);
- }
-
- var month = asJS(this.ops.month) || asJS(other.month);
- if (asJS(this.ops.months)) {
- month -= asJS(this.ops.months);
- // FIXME: no divmod in JS?
- while (month < 1) {
- year -= 1;
- month += 12;
- }
- while (month > 12) {
- year += 1;
- month -= 12;
- }
- }
-
- var lastMonthDay = new Date(year, month, 0).getDate();
- var day = asJS(this.ops.day) || asJS(other.day);
- if (day > lastMonthDay) { day = lastMonthDay; }
- var days_offset = ((asJS(this.ops.weeks) || 0) * 7) + (asJS(this.ops.days) || 0);
- if (days_offset) {
- day = new Date(year, month-1, day - days_offset).getDate();
- }
- // TODO: leapdays?
- // TODO: hours, minutes, seconds? Not used in XML domains
- // TODO: weekday?
- return new datetime.date(year, month, day);
- },
- __rsub__: function (other) {
- return this.__sub__(other);
- }
- });
-
- return {
- uid: new py.float(this.uid),
- datetime: datetime,
- time: time,
- relativedelta: relativedelta,
- current_date: date.today.__call__().strftime(['%Y-%m-%d'])
- };
- },
/**
* FIXME: Huge testing hack, especially the evaluation context, rewrite + test for real before switching
*/
@@ -1154,8 +1006,8 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
'</ul>';
try {
// see Session.eval_context in Python
- var ctx = this.test_eval_contexts(
- ([this.context] || []).concat(source.contexts));
+ 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, {
@@ -1173,7 +1025,7 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
}
try {
- var dom = this.test_eval_domains(source.domains, this.test_eval_get_context());
+ 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, {
@@ -1191,7 +1043,7 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
}
try {
- var groups = this.test_eval_groupby(source.group_by_seq);
+ 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, {
@@ -1208,79 +1060,6 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
}), true);
}
},
- test_eval_contexts: function (contexts, evaluation_context) {
- evaluation_context = evaluation_context || {};
- var self = this;
- return _(contexts).reduce(function (result_context, ctx) {
- // __eval_context evaluations can lead to some of `contexts`'s
- // values being null, skip them as well as empty contexts
- if (_.isEmpty(ctx)) { return result_context; }
- var evaluated = ctx;
- switch(ctx.__ref) {
- case 'context':
- evaluated = py.eval(ctx.__debug, evaluation_context);
- break;
- case 'compound_context':
- var eval_context = self.test_eval_contexts([ctx.__eval_context]);
- evaluated = self.test_eval_contexts(
- ctx.__contexts, _.extend({}, evaluation_context, eval_context));
- break;
- }
- // add newly evaluated context to evaluation context for following
- // siblings
- _.extend(evaluation_context, evaluated);
- return _.extend(result_context, evaluated);
- }, _.extend({}, this.user_context));
- },
- test_eval_domains: function (domains, evaluation_context) {
- var result_domain = [], self = this;
- _(domains).each(function (dom) {
- switch(dom.__ref) {
- case 'domain':
- result_domain.push.apply(
- result_domain, py.eval(dom.__debug, evaluation_context));
- break;
- case 'compound_domain':
- var eval_context = self.test_eval_contexts([dom.__eval_context]);
- result_domain.push.apply(
- result_domain, self.test_eval_domains(
- dom.__domains, _.extend(
- {}, evaluation_context, eval_context)));
- break;
- default:
- result_domain.push.apply(
- result_domain, dom);
- }
- });
- return result_domain;
- },
- test_eval_groupby: function (contexts) {
- var result_group = [], self = this;
- _(contexts).each(function (ctx) {
- var group;
- switch(ctx.__ref) {
- case 'context':
- group = py.eval(ctx.__debug).group_by;
- break;
- case 'compound_context':
- group = self.test_eval_contexts(
- ctx.__contexts, ctx.__eval_context).group_by;
- break;
- default:
- group = ctx.group_by
- }
- if (!group) { return; }
- if (typeof group === 'string') {
- result_group.push(group);
- } else if (group instanceof Array) {
- result_group.push.apply(result_group, group);
- } else {
- throw new Error('Got invalid groupby {{'
- + JSON.stringify(group) + '}}');
- }
- });
- return result_group;
- },
/**
* Executes an RPC call, registering the provided callbacks.
*
diff --git a/addons/web/static/src/js/pyeval.js b/addons/web/static/src/js/pyeval.js
new file mode 100644
index 00000000000..8c498c3f885
--- /dev/null
+++ b/addons/web/static/src/js/pyeval.js
@@ -0,0 +1,244 @@
+/*
+ * py.js helpers and setup
+ */
+openerp.web.pyeval = function (instance) {
+ instance.web.pyeval = {};
+
+ var asJS = function (arg) {
+ if (arg instanceof py.object) {
+ return arg.toJSON();
+ }
+ return arg;
+ };
+
+ var datetime = new py.object();
+ datetime.datetime = new py.type(function datetime() {
+ throw new Error('datetime.datetime not implemented');
+ });
+ var date = datetime.date = new py.type(function date(y, m, d) {
+ if (y instanceof Array) {
+ d = y[2];
+ m = y[1];
+ y = y[0];
+ }
+ this.year = asJS(y);
+ this.month = asJS(m);
+ this.day = asJS(d);
+ }, py.object, {
+ strftime: function (args) {
+ var f = asJS(args[0]), self = this;
+ return new py.str(f.replace(/%([A-Za-z])/g, function (m, c) {
+ switch (c) {
+ case 'Y': return self.year;
+ case 'm': return _.str.sprintf('%02d', self.month);
+ case 'd': return _.str.sprintf('%02d', self.day);
+ }
+ throw new Error('ValueError: No known conversion for ' + m);
+ }));
+ }
+ });
+ date.__getattribute__ = function (name) {
+ if (name === 'today') {
+ return date.today;
+ }
+ throw new Error("AttributeError: object 'date' has no attribute '" + name +"'");
+ };
+ date.today = new py.def(function () {
+ var d = new Date();
+ return new date(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate());
+ });
+ datetime.time = new py.type(function time() {
+ throw new Error('datetime.time not implemented');
+ });
+
+ var time = new py.object();
+ time.strftime = new py.def(function (args) {
+ return date.today.__call__().strftime(args);
+ });
+
+ var relativedelta = new py.type(function relativedelta(args, kwargs) {
+ if (!_.isEmpty(args)) {
+ throw new Error('Extraction of relative deltas from existing datetimes not supported');
+ }
+ this.ops = kwargs;
+ }, py.object, {
+ __add__: function (other) {
+ if (!(other instanceof datetime.date)) {
+ return py.NotImplemented;
+ }
+ // TODO: test this whole mess
+ var year = asJS(this.ops.year) || asJS(other.year);
+ if (asJS(this.ops.years)) {
+ year += asJS(this.ops.years);
+ }
+
+ var month = asJS(this.ops.month) || asJS(other.month);
+ if (asJS(this.ops.months)) {
+ month += asJS(this.ops.months);
+ // FIXME: no divmod in JS?
+ while (month < 1) {
+ year -= 1;
+ month += 12;
+ }
+ while (month > 12) {
+ year += 1;
+ month -= 12;
+ }
+ }
+
+ var lastMonthDay = new Date(year, month, 0).getDate();
+ var day = asJS(this.ops.day) || asJS(other.day);
+ if (day > lastMonthDay) { day = lastMonthDay; }
+ var days_offset = ((asJS(this.ops.weeks) || 0) * 7) + (asJS(this.ops.days) || 0);
+ if (days_offset) {
+ day = new Date(year, month-1, day + days_offset).getDate();
+ }
+ // TODO: leapdays?
+ // TODO: hours, minutes, seconds? Not used in XML domains
+ // TODO: weekday?
+ return new datetime.date(year, month, day);
+ },
+ __radd__: function (other) {
+ return this.__add__(other);
+ },
+
+ __sub__: function (other) {
+ if (!(other instanceof datetime.date)) {
+ return py.NotImplemented;
+ }
+ // TODO: test this whole mess
+ var year = asJS(this.ops.year) || asJS(other.year);
+ if (asJS(this.ops.years)) {
+ year -= asJS(this.ops.years);
+ }
+
+ var month = asJS(this.ops.month) || asJS(other.month);
+ if (asJS(this.ops.months)) {
+ month -= asJS(this.ops.months);
+ // FIXME: no divmod in JS?
+ while (month < 1) {
+ year -= 1;
+ month += 12;
+ }
+ while (month > 12) {
+ year += 1;
+ month -= 12;
+ }
+ }
+
+ var lastMonthDay = new Date(year, month, 0).getDate();
+ var day = asJS(this.ops.day) || asJS(other.day);
+ if (day > lastMonthDay) { day = lastMonthDay; }
+ var days_offset = ((asJS(this.ops.weeks) || 0) * 7) + (asJS(this.ops.days) || 0);
+ if (days_offset) {
+ day = new Date(year, month-1, day - days_offset).getDate();
+ }
+ // TODO: leapdays?
+ // TODO: hours, minutes, seconds? Not used in XML domains
+ // TODO: weekday?
+ return new datetime.date(year, month, day);
+ },
+ __rsub__: function (other) {
+ return this.__sub__(other);
+ }
+ });
+
+ var eval_contexts = function (contexts, evaluation_context) {
+ evaluation_context = evaluation_context || {};
+ return _(contexts).reduce(function (result_context, ctx) {
+ // __eval_context evaluations can lead to some of `contexts`'s
+ // values being null, skip them as well as empty contexts
+ if (_.isEmpty(ctx)) { return result_context; }
+ var evaluated = ctx;
+ switch(ctx.__ref) {
+ case 'context':
+ evaluated = py.eval(ctx.__debug, evaluation_context);
+ break;
+ case 'compound_context':
+ var eval_context = eval_contexts([ctx.__eval_context]);
+ evaluated = eval_contexts(
+ ctx.__contexts, _.extend({}, evaluation_context, eval_context));
+ break;
+ }
+ // add newly evaluated context to evaluation context for following
+ // siblings
+ _.extend(evaluation_context, evaluated);
+ return _.extend(result_context, evaluated);
+ }, _.extend({}, instance.connection.user_context));
+ };
+ var eval_domains = function (domains, evaluation_context) {
+ var result_domain = [];
+ _(domains).each(function (domain) {
+ switch(domain.__ref) {
+ case 'domain':
+ result_domain.push.apply(
+ result_domain, py.eval(domain.__debug, evaluation_context));
+ break;
+ case 'compound_domain':
+ var eval_context = eval_contexts([domain.__eval_context]);
+ result_domain.push.apply(
+ result_domain, eval_domains(
+ domain.__domains, _.extend(
+ {}, evaluation_context, eval_context)));
+ break;
+ default:
+ result_domain.push.apply(result_domain, domain);
+ }
+ });
+ return result_domain;
+ };
+ var eval_groupbys = function (contexts, evaluation_context) {
+ var result_group = [];
+ _(contexts).each(function (ctx) {
+ var group;
+ var evaluated = ctx;
+ switch(ctx.__ref) {
+ case 'context':
+ evaluated = py.eval(ctx.__debug), evaluation_context;
+ break;
+ case 'compound_context':
+ var eval_context = eval_contexts([ctx.__eval_context]);
+ evaluated = eval_contexts(
+ ctx.__contexts, _.extend({}, evaluation_context, eval_context));
+ break;
+ }
+ group = evaluated.group_by;
+ if (!group) { return; }
+ if (typeof group === 'string') {
+ result_group.push(group);
+ } else if (group instanceof Array) {
+ result_group.push.apply(result_group, group);
+ } else {
+ throw new Error('Got invalid groupby {{'
+ + JSON.stringify(group) + '}}');
+ }
+ _.extend(evaluation_context, evaluated);
+ });
+ return result_group;
+ };
+
+ instance.web.pyeval.context = function () {
+ return {
+ uid: new py.float(instance.connection.uid),
+ datetime: datetime,
+ time: time,
+ relativedelta: relativedelta,
+ current_date: date.today.__call__().strftime(['%Y-%m-%d']),
+ };
+ };
+
+ /**
+ * @param {String} type "domains", "contexts" or "groupbys"
+ * @param {Array} object domains or contexts to evaluate
+ * @param {Object} [context] evaluation context
+ */
+ instance.web.pyeval.eval = function (type, object, context) {
+ if (!context) { context = instance.web.pyeval.context()}
+ switch(type) {
+ case 'contexts': return eval_contexts(object, context);
+ case 'domains': return eval_domains(object, context);
+ case 'groupbys': return eval_groupbys(object, context);
+ }
+ throw new Error("Unknow evaluation type " + type)
+ };
+};
diff --git a/addons/web/static/test/evals.js b/addons/web/static/test/evals.js
index 7bc6554e074..ee4aef4bf79 100644
--- a/addons/web/static/test/evals.js
+++ b/addons/web/static/test/evals.js
@@ -3,16 +3,14 @@ $(document).ready(function () {
module("eval.contexts", {
setup: function () {
- openerp = window.openerp.init([]);
- window.openerp.web.corelib(openerp);
- window.openerp.web.coresetup(openerp);
+ openerp = window.openerp.testing.instanceFor('coresetup');
}
});
test('context_sequences', function () {
// Context n should have base evaluation context + all of contexts
// 0..n-1 in its own evaluation context
var active_id = 4;
- var result = openerp.connection.test_eval_contexts([
+ var result = openerp.web.pyeval.eval('contexts', [
{
"__contexts": [
{
@@ -56,7 +54,7 @@ $(document).ready(function () {
});
});
test('non-literal_eval_contexts', function () {
- var result = openerp.connection.test_eval_contexts([{
+ var result = openerp.web.pyeval.eval('contexts', [{
"__ref": "compound_context",
"__contexts": [
{"__ref": "context", "__debug": "{'type':parent.type}",
@@ -141,9 +139,8 @@ $(document).ready(function () {
});
test('current_date', function () {
var current_date = openerp.web.date_to_str(new Date());
- var result = openerp.connection.test_eval_domains(
- [[],{"__ref":"domain","__debug":"[('name','>=',current_date),('name','<=',current_date)]","__id":"5dedcfc96648"}],
- openerp.connection.test_eval_get_context());
+ var result = openerp.web.pyeval.eval('domains',
+ [[],{"__ref":"domain","__debug":"[('name','>=',current_date),('name','<=',current_date)]","__id":"5dedcfc96648"}]);
deepEqual(result, [
['name', '>=', current_date],
['name', '<=', current_date]
diff --git a/addons/web/static/test/test.html b/addons/web/static/test/test.html
index 35d57d3c3a6..91b45c44bad 100644
--- a/addons/web/static/test/test.html
+++ b/addons/web/static/test/test.html
@@ -28,6 +28,7 @@
<script src="/web/static/lib/py.js/lib/py.js"></script>
<script src="/web/static/src/js/boot.js"></script>
+ <script src="/web/static/src/js/pyeval.js"></script>
<script src="/web/static/src/js/corelib.js"></script>
<script src="/web/static/src/js/coresetup.js"></script>
<script src="/web/static/src/js/dates.js"></script>
diff --git a/addons/web/static/test/testing.js b/addons/web/static/test/testing.js
index e9525fc82a0..9a449a40493 100644
--- a/addons/web/static/test/testing.js
+++ b/addons/web/static/test/testing.js
@@ -6,7 +6,8 @@ openerp.testing = (function () {
var doc = xhr.responseXML;
var dependencies = {
- corelib: [],
+ pyeval: [],
+ corelib: ['pyeval'],
coresetup: ['corelib'],
data: ['corelib', 'coresetup'],
dates: [],