[MERGE] Merged with main web
bzr revid: tde@openerp.com-20120405124945-lq1u2few7bl1fsl4
This commit is contained in:
@@ -45,29 +45,20 @@ class NonLiteralEncoder(simplejson.encoder.JSONEncoder):
|
||||
raise TypeError('Could not encode unknown non-literal %s' % object)
|
||||
|
||||
_ALLOWED_KEYS = frozenset(['__ref', "__id", '__domains', '__debug',
|
||||
'__contexts', '__eval_context', 'own_values'])
|
||||
'__contexts', '__eval_context'])
|
||||
|
||||
def non_literal_decoder(dct):
|
||||
""" Decodes JSON dicts into :class:`Domain` and :class:`Context` based on
|
||||
magic attribute tags.
|
||||
|
||||
Also handles private context section for the domain or section via the
|
||||
``own_values`` dict key.
|
||||
"""
|
||||
if '__ref' in dct:
|
||||
for x in dct:
|
||||
if x not in _ALLOWED_KEYS:
|
||||
raise ValueError("'%s' key not allowed in non literal domain/context" % x)
|
||||
if dct['__ref'] == 'domain':
|
||||
domain = Domain(None, key=dct['__id'])
|
||||
if 'own_values' in dct:
|
||||
domain.own = dct['own_values']
|
||||
return domain
|
||||
return Domain(None, key=dct['__id'])
|
||||
elif dct['__ref'] == 'context':
|
||||
context = Context(None, key=dct['__id'])
|
||||
if 'own_values' in dct:
|
||||
context.own = dct['own_values']
|
||||
return context
|
||||
return Context(None, key=dct['__id'])
|
||||
elif dct["__ref"] == "compound_domain":
|
||||
cdomain = CompoundDomain()
|
||||
for el in dct["__domains"]:
|
||||
@@ -111,7 +102,6 @@ class Domain(BaseDomain):
|
||||
"and a domain string")
|
||||
|
||||
self.session = session
|
||||
self.own = {}
|
||||
if domain_string:
|
||||
self.key = binascii.hexlify(
|
||||
hashlib.sha256(domain_string).digest()[:SHORT_HASH_BYTES_SIZE])
|
||||
@@ -131,8 +121,7 @@ class Domain(BaseDomain):
|
||||
evaluated result.
|
||||
"""
|
||||
ctx = self.session.evaluation_context(context)
|
||||
if self.own:
|
||||
ctx.update(self.own)
|
||||
|
||||
try:
|
||||
return eval(self.get_domain_string(), SuperDict(ctx))
|
||||
except NameError as e:
|
||||
@@ -159,7 +148,7 @@ class Context(BaseContext):
|
||||
"and a domain string")
|
||||
|
||||
self.session = session
|
||||
self.own = {}
|
||||
|
||||
if context_string:
|
||||
self.key = binascii.hexlify(
|
||||
hashlib.sha256(context_string).digest()[:SHORT_HASH_BYTES_SIZE])
|
||||
@@ -179,8 +168,7 @@ class Context(BaseContext):
|
||||
evaluated result.
|
||||
"""
|
||||
ctx = self.session.evaluation_context(context)
|
||||
if self.own:
|
||||
ctx.update(self.own)
|
||||
|
||||
try:
|
||||
return eval(self.get_context_string(), SuperDict(ctx))
|
||||
except NameError as e:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
repo: 076b192d0d8ab2b92d1dbcfa3da055382f30eaea
|
||||
node: 5adb2d9c89e53a6445e3799f9c4dc9110458c149
|
||||
node: 1758bfec1ec1dcff95dcc4c72269cc0e3d000afd
|
||||
branch: default
|
||||
latesttag: 0.5
|
||||
latesttagdistance: 9
|
||||
latesttagdistance: 11
|
||||
|
||||
@@ -384,6 +384,21 @@ var py = {};
|
||||
return new py.def(val);
|
||||
}
|
||||
|
||||
switch(val.constructor) {
|
||||
case Object:
|
||||
var o = new py.object();
|
||||
for (var prop in val) {
|
||||
if (val.hasOwnProperty(prop)) {
|
||||
o[prop] = val[prop];
|
||||
}
|
||||
}
|
||||
return o;
|
||||
case Array:
|
||||
var a = new py.list();
|
||||
a.values = val;
|
||||
return a;
|
||||
}
|
||||
|
||||
throw new Error("Could not convert " + val + " to a pyval");
|
||||
}
|
||||
// Builtins
|
||||
@@ -448,7 +463,7 @@ var py = {};
|
||||
__getattribute__: function (name) {
|
||||
if (name in this) {
|
||||
var val = this[name];
|
||||
if ('__get__' in val) {
|
||||
if (typeof val === 'object' && '__get__' in val) {
|
||||
// TODO: second argument should be class
|
||||
return val.__get__(this);
|
||||
}
|
||||
@@ -627,6 +642,9 @@ var py = {};
|
||||
}
|
||||
return py.False;
|
||||
},
|
||||
__getitem__: function (index) {
|
||||
return PY_ensurepy(this.values[index.toJSON()]);
|
||||
},
|
||||
toJSON: function () {
|
||||
var out = [];
|
||||
for (var i=0; i<this.values.length; ++i) {
|
||||
@@ -846,7 +864,7 @@ var py = {};
|
||||
case '[':
|
||||
if (expr.second) {
|
||||
return py.evaluate(expr.first, context)
|
||||
.__getitem__(expr.evaluate(expr.second, context));
|
||||
.__getitem__(py.evaluate(expr.second, context));
|
||||
}
|
||||
var list_exprs = expr.first, list_values = [];
|
||||
for (var k=0; k<list_exprs.length; ++k) {
|
||||
|
||||
@@ -376,4 +376,13 @@ describe('numerical protocols', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('Type converter', function () {
|
||||
it('should convert bare objects to objects', function () {
|
||||
expect(py.eval('foo.bar', {foo: {bar: 3}})).to.be(3);
|
||||
});
|
||||
it('should convert arrays to lists', function () {
|
||||
expect(py.eval('foo[3]', {foo: [9, 8, 7, 6, 5]}))
|
||||
.to.be(6);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ openerp.web.core = function(openerp) {
|
||||
|
||||
// a function to override the "extend()" method of JR's inheritance, allowing
|
||||
// the usage of "include()"
|
||||
oe_override_class = function(claz){
|
||||
var oe_override_class = function(claz){
|
||||
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ?
|
||||
/\b_super\b/ : /.*/;
|
||||
|
||||
@@ -580,7 +580,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
|
||||
openerp.webclient.notification.warn('Context fail, report to xmo',
|
||||
_.str.sprintf(fail_template, {
|
||||
error: e.message,
|
||||
source: source.contexts
|
||||
source: JSON.stringify(source.contexts)
|
||||
}), true);
|
||||
}
|
||||
|
||||
@@ -598,7 +598,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
|
||||
openerp.webclient.notification.warn('Domain fail, report to xmo',
|
||||
_.str.sprintf(fail_template, {
|
||||
error: e.message,
|
||||
source: source.domains
|
||||
source: JSON.stringify(source.domains)
|
||||
}), true);
|
||||
}
|
||||
|
||||
@@ -616,40 +616,48 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
|
||||
openerp.webclient.notification.warn('GroupBy fail, report to xmo',
|
||||
_.str.sprintf(fail_template, {
|
||||
error: e.message,
|
||||
source: source.group_by_seq
|
||||
source: JSON.stringify(source.group_by_seq)
|
||||
}), true);
|
||||
}
|
||||
},
|
||||
test_eval_contexts: function (contexts) {
|
||||
var result_context = _.extend({}, this.user_context),
|
||||
self = this;
|
||||
_(contexts).each(function (ctx) {
|
||||
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':
|
||||
_.extend(result_context, py.eval(ctx.__debug));
|
||||
evaluated = py.eval(ctx.__debug, evaluation_context);
|
||||
break;
|
||||
case 'compound_context':
|
||||
_.extend(
|
||||
result_context, self.test_eval_contexts(ctx.__contexts));
|
||||
var eval_context = self.test_eval_contexts([ctx.__eval_context]);
|
||||
evaluated = self.test_eval_contexts(
|
||||
ctx.__contexts, _.extend({}, evaluation_context, eval_context));
|
||||
break;
|
||||
default:
|
||||
_.extend(result_context, ctx);
|
||||
}
|
||||
});
|
||||
return result_context;
|
||||
// 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, eval_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, eval_context));
|
||||
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, eval_context));
|
||||
dom.__domains, _.extend(
|
||||
{}, evaluation_context, eval_context)));
|
||||
break;
|
||||
default:
|
||||
result_domain.push.apply(
|
||||
@@ -667,7 +675,8 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
|
||||
group = py.eval(ctx.__debug).group_by;
|
||||
break;
|
||||
case 'compound_context':
|
||||
group = self.test_eval_contexts(ctx.__contexts).group_by;
|
||||
group = self.test_eval_contexts(
|
||||
ctx.__contexts, ctx.__eval_context).group_by;
|
||||
break;
|
||||
default:
|
||||
group = ctx.group_by
|
||||
|
||||
@@ -787,9 +787,8 @@ openerp.web.search.Field = openerp.web.search.Input.extend( /** @lends openerp.w
|
||||
if (!(has_value && context)) {
|
||||
return;
|
||||
}
|
||||
return _.extend(
|
||||
{}, context,
|
||||
{own_values: {self: val}});
|
||||
return new openerp.web.CompoundContext(context)
|
||||
.set_eval_context({self: val});
|
||||
},
|
||||
/**
|
||||
* Function creating the returned domain for the field, override this
|
||||
@@ -818,7 +817,8 @@ openerp.web.search.Field = openerp.web.search.Input.extend( /** @lends openerp.w
|
||||
this.attrs.operator || this.default_operator,
|
||||
val);
|
||||
}
|
||||
return _.extend({}, domain, {own_values: {self: val}});
|
||||
return new openerp.web.CompoundDomain(domain)
|
||||
.set_eval_context({self: val});
|
||||
}
|
||||
});
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
$(document).ready(function () {
|
||||
var openerp;
|
||||
|
||||
module("eval.contexts", {
|
||||
setup: function () {
|
||||
openerp = window.openerp.init();
|
||||
window.openerp.web.core(openerp);
|
||||
}
|
||||
});
|
||||
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([
|
||||
{
|
||||
"__contexts": [
|
||||
{
|
||||
"department_id": false,
|
||||
"lang": "en_US",
|
||||
"project_id": false,
|
||||
"section_id": false,
|
||||
"tz": false,
|
||||
"uid": 1
|
||||
},
|
||||
{ "search_default_create_uid": 1 },
|
||||
{}
|
||||
],
|
||||
"__eval_context": null,
|
||||
"__ref": "compound_context"
|
||||
},
|
||||
{
|
||||
"active_id": active_id,
|
||||
"active_ids": [ active_id ],
|
||||
"active_model": "purchase.requisition"
|
||||
},
|
||||
{
|
||||
"__debug": "{'record_id' : active_id}",
|
||||
"__id": "63e8e9bff8a6",
|
||||
"__ref": "context"
|
||||
}
|
||||
]);
|
||||
|
||||
deepEqual(result, {
|
||||
department_id: false,
|
||||
lang: 'en_US',
|
||||
project_id: false,
|
||||
section_id: false,
|
||||
tz: false,
|
||||
uid: 1,
|
||||
search_default_create_uid: 1,
|
||||
active_id: active_id,
|
||||
active_ids: [active_id],
|
||||
active_model: 'purchase.requisition',
|
||||
record_id: active_id
|
||||
});
|
||||
});
|
||||
test('non-literal_eval_contexts', function () {
|
||||
var result = openerp.connection.test_eval_contexts([{
|
||||
"__ref": "compound_context",
|
||||
"__contexts": [
|
||||
{"__ref": "context", "__debug": "{'type':parent.type}",
|
||||
"__id": "462b9dbed42f"}
|
||||
],
|
||||
"__eval_context": {
|
||||
"__ref": "compound_context",
|
||||
"__contexts": [{
|
||||
"__ref": "compound_context",
|
||||
"__contexts": [
|
||||
{"__ref": "context", "__debug": "{'type': type}",
|
||||
"__id": "16a04ed5a194"}
|
||||
],
|
||||
"__eval_context": {
|
||||
"__ref": "compound_context",
|
||||
"__contexts": [
|
||||
{"lang": "en_US", "tz": false, "uid": 1,
|
||||
"journal_type": "sale", "section_id": false,
|
||||
"default_type": "out_invoice",
|
||||
"type": "out_invoice", "department_id": false},
|
||||
{"id": false, "journal_id": 10,
|
||||
"number": false, "type": "out_invoice",
|
||||
"currency_id": 1, "partner_id": 4,
|
||||
"fiscal_position": false,
|
||||
"date_invoice": false, "period_id": false,
|
||||
"payment_term": false, "reference_type": "none",
|
||||
"reference": false, "account_id": 440,
|
||||
"name": false, "invoice_line": [],
|
||||
"tax_line": [], "amount_untaxed": 0,
|
||||
"amount_tax": 0, "reconciled": false,
|
||||
"amount_total": 0, "state": "draft",
|
||||
"residual": 0, "company_id": 1,
|
||||
"date_due": false, "user_id": 1,
|
||||
"partner_bank_id": false, "origin": false,
|
||||
"move_id": false, "comment": false,
|
||||
"payment_ids": [[6, false, []]],
|
||||
"active_id": false, "active_ids": [],
|
||||
"active_model": "account.invoice",
|
||||
"parent": {}}
|
||||
], "__eval_context": null}
|
||||
}, {
|
||||
"id": false,
|
||||
"product_id": 4,
|
||||
"name": "[PC1] Basic PC",
|
||||
"quantity": 1,
|
||||
"uos_id": 1,
|
||||
"price_unit": 100,
|
||||
"account_id": 853,
|
||||
"discount": 0,
|
||||
"account_analytic_id": false,
|
||||
"company_id": false,
|
||||
"note": false,
|
||||
"invoice_line_tax_id": [[6, false, [1]]],
|
||||
"active_id": false,
|
||||
"active_ids": [],
|
||||
"active_model": "account.invoice.line",
|
||||
"parent": {
|
||||
"id": false, "journal_id": 10, "number": false,
|
||||
"type": "out_invoice", "currency_id": 1,
|
||||
"partner_id": 4, "fiscal_position": false,
|
||||
"date_invoice": false, "period_id": false,
|
||||
"payment_term": false, "reference_type": "none",
|
||||
"reference": false, "account_id": 440, "name": false,
|
||||
"tax_line": [], "amount_untaxed": 0, "amount_tax": 0,
|
||||
"reconciled": false, "amount_total": 0,
|
||||
"state": "draft", "residual": 0, "company_id": 1,
|
||||
"date_due": false, "user_id": 1,
|
||||
"partner_bank_id": false, "origin": false,
|
||||
"move_id": false, "comment": false,
|
||||
"payment_ids": [[6, false, []]]}
|
||||
}],
|
||||
"__eval_context": null
|
||||
}
|
||||
}]);
|
||||
deepEqual(result, {type: 'out_invoice'});
|
||||
});
|
||||
});
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
<script src="/web/static/lib/qweb/qweb2.js"></script>
|
||||
|
||||
<script src="/web/static/lib/py.parse/lib/py.js"></script>
|
||||
<script src="/web/static/lib/py.js/lib/py.js"></script>
|
||||
|
||||
<script src="/web/static/lib/novajs/src/nova.js"></script>
|
||||
|
||||
<script src="/web/static/src/js/boot.js"></script>
|
||||
<script src="/web/static/src/js/core.js"></script>
|
||||
@@ -51,4 +53,5 @@
|
||||
<script type="text/javascript" src="/web/static/test/list-utils.js"></script>
|
||||
<script type="text/javascript" src="/web/static/test/formats.js"></script>
|
||||
<script type="text/javascript" src="/web/static/test/onchange.js"></script>
|
||||
<script type="text/javascript" src="/web/static/test/evals.js"></script>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user