From d32d0c5637e0b7d85c97278e4479d4e5f8ff1d69 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Sep 2011 15:54:49 +0200 Subject: [IMP] update py.parse to 0.2 bzr revid: xmo@openerp.com-20110929135449-ssommvnyof6auy29 --- addons/web/static/lib/py.parse/.hg_archival.txt | 5 + addons/web/static/lib/py.parse/README | 1 + addons/web/static/lib/py.parse/TODO.rst | 14 +++ addons/web/static/lib/py.parse/lib/py.js | 116 ++++++++++++++++++------ addons/web/static/lib/py.parse/test/test.js | 90 ++++++++++++++++++ 5 files changed, 196 insertions(+), 30 deletions(-) create mode 100644 addons/web/static/lib/py.parse/.hg_archival.txt create mode 100644 addons/web/static/lib/py.parse/README create mode 100644 addons/web/static/lib/py.parse/TODO.rst create mode 100644 addons/web/static/lib/py.parse/test/test.js (limited to 'addons/web/static/lib/py.parse') diff --git a/addons/web/static/lib/py.parse/.hg_archival.txt b/addons/web/static/lib/py.parse/.hg_archival.txt new file mode 100644 index 00000000000..43d5d80a9e4 --- /dev/null +++ b/addons/web/static/lib/py.parse/.hg_archival.txt @@ -0,0 +1,5 @@ +repo: 076b192d0d8ab2b92d1dbcfa3da055382f30eaea +node: 87fb1b67d6a13f10a1a328104ee4d4b2c36801ec +branch: default +latesttag: 0.2 +latesttagdistance: 1 diff --git a/addons/web/static/lib/py.parse/README b/addons/web/static/lib/py.parse/README new file mode 100644 index 00000000000..453f001ee15 --- /dev/null +++ b/addons/web/static/lib/py.parse/README @@ -0,0 +1 @@ +Parser and evaluator of Python expressions diff --git a/addons/web/static/lib/py.parse/TODO.rst b/addons/web/static/lib/py.parse/TODO.rst new file mode 100644 index 00000000000..3638b681ddc --- /dev/null +++ b/addons/web/static/lib/py.parse/TODO.rst @@ -0,0 +1,14 @@ +* Parser + since parsing expressions, try with a pratt parser + http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ + http://effbot.org/zone/simple-top-down-parsing.htm + +Evaluator +--------- + +* Stop busyworking trivial binary operator +* Make it *trivial* to build Python type-wrappers +* Implement Python's `data model + protocols`_ + for *all* supported operations, optimizations can come later +* Automatically type-wrap everything (for now anyway) diff --git a/addons/web/static/lib/py.parse/lib/py.js b/addons/web/static/lib/py.parse/lib/py.js index d5cf304bb58..0f2415f1252 100644 --- a/addons/web/static/lib/py.parse/lib/py.js +++ b/addons/web/static/lib/py.parse/lib/py.js @@ -5,7 +5,7 @@ var py = {}; NAME = /^[a-zA-Z0-9_]$/; var create = function (o, props) { - function F() {}; + function F() {} F.prototype = o; var inst = new F; for(var name in props) { @@ -13,7 +13,7 @@ var py = {}; inst[name] = props[name]; } return inst; - } + }; var symbols = {}; var comparators = {}; @@ -26,17 +26,17 @@ var py = {}; } else if (this.id === '(end)') { return '(end)'; } else if (this.id === '(comparator)' ) { - var out = ['(comparator', this.expressions[0]]; + var repr = ['(comparator', this.expressions[0]]; for (var i=0;i': return a > b; case '>=': return a >= b; - case 'in': return b.__contains__(a); - case 'not in': return !b.__contains__(a); + case 'in': + if (typeof b === 'string') { + return b.indexOf(a) !== -1; + } + return b.__contains__(a); + case 'not in': + if (typeof b === 'string') { + return b.indexOf(a) === -1; + } + return !b.__contains__(a); } throw new Error('SyntaxError: unknown comparator [[' + operator + ']]'); - } + }; exports.evaluate = function (expr, context) { switch (expr.id) { case '(name)': @@ -444,6 +463,14 @@ var py = {}; case '(string)': case '(number)': return expr.value; + case '(constant)': + if (expr.value === 'None') + return null; + else if (expr.value === 'False') + return false; + else if (expr.value === 'True') + return true; + throw new Error("SyntaxError: unknown constant '" + expr.value + "'"); case '(comparator)': var result, left = exports.evaluate(expr.expressions[0], context); for(var i=0; i= 3')); +assert.ok(py.eval('3 >= 3')); +assert.ok(!py.eval('5 < 3')); +assert.ok(py.eval('1 < 3 < 5')); +assert.ok(py.eval('5 > 3 > 1')); +assert.ok(py.eval('1 < 3 > 2 == 2 > -2 not in (0, 1, 2)')); +// string rich comparisons +assert.ok(py.eval( + 'date >= current', {date: '2010-06-08', current: '2010-06-05'})); + +// Boolean operators +assert.ok(py.eval( + "foo == 'foo' or foo == 'bar'", {foo: 'bar'})); +assert.ok(py.eval( + "foo == 'foo' and bar == 'bar'", {foo: 'foo', bar: 'bar'})); +// - lazyness, second clauses NameError if not short-circuited +assert.ok(py.eval( + "foo == 'foo' or bar == 'bar'", {foo: 'foo'})); +assert.ok(!py.eval( + "foo == 'foo' and bar == 'bar'", {foo: 'bar'})); + +// contains (in) +assert.ok(py.eval( + "foo in ('foo', 'bar')", {foo: 'bar'})); +assert.ok(py.eval('1 in (1, 2, 3, 4)')); +assert.ok(!py.eval('1 in (2, 3, 4)')); +assert.ok(py.eval('type in ("url",)', {type: 'url'})); +assert.ok(!py.eval('type in ("url",)', {type: 'ur'})); +assert.ok(py.eval('1 not in (2, 3, 4)')); +assert.ok(py.eval('type not in ("url",)', {type: 'ur'})); + +assert.ok(py.eval( + "foo in ['foo', 'bar']", {foo: 'bar'})); +// string contains +assert.ok(py.eval('type in "view"', {type: 'view'})); +assert.ok(!py.eval('type in "view"', {type: 'bob'})); +assert.ok(py.eval('type in "url"', {type: 'ur'})); + +// Literals +assert.strictEqual(py.eval('False'), false); +assert.strictEqual(py.eval('True'), true); +assert.strictEqual(py.eval('None'), null); +assert.ok(py.eval('foo == False', {foo: false})); +assert.ok(!py.eval('foo == False', {foo: true})); + +// conversions +assert.strictEqual( + py.eval('bool(date_deadline)', {bool: py.bool, date_deadline: '2008'}), + true); + +// getattr +assert.ok(py.eval('foo.bar', {foo: {bar: true}})); +assert.ok(!py.eval('foo.bar', {foo: {bar: false}})); + +// complex expressions +assert.ok(py.eval( + "state=='pending' and not(date_deadline and (date_deadline < current_date))", + {state: 'pending', date_deadline: false})); +assert.ok(py.eval( + "state=='pending' and not(date_deadline and (date_deadline < current_date))", + {state: 'pending', date_deadline: '2010-05-08', current_date: '2010-05-08'}));; -- cgit v1.2.3