diff --git a/js/pyson.js b/js/pyson.js
new file mode 100644
index 0000000000..90e5044c2d
--- /dev/null
+++ b/js/pyson.js
@@ -0,0 +1,632 @@
+/* This file is part of Tryton. The COPYRIGHT file at the top level of
+ this repository contains the full copyright notices and license terms. */
+'use strict';
+
+Sao.PYSON = {};
+
+Sao.PYSON.PYSON = Class(Object, {
+ init: function() {
+ },
+ pyson: function() {
+ throw 'NotImplementedError';
+ },
+ types: function() {
+ throw 'NotImplementedError';
+ }
+});
+
+Sao.PYSON.PYSON.eval = function(value, context) {
+ throw 'NotImplementedError';
+};
+
+Sao.PYSON.Encoder = Class(Object, {
+ encode: function(pyson) {
+ return JSON.stringify(pyson, function(k, v) {
+ if (v instanceof Sao.PYSON.PYSON) {
+ return v.pyson();
+ } else if (v instanceof Date) {
+ if (v.getHours() || v.getMinutes() || v.getSeconds() ||
+ v.getMilliseconds()) {
+ return Sao.PYSON.DateTime(
+ v.getFullYear(),
+ v.getMonth(),
+ v.getDate(),
+ v.getHours(),
+ v.getMinutes(),
+ v.getSeconds(),
+ v.getMilliseconds()).pyson();
+ } else {
+ return Sao.PYSON.DateTime(
+ v.getFullYear(),
+ v.getMonth(),
+ v.getDate()).pyson();
+ }
+ }
+ return v;
+ });
+ }
+});
+
+Sao.PYSON.Decoder = Class(Object, {
+ init: function(context) {
+ this.__context = context || {};
+ },
+ decode: function(str) {
+ var reviver = function(k, v) {
+ if (typeof v == 'object') {
+ var cls = Sao.PYSON[v.__class__];
+ if (cls) {
+ return cls.eval(v, this.__context);
+ }
+ }
+ return v;
+ };
+ return JSON.parse(str, reviver.bind(this));
+ }
+});
+
+Sao.PYSON.Eval = Class(Sao.PYSON.PYSON, {
+ init: function(value, default_) {
+ if (default_ === undefined) {
+ default_ = '';
+ }
+ Sao.PYSON.Eval._super.init.call(this);
+ this._value = value;
+ this._default = default_;
+ },
+ pyson: function() {
+ return {
+ '__class__': 'Eval',
+ 'v': this._value,
+ 'd': this._default
+ };
+ },
+ types: function() {
+ if (this._default instanceof Sao.PYSON.PYSON) {
+ return this._default.types();
+ } else {
+ return [typeof this._default];
+ }
+ }
+});
+
+Sao.PYSON.Eval.eval = function(value, context) {
+ if (value.v in context) {
+ return context[value.v];
+ } else {
+ return value.d;
+ }
+};
+
+Sao.PYSON.Not = Class(Sao.PYSON.PYSON, {
+ init: function(value) {
+ Sao.PYSON.Not._super.init.call(this);
+ if (value instanceof Sao.PYSON.PYSON) {
+ if ((jQuery(value.types()).not(['boolean']).length != 0) ||
+ (jQuery(['boolean']).not(value.types()).length != 0)) {
+ throw 'value must be boolean';
+ }
+ } else {
+ if (typeof value != 'boolean') {
+ throw 'value must be boolean';
+ }
+ }
+ this._value = value;
+ },
+ pyson: function() {
+ return {
+ '__class__': 'Not',
+ 'v': this._value
+ };
+ },
+ types: function() {
+ return ['boolean'];
+ }
+});
+
+Sao.PYSON.Not.eval = function(value, context) {
+ return !value.v;
+};
+
+Sao.PYSON.Bool = Class(Sao.PYSON.PYSON, {
+ init: function(value) {
+ Sao.PYSON.Bool._super.init.call(this);
+ this._value = value;
+ },
+ pyson: function() {
+ return {
+ '__class__': 'Bool',
+ 'v': this._value
+ };
+ },
+ types: function() {
+ return ['boolean'];
+ }
+});
+
+Sao.PYSON.Bool.eval = function(value, context) {
+ if (value.v instanceof Object) {
+ return !jQuery.isEmptyObject(value.v);
+ } else {
+ return Boolean(value.v);
+ }
+};
+
+
+Sao.PYSON.And = Class(Sao.PYSON.PYSON, {
+ init: function(statements) {
+ Sao.PYSON.And._super.init.call(this);
+ for (var i = 0, len = statements.length; i < len; i++) {
+ var statement = statements[i];
+ if (statement instanceof Sao.PYSON.PYSON) {
+ if ((jQuery(statement.types()).not(['boolean']).length != 0) ||
+ (jQuery(['boolean']).not(statement.types()).length != 0)) {
+ throw 'statement must be boolean';
+ }
+ } else {
+ if (typeof statement != 'boolean') {
+ throw 'statement must be boolean';
+ }
+ }
+ }
+ if (statements.length < 2) {
+ throw 'must have at least 2 statements';
+ }
+ this._statements = statements;
+ },
+ pyson: function() {
+ return {
+ '__class__': 'And',
+ 's': this._statements
+ };
+ },
+ types: function() {
+ return ['boolean'];
+ }
+});
+
+Sao.PYSON.And.eval = function(value, context) {
+ var result = true;
+ for (var i = 0, len = value.s.length; i < len; i++) {
+ var statement = value.s[i];
+ result = result && statement;
+ }
+ return result;
+};
+
+
+Sao.PYSON.Or = Class(Sao.PYSON.And, {
+ pyson: function() {
+ var result = Sao.PYSON.Or._super.pyson.call(this);
+ result['__class__'] = 'Or';
+ return result;
+ }
+});
+
+Sao.PYSON.Or.eval = function(value, context) {
+ var result = false;
+ for (var i = 0, len = value.s.length; i < len; i++) {
+ var statement = value.s[i];
+ result = result || statement;
+ }
+ return result;
+};
+
+Sao.PYSON.Equal = Class(Sao.PYSON.PYSON, {
+ init: function(statement1, statement2) {
+ Sao.PYSON.Equal._super.init.call(this);
+ if (statement1 instanceof Sao.PYSON.PYSON) {
+ var types1 = statement1.types();
+ } else {
+ var types1 = [typeof statement1];
+ }
+ if (statement2 instanceof Sao.PYSON.PYSON) {
+ var types2 = statement2.types();
+ } else {
+ var types2 = [typeof statement2];
+ }
+ if ((jQuery(types1).not(types2).length != 0) ||
+ (jQuery(types2).not(types1).length != 0)) {
+ throw 'statements must have the same type';
+ }
+ this._statement1 = statement1;
+ this._statement2 = statement2;
+ },
+ pyson: function() {
+ return {
+ '__class__': 'Equal',
+ 's1': this._statement1,
+ 's2': this._statement2
+ };
+ },
+ types: function() {
+ return ['boolean'];
+ }
+});
+
+Sao.PYSON.Equal.eval = function(value, context) {
+ return value.s1 == value.s2;
+};
+
+Sao.PYSON.Greater = Class(Sao.PYSON.PYSON, {
+ init: function(statement1, statement2, equal) {
+ Sao.PYSON.Greater._super.init.call(this);
+ var statements = [statement1, statement2];
+ for (var i = 0; i < 2; i++) {
+ var statement = statements[i];
+ if (statement instanceof Sao.PYSON.PYSON) {
+ if (jQuery(statement).not([int, float]).length != 0) {
+ throw 'statement must be an integer or a float';
+ }
+ } else {
+ if (typeof statement != 'number') {
+ throw 'statement must be an integer or a float';
+ }
+ }
+ }
+ if (equal === undefined) {
+ equal = false;
+ }
+ if (equal instanceof Sao.PYSON.PYSON) {
+ if ((jQuery(equal.types()).not(['boolean']).length != 0) ||
+ (jQuery(['boolean']).not(equal.types()).length != 0)) {
+ throw 'equal must be boolean';
+ }
+ } else {
+ if (typeof equal != 'boolean') {
+ throw 'equal must be boolean';
+ }
+ }
+ this._statement1 = statement1;
+ this._statement2 = statement2;
+ this._equal = equal;
+ },
+ pyson: function() {
+ return {
+ '__class__': 'Greater',
+ 's1': this._statement1,
+ 's2': this._statement2,
+ 'e': this._equal
+ };
+ },
+ types: function() {
+ return ['boolean'];
+ }
+});
+
+Sao.PYSON.Greater._convert = function(value) {
+ value = jQuery.extend({}, value);
+ value.s1 = Number(value.s1);
+ value.s2 = Number(value.s2);
+ return value;
+};
+
+Sao.PYSON.Greater.eval = function(value, context) {
+ value = Sao.PYSON.Greater._convert(value);
+ if (value.e) {
+ return value.s1 >= value.s2;
+ } else {
+ return value.s1 > value.s2;
+ }
+};
+
+Sao.PYSON.Less = Class(Sao.PYSON.Greater, {
+ pyson: function() {
+ var result = Sao.PYSON.Less._super.pyson.call(this);
+ result['__class__'] = 'Less';
+ return result;
+ }
+});
+
+Sao.PYSON.Less._convert = Sao.PYSON.Greater._convert;
+
+Sao.PYSON.Less.eval = function(value, context) {
+ value = Sao.PYSON.Less._convert(value);
+ if (value.e) {
+ return value.s1 <= value.s2;
+ } else {
+ return value.s1 < value.s2;
+ }
+};
+
+Sao.PYSON.If = Class(Sao.PYSON.PYSON, {
+ init: function(condition, then_statement, else_statement) {
+ Sao.PYSON.If._super.init.call(this);
+ if (condition instanceof Sao.PYSON.PYSON) {
+ if ((jQuery(condition.types()).not(['boolean']).length != 0) ||
+ (jQuery(['boolean']).not(condition.types()).length != 0)) {
+ throw 'condition must be boolean';
+ }
+ } else {
+ if (typeof condition != 'boolean') {
+ throw 'condition must be boolean';
+ }
+ }
+ if (then_statement instanceof Sao.PYSON.PYSON) {
+ var then_types = then_statement.types();
+ } else {
+ var then_types = [typeof then_statement];
+ }
+ if (else_statement === undefined) {
+ else_statement = null;
+ }
+ if (else_statement instanceof Sao.PYSON.PYSON) {
+ var else_types = else_statement.types();
+ } else {
+ var else_types = [typeof else_statement];
+ }
+ if ((jQuery(then_types).not(else_types).length != 0) ||
+ (jQuery(else_types).not(then_types).length != 0)) {
+ throw 'then and else statements must be the same type';
+ }
+ this._condition = condition;
+ this._then_statement = then_statement;
+ this._else_statement = else_statement;
+ },
+ pyson: function() {
+ return {
+ '__class__': 'If',
+ 'c': this._condition,
+ 't': this._then_statement,
+ 'e': this._else_statement
+ };
+ },
+ types: function() {
+ if (this._then_statement instanceof Sao.PYSON.PYSON) {
+ return this._then_statement.types();
+ } else {
+ return [typeof this._then_statement];
+ }
+ }
+});
+
+Sao.PYSON.If.eval = function(value, context) {
+ if (value.c) {
+ return value.t;
+ } else {
+ return value.e;
+ }
+};
+
+Sao.PYSON.Get = Class(Sao.PYSON.PYSON, {
+ init: function(obj, key, default_) {
+ Sao.PYSON.Get._super.init.call(this);
+ if (default_ === undefined) {
+ default_ = null;
+ }
+ if (obj instanceof Sao.PYSON.PYSON) {
+ if ((jQuery(obj.types()).not(['object']).length != 0) ||
+ (jQuery(['object']).not(obj.types()).length != 0)) {
+ throw 'obj must be a dict';
+ }
+ } else {
+ if (!(obj instanceof Object)) {
+ throw 'obj must be a dict';
+ }
+ }
+ this._obj = obj;
+ if (key instanceof Sao.PYSON.PYSON) {
+ if ((jQuery(key.types()).not(['string']).length != 0) ||
+ (jQuery(['string']).not(key.types()).length != 0)) {
+ throw 'key must be a string';
+ }
+ } else {
+ if (typeof key != 'string') {
+ throw 'key must be a string';
+ }
+ }
+ this._key = key;
+ this._default = default_;
+ },
+ pyson: function() {
+ return {
+ '__class__': 'Get',
+ 'v': this._obj,
+ 'k': this._key,
+ 'd': this._default
+ };
+ },
+ types: function() {
+ if (this._default instanceof Sao.PYSON.PYSON) {
+ return this._default.types();
+ } else {
+ return [typeof this._default];
+ }
+ }
+});
+
+Sao.PYSON.Get.eval = function(value, context) {
+ if (value.k in value.v) {
+ return value.v[value.k];
+ } else {
+ return value.d;
+ }
+};
+
+Sao.PYSON.In = Class(Sao.PYSON.PYSON, {
+ init: function(key, obj) {
+ Sao.PYSON.In._super.init.call(this);
+ if (key instanceof Sao.PYSON.PYSON) {
+ if (jQuery(key.types()).not(['string', 'number']).length != 0) {
+ throw 'key must be a string or a number';
+ }
+ } else {
+ if (['string', 'number'].indexOf(typeof key) < 0) {
+ throw 'key must be a string or a number';
+ }
+ }
+ if (obj instanceof Sao.PYSON.PYSON) {
+ if ((jQuery(obj.types()).not(['object']).length != 0) ||
+ (jQuery(['object']).not(obj.types()).length != 0)) {
+ throw 'obj must be a dict or a list';
+ }
+ } else {
+ if (!(obj instanceof Object)) {
+ throw 'obj must be a dict or a list';
+ }
+ }
+ this._key = key;
+ this._obj = obj;
+ },
+ pyson: function() {
+ return {'__class__': 'In',
+ 'k': this._key,
+ 'v': this._obj
+ };
+ },
+ types: function() {
+ return ['boolean'];
+ }
+});
+
+Sao.PYSON.In.eval = function(value, context) {
+ if (value.v.indexOf) {
+ return value.v.indexOf(value.k) >= 0;
+ } else {
+ return !!value.v[value.k];
+ }
+};
+
+Sao.PYSON.Date = Class(Sao.PYSON.PYSON, {
+ init: function(year, month, day, delta_years, delta_months, delta_days) {
+ Sao.PYSON.Date._super.init.call(this);
+ if (year === undefined) year = null;
+ if (month === undefined) month = null;
+ if (day === undefined) day = null;
+ if (delta_years === undefined) delta_years = 0;
+ if (delta_months === undefined) delta_months = 0;
+ if (delta_days === undefined) delta_days = 0;
+
+ this._test(year, 'year');
+ this._test(month, 'month');
+ this._test(day, 'day');
+ this._test(delta_years, 'delta_years');
+ this._test(delta_days, 'delta_days');
+ this._test(delta_months, 'delta_months');
+
+ this._year = year;
+ this._month = month;
+ this._day = day;
+ this._delta_years = delta_years;
+ this._delta_months = delta_months;
+ this._delta_days = delta_days;
+ },
+ pyson: function() {
+ return {
+ '__class__': 'Date',
+ 'y': this._year,
+ 'M': this._month,
+ 'd': this._day,
+ 'dy': this._delta_years,
+ 'dM': this._delta_months,
+ 'dd': this._delta_days
+ };
+ },
+ types: function() {
+ return ['object'];
+ },
+ _test: function(value, name) {
+ if (value instanceof Sao.PYSON.PYSON) {
+ if (jQuery(value.types()).not(
+ ['number', typeof null]).length != 0) {
+ throw name + ' must be an integer or None';
+ }
+ } else {
+ if ((typeof value != 'number') && (value !== null)) {
+ throw name + ' must be an integer or None';
+ }
+ }
+ }
+});
+
+Sao.PYSON.Date.eval = function(value, context) {
+ var date = new Date();
+ date.setHours(0);
+ date.setMinutes(0);
+ date.setSeconds(0);
+ date.setMilliseconds(0);
+ if (value.y) date.setFullYear(value.y);
+ if (value.M) date.setMonth(value.M);
+ if (value.d) date.setDate(value.d);
+ var year = date.getFullYear();
+ var month = date.getMonth();
+ var day = date.getDate();
+ if (value.dy) date.setFullYear(year + value.dy);
+ if (value.dM) date.setMonth(month + value.dM);
+ if (value.dd) date.setDate(day + value.dd);
+ return date;
+};
+
+Sao.PYSON.DateTime = Class(Sao.PYSON.Date, {
+ init: function(year, month, day, hour, minute, second, microsecond,
+ delta_years, delta_months, delta_days, delta_hours,
+ delta_minutes, delta_seconds, delta_microseconds) {
+ Sao.PYSON.DateTime._super.init.call(this, year, month, day,
+ delta_years, delta_months, delta_days);
+ if (hour === undefined) hour = null;
+ if (minute === undefined) minute = null;
+ if (second === undefined) second = null;
+ if (microsecond === undefined) microsecond = null;
+ if (delta_hours === undefined) delta_hours = 0;
+ if (delta_minutes === undefined) delta_minutes = 0;
+ if (delta_seconds === undefined) delta_seconds = 0;
+ if (delta_microseconds === undefined) delta_microseconds = 0;
+
+ this._test(hour, 'hour');
+ this._test(minute, 'minute');
+ this._test(second, 'second');
+ this._test(microsecond, 'microsecond');
+ this._test(delta_hours, 'delta_hours');
+ this._test(delta_minutes, 'delta_minutes');
+ this._test(delta_seconds, 'delta_seconds');
+ this._test(delta_microseconds, 'delta_microseconds');
+
+ this._hour = hour;
+ this._minute = minute;
+ this._second = second;
+ this._microsecond = microsecond;
+ this._delta_hours = delta_hours;
+ this._delta_minutes = delta_minutes;
+ this._delta_seconds = delta_seconds;
+ this._delta_microseconds = delta_microseconds;
+ },
+ pyson: function() {
+ var result = Sao.PYSON.DateTime._super.pyson.call(this);
+ result['__class__'] = 'DateTime';
+ result['h'] = this._hour;
+ result['m'] = this._minute;
+ result['s'] = this._second;
+ result['ms'] = this._microsecond;
+ result['dh'] = this._delta_hours;
+ result['dm'] = this._delta_minutes;
+ result['ds'] = this._delta_seconds;
+ result['dms'] = this._delta_microseconds;
+ return result;
+ }
+});
+
+Sao.PYSON.DateTime.eval = function(value, context) {
+ var date = new Date();
+ if (value.y) date.setFullYear(value.y);
+ if (value.M) date.setMonth(value.M);
+ if (value.d) date.setDate(value.d);
+ if (value.h !== undefined) date.setHours(value.h);
+ if (value.m !== undefined) date.setMinutes(value.m);
+ if (value.s !== undefined) date.setSeconds(value.s);
+ if (value.ms !== undefined) date.setMilliseconds(value.ms / 100);
+ var year = date.getFullYear();
+ var month = date.getMonth();
+ var day = date.getDate();
+ var hour = date.getHours();
+ var minute = date.getMinutes();
+ var second = date.getSeconds();
+ var millisecond = date.getMilliseconds();
+ if (value.dy) date.setFullYear(year + value.dy);
+ if (value.dM) date.setMonth(month + value.dM);
+ if (value.dd) date.setDate(day + value.dd);
+ if (value.dh) date.setHours(hour + value.dh);
+ if (value.dm) date.setMinutes(minute + value.dm);
+ if (value.ds) date.setSeconds(second + value.ds);
+ if (value.dms) date.setMilliseconds(millisecond + value.dms / 100);
+ return date;
+};
diff --git a/tests/index.html b/tests/index.html
index 92f77b3f59..3b1de9ca75 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -21,6 +21,7 @@ this repository contains the full copyright notices and license terms. -->
+
diff --git a/tests/sao.js b/tests/sao.js
index afeb235188..bc2bf1c955 100644
--- a/tests/sao.js
+++ b/tests/sao.js
@@ -10,6 +10,11 @@ var SaoTest = {
'dbname': 'test_' + new Date().getTime()
};
+SaoTest.compare = function(arr1, arr2) {
+ return (jQuery(arr1).not(arr2).length == 0 &&
+ jQuery(arr2).not(arr1).length == 0);
+};
+
QUnit.test('JSON', function() {
var tests = {
'array': [1, 2, 3],
@@ -29,6 +34,708 @@ QUnit.test('JSON', function() {
}
});
+QUnit.test('PYSON.Eval', function() {
+ var value = new Sao.PYSON.Eval('test').pyson();
+ QUnit.strictEqual(value.__class__, 'Eval', "Eval('test').pyson()");
+ QUnit.strictEqual(value.v, 'test', "Eval('test').pyson()");
+ QUnit.strictEqual(value.d, '', "Eval('test').pyson()");
+ var value = new Sao.PYSON.Eval('test', 'foo').pyson();
+ QUnit.strictEqual(value.__class__, 'Eval', "Eval('test', 'foo').pyson()");
+ QUnit.strictEqual(value.v, 'test', "Eval('test', 'foo').pyson()");
+ QUnit.strictEqual(value.d, 'foo', "Eval('test', 'foo').pyson()");
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.Eval('test', 'foo').types(),
+ [typeof 'foo']), "Eval('test', 'foo').types()");
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.Eval('test', 1).types(),
+ [typeof 1]), "Eval('test', 1).types()");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Eval('test', 0));
+ QUnit.strictEqual(new Sao.PYSON.Decoder({test: 1}).decode(eval_), 1,
+ "decode(Eval('test', 0))");
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), 0,
+ "decode(Eval('test', 0))");
+});
+
+QUnit.test('PYSON Not', function() {
+ var value = new Sao.PYSON.Not(true).pyson();
+ QUnit.strictEqual(value.__class__, 'Not', 'Not(true).pyson()');
+ QUnit.strictEqual(value.v, true, 'Not(true).pyson()');
+
+ QUnit.throws(function() {
+ new Sao.PYSON.Not('foo');
+ }, 'value must be boolean', "Not('foo')");
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.Not(true).types(), ['boolean']),
+ 'Not(true).types()');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Not(true));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Not(true))');
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Not(false));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Not(false))');
+});
+
+QUnit.test('PYSON Bool', function() {
+ var value = new Sao.PYSON.Bool('test').pyson();
+ QUnit.strictEqual(value.__class__, 'Bool', "Bool('test').pyson()");
+ QUnit.strictEqual(value.v, 'test', "Bool('test').pyson()");
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.Bool('test').types(), ['boolean']),
+ "Bool('test').types()");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Bool(true));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Bool(true))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Bool(false));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Bool(false))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Bool('test'));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ "decode(Bool('test'))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Bool(''));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ "decode(Bool(''))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Bool(1));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Bool(1))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Bool(0));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Bool(0))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Bool(['test']));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ "decode(Bool(['test']))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Bool([]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Bool([]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Bool({foo: 'bar'}));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ "decode(Bool({foo: 'bar'}))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Bool({}));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Bool({}))');
+});
+
+QUnit.test('PYSON And', function() {
+ var value = new Sao.PYSON.And([true, false]).pyson();
+ QUnit.strictEqual(value.__class__, 'And', 'And([true, false]).pyson()');
+ QUnit.ok(SaoTest.compare(value.s, [true, false]),
+ 'And([true, false]).pyson()');
+
+ QUnit.throws(function() {
+ new Sao.PYSON.And(['test', false]);
+ }, 'statement must be boolean', "And(['test', false])");
+ QUnit.throws(function() {
+ new Sao.PYSON.And([true, 'test']);
+ }, 'statement must be boolean', "And([true, 'test'])");
+ QUnit.throws(function() {
+ new Sao.PYSON.And([true, false, 'test']);
+ }, 'statement must be boolean', "And([true, false, 'test'])");
+ QUnit.throws(function() {
+ new Sao.PYSON.And([true]);
+ }, 'must have at least 2 statements', 'And([true])');
+ QUnit.throws(function() {
+ new Sao.PYSON.And([]);
+ }, 'must have at least 2 statements', 'And([])');
+ QUnit.throws(function() {
+ new Sao.PYSON.And();
+ }, 'must have at least 2 statements', 'And([])');
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.And([true, false]).types(),
+ ['boolean']), 'And([true, false]).types()');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.And([true, true]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(And([true, true]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.And([true, true, true]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(And([true, true, true]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.And([true, false]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(And([true, false]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.And([false, true]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(And([false, true]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.And([false, false]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(And([false, false]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.And([false, false, false]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(And([false, false, false]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.And([true, false, false]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(And([true, false, false]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.And([false, true, false]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(And([false, true, false]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.And([false, false, true]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(And([false, false, true]))');
+});
+
+QUnit.test('PYSON Or', function() {
+ var value = new Sao.PYSON.Or([true, false]).pyson();
+ QUnit.strictEqual(value.__class__, 'Or', 'Or([true, false]).pyson()');
+ QUnit.ok(SaoTest.compare(value.s, [true, false]),
+ 'Or([true, false]).pyson()');
+
+ QUnit.throws(function() {
+ new Sao.PYSON.Or(['test', false]);
+ }, 'statement must be boolean', "Or(['test', false])");
+ QUnit.throws(function() {
+ new Sao.PYSON.Or([true, 'test']);
+ }, 'statement must be boolean', "Or([true, 'test'])");
+ QUnit.throws(function() {
+ new Sao.PYSON.Or([true, false, 'test']);
+ }, 'statement must be boolean', "Or([true, false, 'test'])");
+ QUnit.throws(function() {
+ new Sao.PYSON.Or([true]);
+ }, 'must have at least 2 statements', 'Or([true])');
+ QUnit.throws(function() {
+ new Sao.PYSON.Or([]);
+ }, 'must have at least 2 statements', 'Or([])');
+ QUnit.throws(function() {
+ new Sao.PYSON.Or();
+ }, 'must have at least 2 statements', 'Or([])');
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.Or([true, false]).types(),
+ ['boolean']), 'Or([true, false]).types()');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Or([true, true]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Or([true, true]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Or([true, true, true]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Or([true, true, true]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Or([true, false]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Or([true, false]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Or([false, true]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Or([false, true]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Or([false, false]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Or([false, false]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Or([false, false, false]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Or([false, false, false]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Or([true, false, false]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Or([true, false, false]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Or([false, true, false]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Or([false, true, false]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Or([false, false, true]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Or([false, false, true]))');
+});
+
+QUnit.test('PYSON Equal', function() {
+ var value = new Sao.PYSON.Equal('test', 'test').pyson();
+ QUnit.strictEqual(value.__class__, 'Equal',
+ "Equal('test', 'test').pyson()");
+ QUnit.strictEqual(value.s1, 'test', "Equal('test', 'test').pyson()");
+ QUnit.strictEqual(value.s2, 'test', "Equal('test', 'test').pyson()");
+
+ QUnit.throws(function() {
+ new Sao.PYSON.Equal('test', true);
+ }, 'statements must have the same type');
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.Equal('test', 'test').types(),
+ ['boolean']), "Equal('test', 'test').types()");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Equal('test', 'test'));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ "decode(Equal('test', 'test'))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Equal('foo', 'bar'));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ "decode(Equal('test', 'test'))");
+});
+
+QUnit.test('PYSON Greater', function() {
+ var value = new Sao.PYSON.Greater(1, 0).pyson();
+ QUnit.strictEqual(value.__class__, 'Greater', 'Greater(1, 0).pyson()');
+ QUnit.strictEqual(value.s1, 1, 'Greater(1, 0).pyson()');
+ QUnit.strictEqual(value.s2, 0, 'Greater(1, 0).pyson()');
+ QUnit.strictEqual(value.e, false, 'Greater(1, 0).pyson()');
+
+ QUnit.throws(function() {
+ new Sao.PYSON.Greater('test', 0);
+ }, 'statement must be an integer or a float');
+ QUnit.throws(function() {
+ new Sao.PYSON.Greater(1, 'test');
+ }, 'statement must be an integer or a float');
+ QUnit.throws(function() {
+ new Sao.PYSON.Greater(1, 0, 'test');
+ }, 'equal must be boolean');
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.Greater(1, 0).types(), ['boolean']),
+ 'Greater(1, 0).types()');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Greater(1, 0));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Greater(1, 0))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Greater(0, 1));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Greater(0, 1))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Greater(1, 0, true));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Greater(1, 0, true))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Greater(0, 1, true));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Greater(0, 1, true))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Greater(1, 1));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Greater(1, 1))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Greater(1, 1, true));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Greater(1, 1, true))');
+});
+
+QUnit.test('PYSON Less', function() {
+ var value = new Sao.PYSON.Less(1, 0).pyson();
+ QUnit.strictEqual(value.__class__, 'Less', 'Less(1, 0).pyson()');
+ QUnit.strictEqual(value.s1, 1, 'Less(1, 0).pyson()');
+ QUnit.strictEqual(value.s2, 0, 'Less(1, 0).pyson()');
+ QUnit.strictEqual(value.e, false, 'Less(1, 0).pyson()');
+
+ QUnit.throws(function() {
+ new Sao.PYSON.Less('test', 0);
+ }, 'statement must be an integer or a float');
+ QUnit.throws(function() {
+ new Sao.PYSON.Less(1, 'test');
+ }, 'statement must be an integer or a float');
+ QUnit.throws(function() {
+ new Sao.PYSON.Less(1, 0, 'test');
+ }, 'equal must be boolean');
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.Less(1, 0).types(), ['boolean']),
+ 'Less(1, 0).types()');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Less(1, 0));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Less(1, 0))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Less(0, 1));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Less(0, 1))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Less(1, 0, true));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Less(1, 0, true))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Less(0, 1, true));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Less(0, 1, true))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(new Sao.PYSON.Less(1, 1));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(Less(1, 1))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Less(1, 1, true));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(Less(1, 1, true))');
+});
+
+QUnit.test('PYSON If', function() {
+ var value = new Sao.PYSON.If(true, 'foo', 'bar').pyson();
+ QUnit.strictEqual(value.__class__, 'If', "If(true, 'foo', 'bar')");
+ QUnit.strictEqual(value.c, true, "If(true, 'foo', 'bar')");
+ QUnit.strictEqual(value.t, 'foo', "If(true, 'foo', 'bar')");
+ QUnit.strictEqual(value.e, 'bar', "If(true, 'foo', 'bar')");
+
+ QUnit.throws(function() {
+ new Sao.PYSON.If('test', 'foo', 'bar');
+ }, 'condition must be boolean');
+ QUnit.throws(function() {
+ new Sao.PYSON.If(true, 'foo', false);
+ }, 'then and else statements must be the same type');
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.If(true, 'foo', 'bar').types(),
+ [typeof 'foo']), "If(true, 'foo', 'bar').types()");
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.If(true, false, true).types(),
+ [typeof true]), 'If(true, false, true).types()');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.If(true, 'foo', 'bar'));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), 'foo',
+ "decode(If(true, 'foo', 'bar'))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.If(false, 'foo', 'bar'));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), 'bar',
+ "decode(If(false, 'foo', 'bar'))");
+});
+
+QUnit.test('PYSON Get', function() {
+ var value = new Sao.PYSON.Get({foo: 'bar'}, 'foo', 'default').pyson();
+ QUnit.strictEqual(value.__class__, 'Get',
+ "Get({foo: 'bar'}, 'foo', 'default').pyson()");
+ QUnit.strictEqual(value.v.foo, 'bar',
+ "Get({foo: 'bar'}, 'foo', 'default').pyson()");
+ QUnit.strictEqual(value.k, 'foo',
+ "Get({foo: 'bar'}, 'foo', 'default').pyson()");
+ QUnit.strictEqual(value.d, 'default',
+ "Get({foo: 'bar'}, 'foo', 'default').pyson()");
+
+ QUnit.throws(function() {
+ new Sao.PYSON.Get('test', 'foo', 'default');
+ }, 'obj must be a dict');
+ QUnit.throws(function() {
+ new Sao.PYSON.Get({}, 1, 'default');
+ }, 'key must be a string');
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.Get({}, 'foo', 'default').types(),
+ [typeof '']), "Get({}, 'foo', 'default').types()");
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.Get({}, 'foo', true).types(),
+ [typeof true]), "Get({}, 'foo', true).types()");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Get({foo: 'bar'}, 'foo', 'default'));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), 'bar',
+ "decode(Get({foo: 'bar'}, 'foo', 'default'))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Get({foo: 'bar'}, 'test', 'default'));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), 'default',
+ "decode(Get({foo: 'bar'}, 'test', 'default'))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Get({}, 'foo', 'default'));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), 'default',
+ "decode(Get({}, 'foo', 'default'))");
+});
+
+QUnit.test('PYSON In', function() {
+ var value = new Sao.PYSON.In('foo', {foo: 'bar'}).pyson();
+ QUnit.strictEqual(value.__class__, 'In',
+ "In('foo', {foo: 'bar'}).pyson()");
+ QUnit.strictEqual(value.k, 'foo',
+ "In('foo', {foo: 'bar'}).pyson()");
+ QUnit.strictEqual(value.v.foo, 'bar',
+ "In('foo', {foo: 'bar'}).pyson()");
+
+ QUnit.throws(function() {
+ new Sao.PYSON.In({}, {});
+ }, 'key must be a string or a number');
+ QUnit.throws(function() {
+ new Sao.PYSON.In('test', 'foo');
+ }, 'obj must be a dict or a list');
+
+ QUnit.ok(SaoTest.compare(new Sao.PYSON.In('foo', {}).types(), ['boolean']),
+ "In('foo', {}).types()");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.In('foo', {foo: 'bar'}));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ "decode(In('foo', {foo: 'bar'}))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.In('1', {1: 'bar'}));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ "decode(In('1', {1: 'bar'}))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.In('test', {foo: 'bar'}));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ "decode(In('test', {foo: 'bar'}))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.In('foo', ['foo']));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ "decode(In('foo', ['foo']))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.In(1, [1]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), true,
+ 'decode(In(1, [1]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.In('test', ['foo']));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ "decode(In('test', ['foo']))");
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.In(1, [2]));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ 'decode(In(1, [2]))');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.In('test', []));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_), false,
+ "decode(In('test', []))");
+});
+
+QUnit.test('PYSON Date', function() {
+ var value = new Sao.PYSON.Date(2010, 1, 12, -1, 12, -7).pyson();
+ QUnit.strictEqual(value.__class__, 'Date',
+ 'Date(2010, 1, 12, -1, 12, -7).pyson()');
+ QUnit.strictEqual(value.y, 2010,
+ 'Date(2010, 1, 12, -1, 12, -7).pyson()');
+ QUnit.strictEqual(value.M, 1,
+ 'Date(2010, 1, 12, -1, 12, -7).pyson()');
+ QUnit.strictEqual(value.d, 12,
+ 'Date(2010, 1, 12, -1, 12, -7).pyson()');
+ QUnit.strictEqual(value.dy, -1,
+ 'Date(2010, 1, 12, -1, 12, -7).pyson()');
+ QUnit.strictEqual(value.dM, 12,
+ 'Date(2010, 1, 12, -1, 12, -7).pyson()');
+ QUnit.strictEqual(value.dd, -7,
+ 'Date(2010, 1, 12, -1, 12, -7).pyson()');
+
+ QUnit.throws(function() {
+ new Sao.PYSON.Date('test', 1, 12, -1, 12, -7);
+ }, 'year must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.Date(2010, 'test', 12, -1, 12, -7);
+ }, 'month must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.Date(2010, 1, 'test', -1, 12, -7);
+ }, 'day must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.Date(2010, 1, 12, 'test', 12, -7);
+ }, 'delta_years must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.Date(2010, 1, 12, -1, 'test', -7);
+ }, 'delta_months must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.Date(2010, 1, 12, -1, 12, 'test');
+ }, 'delta_days must be an integer or None');
+
+ QUnit.ok(SaoTest.compare(
+ new Sao.PYSON.Date(2010, 1, 12, -1, 12, -7).types(),
+ ['object']), 'Date(2010, 1, 12, -1, 12, -7).types()');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Date(2010, 1, 12));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2010, 1, 12).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Date(2010, 1, 12, -1));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2009, 1, 12).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Date(2010, 1, 12, 0, 12));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2011, 1, 12).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Date(2010, 1, 12, 0, 0, -7));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2010, 1, 5).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.Date(2010, 2, 22));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2010, 2, 22).valueOf());
+});
+
+QUnit.test('PYSON DateTime', function() {
+ var value = new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0,
+ -1, 12, -7, 2, 15, 30, 1).pyson();
+ QUnit.strictEqual(value.__class__, 'DateTime',
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.y, 2010,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.M, 1,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.d, 12,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.h, 10,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.m, 30,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.s, 20,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.ms, 0,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.dy, -1,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.dM, 12,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.dd, -7,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.dh, 2,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.dm, 15,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.ds, 30,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+ QUnit.strictEqual(value.dms, 1,
+ 'Date(2010, 1, 12, 10, 30, 20, 0, -1, 12, -7, 2, 15, 30, 1).pyson()');
+
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime('test', 1, 12, 10, 30, 20, 0,
+ -1, 12, -7, 2, 15, 30, 1);
+ }, 'year must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 'test', 12, 10, 30, 20, 0,
+ -1, 12, -7, 2, 15, 30, 1);
+ }, 'month must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 'test', 10, 30, 20, 0,
+ -1, 12, -7, 2, 15, 30, 1);
+ }, 'day must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 'test', 30, 20, 0,
+ -1, 12, -7, 2, 15, 30, 1);
+ }, 'hour must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 'test', 20, 0,
+ -1, 12, -7, 2, 15, 30, 1);
+ }, 'minute must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 'test', 0,
+ -1, 12, -7, 2, 15, 30, 1);
+ }, 'second must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 'test',
+ -1, 12, -7, 2, 15, 30, 1);
+ }, 'microsecond must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0,
+ 'test', 12, -7, 2, 15, 30, 1);
+ }, 'delta_years must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0,
+ -1, 'test', -7, 2, 15, 30, 1);
+ }, 'delta_months must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0,
+ -1, 12, 'test', 2, 15, 30, 1);
+ }, 'delta_days must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0,
+ -1, 12, -7, 'test', 15, 30, 1);
+ }, 'delta_hours must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0,
+ -1, 12, -7, 2, 'test', 30, 1);
+ }, 'delta_minutes must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0,
+ -1, 12, -7, 2, 15, 'test', 1);
+ }, 'delta_seconds must be an integer or None');
+ QUnit.throws(function() {
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0,
+ -1, 12, -7, 2, 15, 30, 'test');
+ }, 'delta_microseconds must be an integer or None');
+
+ QUnit.ok(SaoTest.compare(
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0,
+ -1, 12, -7, 2, 15, 30, 1).types(),
+ ['object']), 'DateTime(2010, 1, 12, 10, 30, 20, 0, ' +
+ '-1, 12, -7, 2, 15, 30, 1).types()');
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2010, 1, 12, 10, 30, 20, 0).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0, -1));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2009, 1, 12, 10, 30, 20, 0).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0, 0, 12));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2011, 1, 12, 10, 30, 20, 0).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0, 0, 0, -7));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2010, 1, 5, 10, 30, 20, 0).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20, 0, 0, 0, 0, 12));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2010, 1, 12, 22, 30, 20, 0).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20,
+ 0, 0, 0, 0, 0, -30));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2010, 1, 12, 10, 0, 20, 0).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20,
+ 0, 0, 0, 0, 0, 0, 30));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2010, 1, 12, 10, 30, 50, 0).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.DateTime(2010, 1, 12, 10, 30, 20,
+ 0, 0, 0, 0, 0, 0, 0, 200));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2010, 1, 12, 10, 30, 20, 2).valueOf());
+
+ var eval_ = new Sao.PYSON.Encoder().encode(
+ new Sao.PYSON.DateTime(2010, 2, 22, 10, 30, 20, 200));
+ QUnit.strictEqual(new Sao.PYSON.Decoder().decode(eval_).valueOf(),
+ new Date(2010, 2, 22, 10, 30, 20, 2).valueOf());
+});
+
QUnit.test('CRUD', function() {
var run_tests = function() {
var User = new Sao.Model('res.user');