changeset e032ae3f4015 in tryton:default
details: https://hg.tryton.org/tryton?cmd=changeset;node=e032ae3f4015
description:
Add unittest
issue8905
review258541002
diffstat:
.drone.yml | 25 +
setup.py | 1 +
tox.ini | 6 +
tryton/common/domain_parser.py | 973 ------------------------
tryton/common/selection.py | 7 -
tryton/common/timedelta.py | 49 -
tryton/tests/__init__.py | 29 +
tryton/tests/test_common_domain_parser.py | 1146 +++++++++++++++++++++++++++++
tryton/tests/test_common_selection.py | 18 +
tryton/tests/test_common_timedelta.py | 54 +
10 files changed, 1279 insertions(+), 1029 deletions(-)
diffs (2418 lines):
diff -r a70914b38278 -r e032ae3f4015 .drone.yml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.drone.yml Wed Dec 18 22:41:05 2019 +0100
@@ -0,0 +1,25 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ commands:
+ - pip install tox
+ - tox -e "${TOXENV}"
+ volumes:
+ - cache:/root/.cache
+
+matrix:
+ include:
+ - IMAGE: tryton/tryton-test:3.5
+ TOXENV: py35
+ - IMAGE: tryton/tryton-test:3.6
+ TOXENV: py36
+ - IMAGE: tryton/tryton-test:3.7
+ TOXENV: py37
diff -r a70914b38278 -r e032ae3f4015 setup.py
--- a/setup.py Wed Dec 18 21:43:09 2019 +0100
+++ b/setup.py Wed Dec 18 22:41:05 2019 +0100
@@ -144,5 +144,6 @@
'calendar': ['GooCalendar>=0.5'],
},
zip_safe=False,
+ test_suite='tryton.tests',
**args
)
diff -r a70914b38278 -r e032ae3f4015 tox.ini
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tox.ini Wed Dec 18 22:41:05 2019 +0100
@@ -0,0 +1,6 @@
+[tox]
+envlist = py35,py36,py37
+
+[testenv]
+commands = {envpython} setup.py test
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/
{opts} {packages}
diff -r a70914b38278 -r e032ae3f4015 tryton/common/domain_parser.py
--- a/tryton/common/domain_parser.py Wed Dec 18 21:43:09 2019 +0100
+++ b/tryton/common/domain_parser.py Wed Dec 18 22:41:05 2019 +0100
@@ -98,14 +98,6 @@
yield cur
-def test_group_operator():
- assert list(group_operator(iter(['a', '>', '=']))) == ['a', '>=']
- assert list(group_operator(iter(['>', '=', 'b']))) == ['>=', 'b']
- assert list(group_operator(iter(['a', '=', 'b']))) == ['a', '=', 'b']
- assert list(group_operator(iter(['a', '>', '=', 'b']))) == ['a', '>=', 'b']
- assert list(group_operator(iter(['a', '>', '=', '=']))) == ['a', '>=', '=']
-
-
def likify(value):
"Add % if needed"
if not value:
@@ -131,13 +123,6 @@
return value
-def test_quote():
- assert quote('test') == 'test'
- assert quote('foo bar') == '"foo bar"'
- assert quote('"foo"') == '\\\"foo\\\"'
- assert quote('foo\\bar') == 'foo\\\\bar'
-
-
def ending_clause(domain, deep=0):
"Return the ending clause"
if not domain:
@@ -210,25 +195,6 @@
return target, value
-def test_split_target_value():
- field = {
- 'type': 'reference',
- 'selection': [
- ('spam', 'Spam'),
- ('ham', 'Ham'),
- ('e', 'Eggs'),
- ]
- }
- for value, result in (
- ('Spam', (None, 'Spam')),
- ('foo', (None, 'foo')),
- ('Spam,', ('spam', '')),
- ('Ham,bar', ('ham', 'bar')),
- ('Eggs,foo', ('e', 'foo')),
- ):
- assert split_target_value(field, value) == result
-
-
def convert_value(field, value, context=None):
"Convert value for field"
if context is None:
@@ -320,168 +286,6 @@
return converts.get(field['type'], lambda: value)()
-def test_convert_boolean():
- field = {
- 'type': 'boolean',
- }
- for value, result in (
- ('Y', True),
- ('yes', True),
- ('t', True),
- ('1', True),
- ('N', False),
- ('False', False),
- ('no', False),
- ('0', False),
- (None, None),
- ):
- assert convert_value(field, value) == result
-
-
-def test_convert_float():
- field = {
- 'type': 'float',
- }
- for value, result in (
- ('1', 1.0),
- ('1.5', 1.5),
- ('', None),
- ('test', None),
- (None, None),
- ):
- assert convert_value(field, value) == result
-
-
-def test_convert_float_factor():
- field = {
- 'type': 'float',
- 'factor': '100',
- }
- assert convert_value(field, '42') == 0.42
-
-
-def test_convert_integer():
- field = {
- 'type': 'integer',
- }
- for value, result in (
- ('1', 1),
- ('1.5', 1),
- ('', None),
- ('test', None),
- (None, None),
- ):
- assert convert_value(field, value) == result
-
-
-def test_convert_integer_factor():
- field = {
- 'type': 'integer',
- 'factor': '2',
- }
- assert convert_value(field, '6') == 3
-
-
-def test_convert_numeric():
- field = {
- 'type': 'numeric',
- }
- for value, result in (
- ('1', Decimal(1)),
- ('1.5', Decimal('1.5')),
- ('', None),
- ('test', None),
- (None, None),
- ):
- assert convert_value(field, value) == result
-
-
-def test_convert_numeric_factor():
- field = {
- 'type': 'numeric',
- 'factor': '5',
- }
- assert convert_value(field, '1') == Decimal('0.2')
-
-
-def test_convert_selection():
- field = {
- 'type': 'selection',
- 'selection': [
- ('male', 'Male'),
- ('female', 'Female'),
- ],
- }
- field_with_empty = field.copy()
- field_with_empty['selection'] = (field_with_empty['selection']
- + [('', '')])
- for value, result in (
- ('Male', 'male'),
- ('male', 'male'),
- ('test', 'test'),
- (None, None),
- ('', ''),
- ):
- assert convert_value(field, value) == result
- assert convert_value(field_with_empty, value) == result
-
-
-def test_convert_datetime():
- field = {
- 'type': 'datetime',
- 'format': '"%H:%M:%S"',
- }
- for value, result in (
- ('12/04/2002', untimezoned_date(datetime.datetime(2002, 12, 4))),
- ('12/04/2002 12:30:00', untimezoned_date(
- datetime.datetime(2002, 12, 4, 12, 30))),
- ('02/03/04', untimezoned_date(datetime.datetime(2004, 2, 3))),
- ('02/03/04 05:06:07', untimezoned_date(
- datetime.datetime(2004, 2, 3, 5, 6, 7))),
- ('test', None),
- (None, None),
- ):
- assert convert_value(field, value) == result, (value,
- convert_value(field, value), result)
-
-
-def test_convert_date():
- field = {
- 'type': 'date',
- }
- for value, result in (
- ('12/04/2002', datetime.date(2002, 12, 4)),
- ('test', None),
- (None, None),
- ):
- assert convert_value(field, value) == result
-
-
-def test_convert_time():
- field = {
- 'type': 'time',
- 'format': '"%H:%M:%S"',
- }
- for value, result in (
- ('12:30:00', datetime.time(12, 30, 0)),
- ('test', None),
- (None, None),
- ):
- assert convert_value(field, value) == result
-
-
-def test_convert_timedelta():
- field = {
- 'type': 'timedelta',
- }
- for value, result in [
- ('1d 2:00', datetime.timedelta(days=1, hours=2)),
- ('foo', datetime.timedelta()),
- (None, None),
- ]:
- assert convert_value(field, value) == result
-
-
def format_value(field, value, target=None, context=None):
"Format value for field"
if context is None:
@@ -580,167 +384,6 @@
lambda: value if value is not None else '')())
-def test_format_boolean():
- field = {
- 'type': 'boolean',
- }
- for value, result in (
- (True, 'True'),
- (False, 'False'),
- (None, ''),
- ):
- assert format_value(field, value) == result
-
-
-def test_format_integer():
- field = {
- 'type': 'integer',
- }
- for value, result in (
- (1, '1'),
- (1.5, '1'),
- (0, '0'),
- (0.0, '0'),
- (False, ''),
- (None, ''),
- ):
- assert format_value(field, value) == result
-
-
-def test_format_integer_factor():
- field = {
- 'type': 'integer',
- 'factor': '2',
- }
- assert format_value(field, 3) == '6'
-
-
-def test_format_float():
- field = {
- 'type': 'float',
- }
- for value, result in (
- (1, '1'),
- (1.5, '1.5'),
- (1.50, '1.5'),
- (150.79, '150.79'),
- (0, '0'),
- (0.0, '0'),
- (False, ''),
- (None, ''),
- ):
- assert format_value(field, value) == result
-
-
-def test_format_float_factor():
- field = {
- 'type': 'float',
- 'factor': '100',
- }
- assert format_value(field, 0.42) == '42'
-
-
-def test_format_numeric():
- field = {
- 'type': 'numeric',
- }
- for value, result in (
- (Decimal(1), '1'),
- (Decimal('1.5'), '1.5'),
- (Decimal('1.50'), '1.5'),
- (Decimal('150.79'), '150.79'),
- (Decimal(0), '0'),
- (Decimal('0.0'), '0'),
- (False, ''),
- (None, ''),
- ):
- assert format_value(field, value) == result
-
-
-def test_format_numeric_factor():
- field = {
- 'type': 'numeric',
- 'factor': '5',
- }
- assert format_value(field, Decimal('0.2')) == '1'
-
-
-def test_format_selection():
- field = {
- 'type': 'selection',
- 'selection': [
- ('male', 'Male'),
- ('female', 'Female'),
- ],
- }
- field_with_empty = field.copy()
- field_with_empty['selection'] = (field_with_empty['selection']
- + [('', '')])
- for value, result in (
- ('male', 'Male'),
- ('test', 'test'),
- (False, ''),
- (None, ''),
- ('', ''),
- ):
- assert format_value(field, value) == result
- assert format_value(field_with_empty, value) == result
-
-
-def test_format_datetime():
- field = {
- 'type': 'datetime',
- 'format': '"%H:%M:%S"',
- }
- for value, result in (
- (datetime.date(2002, 12, 4), '12/04/2002'),
- (untimezoned_date(datetime.datetime(2002, 12, 4)), '12/04/2002'),
- (untimezoned_date(datetime.datetime(2002, 12, 4, 12, 30)),
- '"12/04/2002 12:30:00"'),
- (False, ''),
- (None, ''),
- ):
- assert format_value(field, value) == result
-
-
-def test_format_date():
- field = {
- 'type': 'date',
- }
- for value, result in (
- (datetime.date(2002, 12, 4), '12/04/2002'),
- (False, ''),
- (None, ''),
- ):
- assert format_value(field, value) == result
-
-
-def test_format_time():
- field = {
- 'type': 'time',
- 'format': '"%H:%M:%S"',
- }
- for value, result in (
- (datetime.time(12, 30, 0), '"12:30:00"'),
- (False, ''),
- (None, ''),
- ):
- assert format_value(field, value) == result
-
-
-def test_format_timedelta():
- field = {
- 'type': 'timedelta',
- }
- for value, result in [
- (datetime.timedelta(days=1, hours=2), '"1d 02:00"'),
- (datetime.timedelta(), ''),
- (None, ''),
- ('', ''),
- ]:
- assert format_value(field, value) == result
-
-
def complete_value(field, value):
"Complete value for field"
@@ -799,68 +442,6 @@
return completes.get(field['type'], lambda: [])()
-def test_complete_boolean():
- field = {
- 'type': 'boolean',
- }
- for value, result in [
- (None, [True, False]),
- (True, [False]),
- (False, [True]),
- ]:
- assert list(complete_value(field, value)) == result
-
-
-def test_complete_selection():
- field = {
- 'type': 'selection',
- 'selection': [
- ('male', 'Male'),
- ('female', 'Female'),
- ],
- }
- for value, result in (
- ('m', ['male']),
- ('test', []),
- ('', ['male', 'female']),
- (None, ['male', 'female']),
- (['male', 'f'], [['male', 'female']]),
- (['male', None], [['male', 'male'], ['male', 'female']]),
- ):
- assert list(complete_value(field, value)) == result
-
- field_with_empty = field.copy()
- field_with_empty['selection'] = (field_with_empty['selection']
- + [('', '')])
- for value, result in (
- ('m', ['male']),
- ('test', []),
- ('', ['male', 'female', '']),
- (None, ['male', 'female', '']),
- (['male', 'f'], [['male', 'female']]),
- ):
- assert list(complete_value(field_with_empty, value)) == result
-
-
-def test_complete_reference():
- field = {
- 'type': 'reference',
- 'selection': [
- ('spam', 'Spam'),
- ('ham', 'Ham'),
- ('', ''),
- ],
- }
- for value, result in (
- ('s', ['%spam%']),
- ('test', []),
- ('', ['%spam%', '%ham%', '%']),
- (None, ['%spam%', '%ham%', '%']),
- (['spam', 'h'], [['spam', 'ham']]),
- ):
- assert list(complete_value(field, value)) == result
-
-
def parenthesize(tokens):
"Nest tokens according to parenthesis"
for token in tokens:
@@ -872,22 +453,6 @@
yield token
-def test_parenthesize():
- for value, result in (
- (['a'], ['a']),
- (['a', 'b'], ['a', 'b']),
- (['(', 'a', ')'], [['a']]),
- (['a', 'b', '(', 'c', '(', 'd', 'e', ')', 'f', ')', 'g'],
- ['a', 'b', ['c', ['d', 'e'], 'f'], 'g']),
- (['a', 'b', '(', 'c'], ['a', 'b', ['c']]),
- (['a', 'b', '(', 'c', '(', 'd', 'e', ')', 'f'],
- ['a', 'b', ['c', ['d', 'e'], 'f']]),
- (['a', 'b', ')'], ['a', 'b']),
- (['a', 'b', ')', 'c', ')', 'd)'], ['a', 'b']),
- ):
- assert rlist(parenthesize(iter(value))) == result
-
-
def operatorize(tokens, operator='or'):
"Convert operators"
test = (operator, (operator,))
@@ -927,43 +492,6 @@
yield cur
-def test_operatorize():
- a = ('a', 'a', 'a')
- b = ('b', 'b', 'b')
- c = ('c', 'c', 'c')
- null_ = ('d', None, 'x')
- double_null_ = ('e', None, None)
- for value, result in (
- (['a'], ['a']),
- (['a', 'or', 'b'], [['OR', 'a', 'b']]),
- (['a', 'or', 'b', 'or', 'c'], [['OR', ['OR', 'a', 'b'], 'c']]),
- (['a', 'b', 'or', 'c'], ['a', ['OR', 'b', 'c']]),
- (['a', 'or', 'b', 'c'], [['OR', 'a', 'b'], 'c']),
- (['a', iter(['b', 'c'])], ['a', ['b', 'c']]),
- (['a', iter(['b', 'c']), 'd'], ['a', ['b', 'c'], 'd']),
- (['a', 'or', iter(['b', 'c'])], [['OR', 'a', ['b', 'c']]]),
- (['a', 'or', iter(['b', 'c']), 'd'],
- [['OR', 'a', ['b', 'c']], 'd']),
- (['a', iter(['b', 'c']), 'or', 'd'],
- ['a', ['OR', ['b', 'c'], 'd']]),
- (['a', 'or', iter(['b', 'or', 'c'])],
- [['OR', 'a', [['OR', 'b', 'c']]]]),
- (['or'], []),
- (['or', 'a'], ['a']),
- (['a', iter(['or', 'b'])], ['a', ['b']]),
- (['a', 'or', 'or', 'b'], [['OR', 'a', 'b']]),
- (['or', 'or', 'a'], ['a']),
- (['or', 'or', 'a', 'b'], ['a', 'b']),
- (['or', 'or', 'a', 'or', 'b'], [['OR', 'a', 'b']]),
- (['a', iter(['b', 'or', 'c'])], ['a', [['OR', 'b', 'c']]]),
- ([a, iter([b, ('or',), c])], [a, [['OR', b, c]]]),
- (['a', iter(['b', 'or'])], ['a', [['OR', 'b']]]),
- ([null_], [null_]),
- ([null_, 'or', double_null_], [['OR', null_, double_null_]]),
- ):
- assert rlist(operatorize(iter(value))) == result
-
-
class DomainParser(object):
"A parser for domain"
@@ -1321,504 +849,3 @@
yield (field_name, operator, value, target)
else:
yield field_name, operator, value
-
-
-def test_stringable():
- dom = DomainParser({
- 'name': {
- 'string': 'Name',
- 'type': 'char',
- },
- 'multiselection': {
- 'string': "MultiSelection",
- 'type': 'multiselection',
- 'selection': [
- ('foo', "Foo"),
- ('bar', "Bar"),
- ('baz', "Baz"),
- ],
- },
- 'relation': {
- 'string': 'Relation',
- 'type': 'many2one',
- 'relation_fields': {
- 'name': {
- 'string': "Name",
- 'type': 'char',
- },
- },
- },
- 'relations': {
- 'string': 'Relations',
- 'type': 'many2many',
- },
- })
- valid = ('name', '=', 'Doe')
- invalid = ('surname', '=', 'John')
- assert dom.stringable([valid])
- assert not dom.stringable([invalid])
- assert dom.stringable(['AND', valid])
- assert not dom.stringable(['AND', valid, invalid])
- assert dom.stringable([[valid]])
- assert not dom.stringable([[valid], [invalid]])
- assert dom.stringable([('multiselection', '=', None)])
- assert dom.stringable([('multiselection', '=', '')])
- assert not dom.stringable([('multiselection', '=', 'foo')])
- assert dom.stringable([('multiselection', '=', ['foo'])])
- assert dom.stringable([('relation', '=', None)])
- assert dom.stringable([('relation', '=', "Foo")])
- assert dom.stringable([('relation.rec_name', '=', "Foo")])
- assert not dom.stringable([('relation', '=', 1)])
- assert dom.stringable([('relations', '=', "Foo")])
- assert dom.stringable([('relations', 'in', ["Foo"])])
- assert not dom.stringable([('relations', 'in', [42])])
- assert dom.stringable([('relation.name', '=', "Foo")])
-
-
-def test_string():
- dom = DomainParser({
- 'name': {
- 'string': 'Name',
- 'type': 'char',
- },
- 'surname': {
- 'string': '(Sur)Name',
- 'type': 'char',
- },
- 'date': {
- 'string': 'Date',
- 'type': 'date',
- },
- 'selection': {
- 'string': 'Selection',
- 'type': 'selection',
- 'selection': [
- ('male', 'Male'),
- ('female', 'Female'),
- ('', ''),
- ],
- },
- 'multiselection': {
- 'string': "MultiSelection",
- 'type': 'multiselection',
- 'selection': [
- ('foo', "Foo"),
- ('bar', "Bar"),
- ('baz', "Baz"),
- ],
- },
- 'reference': {
- 'string': 'Reference',
- 'type': 'reference',
- 'selection': [
- ('spam', 'Spam'),
- ('ham', 'Ham'),
- ]
- },
- 'many2one': {
- 'string': 'Many2One',
- 'name': 'many2one',
- 'type': 'many2one',
- 'relation_fields': {
- 'name': {
- 'string': "Name",
- 'type': 'char',
- },
- },
- },
- })
- assert dom.string([('name', '=', 'Doe')]) == 'Name: =Doe'
- assert dom.string([('name', '=', None)]) == 'Name: ='
- assert dom.string([('name', '=', '')]) == 'Name: =""'
- assert dom.string([('name', 'ilike', '%')]) == 'Name: '
- assert dom.string([('name', 'ilike', '%Doe%')]) == 'Name: Doe'
- assert dom.string([('name', 'ilike', '%<%')]) == 'Name: "" "<"'
- assert dom.string([('name', 'ilike', 'Doe')]) == 'Name: =Doe'
- assert dom.string([('name', 'ilike', 'Doe%')]) == 'Name: Doe%'
- assert dom.string([('name', 'ilike', 'Doe%%')]) == 'Name: =Doe%'
- assert dom.string([('name', 'not ilike', '%Doe%')]) == 'Name: !Doe'
- assert dom.string([('name', 'in', ['John', 'Jane'])]) == 'Name: John;Jane'
- assert dom.string([('name', 'not in', ['John', 'Jane'])]) == \
- 'Name: !John;Jane'
- assert dom.string([
- ('name', 'ilike', '%Doe%'),
- ('name', 'ilike', '%Jane%')]) == 'Name: Doe Name: Jane'
- assert dom.string(['AND',
- ('name', 'ilike', '%Doe%'),
- ('name', 'ilike', '%Jane%')]) == 'Name: Doe Name: Jane'
- assert dom.string(['OR',
- ('name', 'ilike', '%Doe%'),
- ('name', 'ilike', '%Jane%')]) == 'Name: Doe or Name: Jane'
- assert dom.string([
- ('name', 'ilike', '%Doe%'),
- ['OR',
- ('name', 'ilike', '%John%'),
- ('name', 'ilike', '%Jane%')]]) == \
- 'Name: Doe (Name: John or Name: Jane)'
- assert dom.string([]) == ''
- assert dom.string([('surname', 'ilike', '%Doe%')]) == '"(Sur)Name": Doe'
- assert dom.string([('date', '>=', datetime.date(2012, 10, 24))]) == \
- 'Date: >=10/24/2012'
- assert dom.string([('selection', '=', '')]) == 'Selection: '
- assert dom.string([('selection', '=', None)]) == 'Selection: '
- assert dom.string([('selection', '!=', '')]) == 'Selection: !""'
- assert dom.string([('selection', '=', 'male')]) == 'Selection: Male'
- assert dom.string([('selection', '!=', 'male')]) == 'Selection: !Male'
- assert dom.string([('multiselection', '=', None)]) == "MultiSelection: ="
- assert dom.string([('multiselection', '=', '')]) == "MultiSelection: ="
- assert dom.string([('multiselection', '!=', '')]) == "MultiSelection: !="
- assert dom.string([('multiselection', '=', ['foo'])]) == \
- "MultiSelection: =Foo"
- assert dom.string([('multiselection', '!=', ['foo'])]) == \
- "MultiSelection: !=Foo"
- assert dom.string([('multiselection', '=', ['foo', 'bar'])]) == \
- "MultiSelection: =Foo;Bar"
- assert dom.string([('multiselection', '!=', ['foo', 'bar'])]) == \
- "MultiSelection: !=Foo;Bar"
- assert dom.string([('multiselection', 'in', ['foo'])]) == \
- "MultiSelection: Foo"
- assert dom.string([('multiselection', 'not in', ['foo'])]) == \
- "MultiSelection: !Foo"
- assert dom.string([('multiselection', '=', ['foo', 'bar'])]) == \
- "MultiSelection: =Foo;Bar"
- assert dom.string([('multiselection', '!=', ['foo', 'bar'])]) == \
- "MultiSelection: !=Foo;Bar"
- assert dom.string([('multiselection', 'in', ['foo', 'bar'])]) == \
- "MultiSelection: Foo;Bar"
- assert dom.string([('multiselection', 'not in', ['foo', 'bar'])]) == \
- "MultiSelection: !Foo;Bar"
- assert dom.string([('reference', 'ilike', '%foo%')]) == \
- 'Reference: foo'
- assert dom.string([('reference.rec_name', 'ilike', '%bar%', 'spam')]) == \
- 'Reference: Spam,bar'
- assert dom.string([('reference', 'in', ['foo', 'bar'])]) == \
- 'Reference: foo;bar'
- assert dom.string([('many2one', 'ilike', '%John%')]) == 'Many2One: John'
- assert dom.string([('many2one.rec_name', 'in', ['John', 'Jane'])]) == \
- 'Many2One: John;Jane'
- assert dom.string([('many2one.name', 'ilike', '%Foo%')]) == \
- "Many2One.Name: Foo"
-
-
-def test_group():
- dom = DomainParser({
- 'name': {
- 'string': 'Name',
- },
- 'firstname': {
- 'string': 'First Name',
- },
- 'surname': {
- 'string': '(Sur)Name',
- },
- 'relation': {
- 'string': "Relation",
- 'relation': 'relation',
- 'relation_fields': {
- 'name': {
- 'string': "Name",
- },
- },
- },
- })
- assert rlist(dom.group(udlex('Name: Doe'))) == [('Name', None, 'Doe')]
- assert rlist(dom.group(udlex('"(Sur)Name": Doe'))) == [
- ('(Sur)Name', None, 'Doe'),
- ]
- assert rlist(dom.group(udlex('Name: Doe Name: John'))) == [
- ('Name', None, 'Doe'),
- ('Name', None, 'John')]
- assert rlist(dom.group(udlex('Name: Name: John'))) == [
- ('Name', None, None),
- ('Name', None, 'John')]
- assert rlist(dom.group(udlex('First Name: John'))) == [
- ('First Name', None, 'John'),
- ]
- assert rlist(dom.group(udlex('Name: Doe First Name: John'))) == [
- ('Name', None, 'Doe'),
- ('First Name', None, 'John'),
- ]
- assert rlist(dom.group(udlex('First Name: John Name: Doe'))) == [
- ('First Name', None, 'John'),
- ('Name', None, 'Doe'),
- ]
- assert rlist(dom.group(udlex('First Name: John First Name: Jane'))) == [
- ('First Name', None, 'John'),
- ('First Name', None, 'Jane'),
- ]
- assert rlist(dom.group(udlex('Name: John Doe'))) == [
- ('Name', None, 'John'),
- ('Doe',),
- ]
- assert rlist(dom.group(udlex('Name: "John Doe"'))) == [
- ('Name', None, 'John Doe'),
- ]
- assert rlist(dom.group(udlex('Doe Name: John'))) == [
- ('Doe',), ('Name', None, 'John')]
- assert rlist(dom.group(udlex('Name: =Doe'))) == [('Name', '=', 'Doe')]
- assert rlist(dom.group(udlex('Name: =Doe Name: >John'))) == [
- ('Name', '=', 'Doe'),
- ('Name', '>', 'John'),
- ]
- assert rlist(dom.group(udlex('First Name: =John First Name: =Jane'))) == [
- ('First Name', '=', 'John'),
- ('First Name', '=', 'Jane'),
- ]
- assert rlist(dom.group(udlex('Name: John;Jane'))) == [
- ('Name', None, ['John', 'Jane'])
- ]
- assert rlist(dom.group(udlex('Name: John;'))) == [
- ('Name', None, ['John'])
- ]
- assert rlist(dom.group(udlex('Name: John;Jane Name: Doe'))) == [
- ('Name', None, ['John', 'Jane']),
- ('Name', None, 'Doe'),
- ]
- assert rlist(dom.group(udlex('Name: John; Name: Doe'))) == [
- ('Name', None, ['John']),
- ('Name', None, 'Doe'),
- ]
- assert rlist(dom.group(udlex('Name:'))) == [
- ('Name', None, None),
- ]
- assert rlist(dom.group(udlex('Name: ='))) == [
- ('Name', '=', None),
- ]
- assert rlist(dom.group(udlex('Name: =""'))) == [
- ('Name', '=', ''),
- ]
- assert rlist(dom.group(udlex('Name: = ""'))) == [
- ('Name', '=', ''),
- ]
- assert rlist(dom.group(udlex('Name: = Name: Doe'))) == [
- ('Name', '=', None),
- ('Name', None, 'Doe'),
- ]
- assert rlist(dom.group(udlex('Name: \\"foo\\"'))) == [
- ('Name', None, '"foo"'),
- ]
- assert rlist(dom.group(udlex('Name: "" <'))) == [
- ('Name', '', '<'),
- ]
- assert rlist(dom.group(udlex('Relation.Name: Test'))) == [
- ('Relation.Name', None, "Test"),
- ]
-
-
-def test_parse_clause():
- dom = DomainParser({
- 'name': {
- 'string': 'Name',
- 'name': 'name',
- 'type': 'char',
- },
- 'integer': {
- 'string': 'Integer',
- 'name': 'integer',
- 'type': 'integer',
- },
- 'selection': {
- 'string': 'Selection',
- 'name': 'selection',
- 'type': 'selection',
- 'selection': [
- ('male', 'Male'),
- ('female', 'Female'),
- ],
- },
- 'multiselection': {
- 'string': "MultiSelection",
- 'name': 'multiselection',
- 'type': 'multiselection',
- 'selection': [
- ('foo', "Foo"),
- ('bar', "Bar"),
- ('baz', "Baz"),
- ],
- },
- 'reference': {
- 'string': 'Reference',
- 'name': 'reference',
- 'type': 'reference',
- 'selection': [
- ('spam', 'Spam'),
- ('ham', 'Ham'),
- ]
- },
- 'many2one': {
- 'string': 'Many2One',
- 'name': 'many2one',
- 'type': 'many2one',
- },
- 'relation': {
- 'string': "Relation",
- 'relation': 'relation',
- 'name': 'relation',
- 'relation_fields': {
- 'name': {
- 'string': "Name",
- 'name': 'name',
- 'type': 'char',
- },
- },
- },
- })
- assert rlist(dom.parse_clause([('John',)])) == [
- ('rec_name', 'ilike', '%John%')]
- assert rlist(dom.parse_clause([('Name', None, None)])) == [
- ('name', 'ilike', '%')]
- assert rlist(dom.parse_clause([('Name', '', None)])) == [
- ('name', 'ilike', '%')]
- assert rlist(dom.parse_clause([('Name', '=', None)])) == [
- ('name', '=', None)]
- assert rlist(dom.parse_clause([('Name', '=', '')])) == [
- ('name', '=', '')]
- assert rlist(dom.parse_clause([('Name', None, 'Doe')])) == [
- ('name', 'ilike', '%Doe%')]
- assert rlist(dom.parse_clause([('Name', '!', 'Doe')])) == [
- ('name', 'not ilike', '%Doe%')]
- assert rlist(dom.parse_clause([('Name', None, ['John', 'Jane'])])) == [
- ('name', 'in', ['John', 'Jane']),
- ]
- assert rlist(dom.parse_clause([('Name', '!', ['John', 'Jane'])])) == [
- ('name', 'not in', ['John', 'Jane']),
- ]
- assert rlist(dom.parse_clause([('Selection', None, None)])) == [
- ('selection', '=', None),
- ]
- assert rlist(dom.parse_clause([('Selection', None, '')])) == [
- ('selection', '=', ''),
- ]
- assert rlist(dom.parse_clause([('Selection', None, ['Male', 'Female'])])) \
- == [
- ('selection', 'in', ['male', 'female'])
- ]
- assert rlist(dom.parse_clause([('MultiSelection', None, None)])) == [
- ('multiselection', '=', None),
- ]
- assert rlist(dom.parse_clause([('MultiSelection', None, '')])) == [
- ('multiselection', 'in', ['']),
- ]
- assert rlist(dom.parse_clause([('MultiSelection', '=', '')])) == [
- ('multiselection', '=', ['']),
- ]
- assert rlist(dom.parse_clause([('MultiSelection', '!', '')])) == [
- ('multiselection', 'not in', ['']),
- ]
- assert rlist(dom.parse_clause([('MultiSelection', '!=', '')])) == [
- ('multiselection', '!=', ['']),
- ]
- assert rlist(dom.parse_clause(
- [('MultiSelection', None, ['Foo', 'Bar'])])) == [
- ('multiselection', 'in', ['foo', 'bar']),
- ]
- assert rlist(dom.parse_clause(
- [('MultiSelection', '=', ['Foo', 'Bar'])])) == [
- ('multiselection', '=', ['foo', 'bar']),
- ]
- assert rlist(dom.parse_clause(
- [('MultiSelection', '!', ['Foo', 'Bar'])])) == [
- ('multiselection', 'not in', ['foo', 'bar']),
- ]
- assert rlist(dom.parse_clause(
- [('MultiSelection', '!=', ['Foo', 'Bar'])])) == [
- ('multiselection', '!=', ['foo', 'bar']),
- ]
- assert rlist(dom.parse_clause([('Integer', None, None)])) == [
- ('integer', '=', None),
- ]
- assert rlist(dom.parse_clause([('Integer', None, '3..5')])) == [[
- ('integer', '>=', 3),
- ('integer', '<=', 5),
- ]]
- assert rlist(dom.parse_clause([('Reference', None, 'foo')])) == [
- ('reference', 'ilike', '%foo%'),
- ]
- assert rlist(dom.parse_clause([('Reference', None, 'Spam')])) == [
- ('reference', 'ilike', '%spam%'),
- ]
- assert rlist(dom.parse_clause([('Reference', None, 'Spam,bar')])) == [
- ('reference.rec_name', 'ilike', '%bar%', 'spam'),
- ]
- assert rlist(dom.parse_clause([('Reference', None, ['foo', 'bar'])])) == [
- ('reference', 'in', ['foo', 'bar']),
- ]
- assert rlist(dom.parse_clause(['OR',
- ('Name', None, 'John'), ('Name', None, 'Jane')])) == ['OR',
- ('name', 'ilike', '%John%'),
- ('name', 'ilike', '%Jane%'),
- ]
- assert rlist(dom.parse_clause([('Many2One', None, 'John')])) == [
- ('many2one', 'ilike', '%John%'),
- ]
- assert rlist(dom.parse_clause([('Many2One', None, ['John', 'Jane'])])) == [
- ('many2one.rec_name', 'in', ['John', 'Jane']),
- ]
- assert rlist(dom.parse_clause(iter([iter([['John']])]))) == [
- [('rec_name', 'ilike', '%John%')]]
- assert rlist(dom.parse_clause(
- iter([['Relation.Name', None, "Test"]]))) == [
- ('relation.name', 'ilike', "%Test%")]
- assert rlist(dom.parse_clause(
- iter([['OR']]))) == [
- ('rec_name', 'ilike', "%OR%")]
- assert rlist(dom.parse_clause(
- iter([['AND']]))) == [
- ('rec_name', 'ilike', "%AND%")]
-
-
-def test_completion():
- dom = DomainParser({
- 'name': {
- 'string': 'Name',
- 'name': 'name',
- 'type': 'char',
- },
- })
- assert list(dom.completion('Nam')) == ['Name: ']
- assert list(dom.completion('Name:')) == ['Name: ']
- assert list(dom.completion('Name: foo')) == []
- assert list(dom.completion('Name: !=')) == []
- assert list(dom.completion('Name: !=foo')) == []
- assert list(dom.completion('')) == ['Name: ']
- assert list(dom.completion(' ')) == ['', 'Name: ']
-
- dom = DomainParser({
- 'relation': {
- 'name': 'relation',
- 'string': "Relation",
- 'type': 'many2one',
- 'relation_fields': {
- 'name': {
- 'name': 'name',
- 'string': "Name",
- 'type': 'char',
- },
- },
- },
- })
- assert list(dom.completion('Relatio')) == [
- 'Relation: ', 'Relation.Name: ']
-
- dom = DomainParser({
- 'name': {
- 'string': "Active",
- 'name': 'active',
- 'type': 'boolean',
- },
- })
-
- assert list(dom.completion("Act")) == ["Active: "]
- assert list(dom.completion("Active:")) == [
- "Active: ", "Active: True", "Active: False"]
- assert list(dom.completion("Active: t")) == [
- "Active: True", "Active: False"]
- assert list(dom.completion("Active: f")) == [
- "Active: False", "Active: True"]
-
-
-if __name__ == '__main__':
- for name in list(globals()):
- if name.startswith('test_'):
- func = globals()[name]
- func()
diff -r a70914b38278 -r e032ae3f4015 tryton/common/selection.py
--- a/tryton/common/selection.py Wed Dec 18 21:43:09 2019 +0100
+++ b/tryton/common/selection.py Wed Dec 18 22:41:05 2019 +0100
@@ -210,10 +210,3 @@
# When setting no item GTK doesn't clear the entry
entry.get_child().set_text('')
return True
-
-
-def test_freeze_value():
- assert freeze_value({'foo': 'bar'}) == (('foo', 'bar'),)
- assert freeze_value([1, 42, 2, 3]) == (1, 42, 2, 3)
- assert freeze_value('foo') == 'foo'
- assert freeze_value({'foo': {'bar': 42}}) == (('foo', (('bar', 42),)),)
diff -r a70914b38278 -r e032ae3f4015 tryton/common/timedelta.py
--- a/tryton/common/timedelta.py Wed Dec 18 21:43:09 2019 +0100
+++ b/tryton/common/timedelta.py Wed Dec 18 22:41:05 2019 +0100
@@ -107,52 +107,3 @@
if '-' in text:
seconds *= -1
return datetime.timedelta(seconds=seconds)
-
-
-_tests = [
- (None, ''),
- (datetime.timedelta(), '00:00'),
- (datetime.timedelta(days=3, hours=5, minutes=30), '3d 05:30'),
- (datetime.timedelta(weeks=48), '11M 6d'),
- (datetime.timedelta(weeks=50), '11M 2w 6d'),
- (datetime.timedelta(weeks=52), '12M 4d'),
- (datetime.timedelta(days=360), '12M'),
- (datetime.timedelta(days=364), '12M 4d'),
- (datetime.timedelta(days=365), '1Y'),
- (datetime.timedelta(days=366), '1Y 1d'),
- (datetime.timedelta(hours=2, minutes=5, seconds=10), '02:05:10'),
- (datetime.timedelta(minutes=15, microseconds=42), '00:15:00.000042'),
- (datetime.timedelta(days=1, microseconds=42), '1d .000042'),
- (datetime.timedelta(seconds=-1), '-00:00:01'),
- (datetime.timedelta(days=-1, hours=-5, minutes=-30), '-1d 05:30'),
- ]
-
-
-def test_format():
- for timedelta, text in _tests:
- assert format(timedelta) == text
-
-
-_tests_parse = [
- (datetime.timedelta(), ' '),
- (datetime.timedelta(), 'foo'),
- (datetime.timedelta(days=1.5), '1.5d'),
- (datetime.timedelta(days=-2), '1d -1d'),
- (datetime.timedelta(hours=1, minutes=5, seconds=10), '1:5:10:42'),
- (datetime.timedelta(hours=2), '1: 1:'),
- (datetime.timedelta(hours=.25), ':15'),
- (datetime.timedelta(hours=1), '1h'),
- (datetime.timedelta(hours=.25), '.25h'),
- ]
-
-
-def test_parse():
- for timedelta, text, in _tests + _tests_parse:
- assert parse(text) == timedelta
-
-
-if __name__ == '__main__':
- for name in list(globals()):
- if name.startswith('test_'):
- func = globals()[name]
- func()
diff -r a70914b38278 -r e032ae3f4015 tryton/tests/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tryton/tests/__init__.py Wed Dec 18 22:41:05 2019 +0100
@@ -0,0 +1,29 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import os
+import sys
+import unittest
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ loader = unittest.TestLoader()
+ for filename in os.listdir(os.path.dirname(__file__)):
+ if filename.startswith("test") and filename.endswith(".py"):
+ modname = "tryton.tests." + filename[:-3]
+ __import__(modname)
+ module = sys.modules[modname]
+ suite.addTests(loader.loadTestsFromModule(module))
+ return suite
+
+
+def main():
+ suite = test_suite()
+ runner = unittest.TextTestRunner()
+ return runner.run(suite)
+
+
+if __name__ == '__main__':
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(
+ os.path.abspath(__file__)))))
+ sys.exit(not main().wasSuccessful())
diff -r a70914b38278 -r e032ae3f4015 tryton/tests/test_common_domain_parser.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tryton/tests/test_common_domain_parser.py Wed Dec 18 22:41:05 2019 +0100
@@ -0,0 +1,1146 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import datetime as dt
+from decimal import Decimal
+from unittest import TestCase
+
+from tryton.common import untimezoned_date
+from tryton.common.domain_parser import (
+ group_operator, quote, split_target_value, convert_value, format_value,
+ complete_value, parenthesize, rlist, operatorize, DomainParser, udlex)
+
+
+class DomainParserTestCase(TestCase):
+ "Test common domain_parser"
+
+ def test_group_operator(self):
+ "Test group_operator"
+ self.assertEqual(
+ list(group_operator(iter(['a', '>', '=']))), ['a', '>='])
+ self.assertEqual(
+ list(group_operator(iter(['>', '=', 'b']))), ['>=', 'b'])
+ self.assertEqual(
+ list(group_operator(iter(['a', '=', 'b']))), ['a', '=', 'b'])
+ self.assertEqual(
+ list(group_operator(iter(['a', '>', '=', 'b']))), ['a', '>=', 'b'])
+ self.assertEqual(
+ list(group_operator(iter(['a', '>', '=', '=']))), ['a', '>=', '='])
+
+ def test_quote(self):
+ "Test quote"
+ self.assertEqual(quote('test'), 'test')
+ self.assertEqual(quote('foo bar'), '"foo bar"')
+ self.assertEqual(quote('"foo"'), '\\\"foo\\\"')
+ self.assertEqual(quote('foo\\bar'), 'foo\\\\bar')
+
+ def test_split_target_value(self):
+ "Test split_target_value"
+ field = {
+ 'type': 'reference',
+ 'selection': [
+ ('spam', 'Spam'),
+ ('ham', 'Ham'),
+ ('e', 'Eggs'),
+ ]
+ }
+ for value, result in (
+ ('Spam', (None, 'Spam')),
+ ('foo', (None, 'foo')),
+ ('Spam,', ('spam', '')),
+ ('Ham,bar', ('ham', 'bar')),
+ ('Eggs,foo', ('e', 'foo')),
+ ):
+ self.assertEqual(
+ split_target_value(field, value), result,
+ msg="split_target_value(%r, %r)" % (field, value))
+
+ def test_convert_boolean(self):
+ "Test convert boolean"
+ field = {
+ 'type': 'boolean',
+ }
+ for value, result in (
+ ('Y', True),
+ ('yes', True),
+ ('t', True),
+ ('1', True),
+ ('N', False),
+ ('False', False),
+ ('no', False),
+ ('0', False),
+ (None, None),
+ ):
+ self.assertEqual(
+ convert_value(field, value), result,
+ msg="convert_value(%r, %r)" % (field, value))
+
+ def test_convert_float(self):
+ "Test convert float"
+ field = {
+ 'type': 'float',
+ }
+ for value, result in (
+ ('1', 1.0),
+ ('1.5', 1.5),
+ ('', None),
+ ('test', None),
+ (None, None),
+ ):
+ self.assertEqual(
+ convert_value(field, value), result,
+ msg="convert_value(%r, %r)" % (field, value))
+
+ def test_convert_float_factor(self):
+ "Test convert float with factor"
+ field = {
+ 'type': 'float',
+ 'factor': '100',
+ }
+ self.assertEqual(convert_value(field, '42'), 0.42)
+
+ def test_convert_integer(self):
+ "Test convert integer"
+ field = {
+ 'type': 'integer',
+ }
+ for value, result in (
+ ('1', 1),
+ ('1.5', 1),
+ ('', None),
+ ('test', None),
+ (None, None),
+ ):
+ self.assertEqual(
+ convert_value(field, value), result,
+ msg="convert_value(%r, %r)" % (field, value))
+
+ def test_convert_integer_factor(self):
+ "Test convert integer with factor"
+ field = {
+ 'type': 'integer',
+ 'factor': '2',
+ }
+ self.assertEqual(convert_value(field, '6'), 3)
+
+ def test_convert_numeric(self):
+ "Test convert numeric"
+ field = {
+ 'type': 'numeric',
+ }
+ for value, result in (
+ ('1', Decimal(1)),
+ ('1.5', Decimal('1.5')),
+ ('', None),
+ ('test', None),
+ (None, None),
+ ):
+ self.assertEqual(
+ convert_value(field, value), result,
+ msg="convert_value(%r, %r)" % (field, value))
+
+ def test_convert_numeric_factor(self):
+ "Test convert numeric with factor"
+ field = {
+ 'type': 'numeric',
+ 'factor': '5',
+ }
+ self.assertEqual(convert_value(field, '1'), Decimal('0.2'))
+
+ def test_convert_selection(self):
+ "Test convert selection"
+ field = {
+ 'type': 'selection',
+ 'selection': [
+ ('male', 'Male'),
+ ('female', 'Female'),
+ ],
+ }
+ field_with_empty = field.copy()
+ field_with_empty['selection'] = (field_with_empty['selection']
+ + [('', '')])
+ for value, result in (
+ ('Male', 'male'),
+ ('male', 'male'),
+ ('test', 'test'),
+ (None, None),
+ ('', ''),
+ ):
+ self.assertEqual(
+ convert_value(field, value), result,
+ msg="convert_value(%r, %r)" % (field, value))
+ self.assertEqual(
+ convert_value(field_with_empty, value), result,
+ msg="convert_value(%r, %r)" % (field_with_empty, value))
+
+ def test_convert_datetime(self):
+ "Test convert datetime"
+ field = {
+ 'type': 'datetime',
+ 'format': '"%H:%M:%S"',
+ }
+ for value, result in (
+ ('12/04/2002', untimezoned_date(dt.datetime(2002, 12, 4))),
+ ('12/04/2002 12:30:00', untimezoned_date(
+ dt.datetime(2002, 12, 4, 12, 30))),
+ ('02/03/04', untimezoned_date(dt.datetime(2004, 2, 3))),
+ ('02/03/04 05:06:07', untimezoned_date(
+ dt.datetime(2004, 2, 3, 5, 6, 7))),
+ ('test', None),
+ (None, None),
+ ):
+ self.assertEqual(
+ convert_value(field, value), result,
+ msg="convert_value(%r, %r)" % (field, value))
+
+ def test_convert_date(self):
+ "Test convert date"
+ field = {
+ 'type': 'date',
+ }
+ for value, result in (
+ ('12/04/2002', dt.date(2002, 12, 4)),
+ ('test', None),
+ (None, None),
+ ):
+ self.assertEqual(
+ convert_value(field, value), result,
+ msg="convert_value(%r, %r)" % (field, value))
+
+ def test_convert_time(self):
+ "Test convert time"
+ field = {
+ 'type': 'time',
+ 'format': '"%H:%M:%S"',
+ }
+ for value, result in (
+ ('12:30:00', dt.time(12, 30, 0)),
+ ('test', None),
+ (None, None),
+ ):
+ self.assertEqual(
+ convert_value(field, value), result,
+ msg="convert_value(%r, %r)" % (field, value))
+
+ def test_convert_timedelta(self):
+ "Test convert timedelta"
+ field = {
+ 'type': 'timedelta',
+ }
+ for value, result in [
+ ('1d 2:00', dt.timedelta(days=1, hours=2)),
+ ('foo', dt.timedelta()),
+ (None, None),
+ ]:
+ self.assertEqual(
+ convert_value(field, value), result,
+ msg="convert_value(%r, %r)" % (field, value))
+
+ def test_format_boolean(self):
+ "Test format boolean"
+ field = {
+ 'type': 'boolean',
+ }
+ for value, result in (
+ (True, 'True'),
+ (False, 'False'),
+ (None, ''),
+ ):
+ self.assertEqual(
+ format_value(field, value), result,
+ msg="format_value(%r, %r)" % (field, value))
+
+ def test_format_integer(self):
+ "Test format integer"
+ field = {
+ 'type': 'integer',
+ }
+ for value, result in (
+ (1, '1'),
+ (1.5, '1'),
+ (0, '0'),
+ (0.0, '0'),
+ (False, ''),
+ (None, ''),
+ ):
+ self.assertEqual(
+ format_value(field, value), result,
+ msg="format_value(%r, %r)" % (field, value))
+
+ def test_format_integer_factor(self):
+ "Test format integer with factor"
+ field = {
+ 'type': 'integer',
+ 'factor': '2',
+ }
+ self.assertEqual(format_value(field, 3), '6')
+
+ def test_format_float(self):
+ "Test format float"
+ field = {
+ 'type': 'float',
+ }
+ for value, result in (
+ (1, '1'),
+ (1.5, '1.5'),
+ (1.50, '1.5'),
+ (150.79, '150.79'),
+ (0, '0'),
+ (0.0, '0'),
+ (False, ''),
+ (None, ''),
+ ):
+ self.assertEqual(
+ format_value(field, value), result,
+ msg="format_value(%r, %r)" % (field, value))
+
+ def test_format_float_factor(self):
+ "Test format float with factor"
+ field = {
+ 'type': 'float',
+ 'factor': '100',
+ }
+ self.assertEqual(format_value(field, 0.42), '42')
+
+ def test_format_numeric(self):
+ "Test format numeric"
+ field = {
+ 'type': 'numeric',
+ }
+ for value, result in (
+ (Decimal(1), '1'),
+ (Decimal('1.5'), '1.5'),
+ (Decimal('1.50'), '1.5'),
+ (Decimal('150.79'), '150.79'),
+ (Decimal(0), '0'),
+ (Decimal('0.0'), '0'),
+ (False, ''),
+ (None, ''),
+ ):
+ self.assertEqual(
+ format_value(field, value), result,
+ msg="format_value(%r, %r)" % (field, value))
+
+ def test_format_numeric_factor(self):
+ "Test format numeric with factor"
+ field = {
+ 'type': 'numeric',
+ 'factor': '5',
+ }
+ self.assertEqual(format_value(field, Decimal('0.2')), '1')
+
+ def test_format_selection(self):
+ "Test format selection"
+ field = {
+ 'type': 'selection',
+ 'selection': [
+ ('male', 'Male'),
+ ('female', 'Female'),
+ ],
+ }
+ field_with_empty = field.copy()
+ field_with_empty['selection'] = (field_with_empty['selection']
+ + [('', '')])
+ for value, result in (
+ ('male', 'Male'),
+ ('test', 'test'),
+ (False, ''),
+ (None, ''),
+ ('', ''),
+ ):
+ self.assertEqual(
+ format_value(field, value), result,
+ msg="format_value(%r, %r)" % (field, value))
+ self.assertEqual(
+ format_value(field_with_empty, value), result,
+ msg="format_value(%r, %r)" % (field_with_empty, value))
+
+ def test_format_datetime(self):
+ "Test format datetime"
+ field = {
+ 'type': 'datetime',
+ 'format': '"%H:%M:%S"',
+ }
+ for value, result in (
+ (dt.date(2002, 12, 4), dt.date(2002, 12, 4).strftime('%x')),
+ (untimezoned_date(dt.datetime(2002, 12, 4)),
+ dt.date(2002, 12, 4).strftime('%x')),
+ (untimezoned_date(dt.datetime(2002, 12, 4, 12, 30)),
+ dt.datetime(2002, 12, 4, 12, 30).strftime('"%x
%H:%M:%S"')),
+ (False, ''),
+ (None, ''),
+ ):
+ self.assertEqual(
+ format_value(field, value), result,
+ msg="format_value(%r, %r)" % (field, value))
+
+ def test_format_date(self):
+ "Test format date"
+ field = {
+ 'type': 'date',
+ }
+ for value, result in (
+ (dt.date(2002, 12, 4), dt.date(2002, 12, 4).strftime('%x')),
+ (False, ''),
+ (None, ''),
+ ):
+ self.assertEqual(
+ format_value(field, value), result,
+ msg="format_value(%r, %r)" % (field, value))
+
+ def test_format_time(self):
+ "Test format time"
+ field = {
+ 'type': 'time',
+ 'format': '"%H:%M:%S"',
+ }
+ for value, result in (
+ (dt.time(12, 30, 0), '"12:30:00"'),
+ (False, ''),
+ (None, ''),
+ ):
+ self.assertEqual(
+ format_value(field, value), result,
+ msg="format_value(%r, %r)" % (field, value))
+
+ def test_format_timedelta(self):
+ "Test format timedelta"
+ field = {
+ 'type': 'timedelta',
+ }
+ for value, result in [
+ (dt.timedelta(days=1, hours=2), '"1d 02:00"'),
+ (dt.timedelta(), ''),
+ (None, ''),
+ ('', ''),
+ ]:
+ self.assertEqual(
+ format_value(field, value), result,
+ msg="format_value(%r, %r)" % (field, value))
+
+ def test_complete_boolean(self):
+ "Test complete boolean"
+ field = {
+ 'type': 'boolean',
+ }
+ for value, result in [
+ (None, [True, False]),
+ (True, [False]),
+ (False, [True]),
+ ]:
+ self.assertEqual(
+ list(complete_value(field, value)), result,
+ msg="complete_value(%r, %r)" % (field, value))
+
+ def test_complete_selection(self):
+ "Test complete selection"
+ field = {
+ 'type': 'selection',
+ 'selection': [
+ ('male', 'Male'),
+ ('female', 'Female'),
+ ],
+ }
+ for value, result in (
+ ('m', ['male']),
+ ('test', []),
+ ('', ['male', 'female']),
+ (None, ['male', 'female']),
+ (['male', 'f'], [['male', 'female']]),
+ (['male', None], [['male', 'male'], ['male', 'female']]),
+ ):
+ self.assertEqual(
+ list(complete_value(field, value)), result,
+ msg="complete_value(%r, %r)" % (field, value))
+
+ field_with_empty = field.copy()
+ field_with_empty['selection'] = (field_with_empty['selection']
+ + [('', '')])
+ for value, result in (
+ ('m', ['male']),
+ ('test', []),
+ ('', ['male', 'female', '']),
+ (None, ['male', 'female', '']),
+ (['male', 'f'], [['male', 'female']]),
+ ):
+ self.assertEqual(
+ list(complete_value(field_with_empty, value)), result,
+ msg="complete_value(%r, %r)" % (field_with_empty, value))
+
+ def test_complete_reference(self):
+ "Test complete reference"
+ field = {
+ 'type': 'reference',
+ 'selection': [
+ ('spam', 'Spam'),
+ ('ham', 'Ham'),
+ ('', ''),
+ ],
+ }
+ for value, result in (
+ ('s', ['%spam%']),
+ ('test', []),
+ ('', ['%spam%', '%ham%', '%']),
+ (None, ['%spam%', '%ham%', '%']),
+ (['spam', 'h'], [['spam', 'ham']]),
+ ):
+ self.assertEqual(
+ list(complete_value(field, value)), result,
+ msg="complete_value(%r, %r)" % (field, value))
+
+ def test_parenthesize(self):
+ for value, result in (
+ (['a'], ['a']),
+ (['a', 'b'], ['a', 'b']),
+ (['(', 'a', ')'], [['a']]),
+ (['a', 'b', '(', 'c', '(', 'd', 'e', ')', 'f', ')', 'g'],
+ ['a', 'b', ['c', ['d', 'e'], 'f'], 'g']),
+ (['a', 'b', '(', 'c'], ['a', 'b', ['c']]),
+ (['a', 'b', '(', 'c', '(', 'd', 'e', ')', 'f'],
+ ['a', 'b', ['c', ['d', 'e'], 'f']]),
+ (['a', 'b', ')'], ['a', 'b']),
+ (['a', 'b', ')', 'c', ')', 'd)'], ['a', 'b']),
+ ):
+ self.assertEqual(
+ rlist(parenthesize(iter(value))), result,
+ msg="parenthesize(%r)" % value)
+
+ def test_operatorize(self):
+ "Test operatorize"
+ a = ('a', 'a', 'a')
+ b = ('b', 'b', 'b')
+ c = ('c', 'c', 'c')
+ null_ = ('d', None, 'x')
+ double_null_ = ('e', None, None)
+ for value, result in (
+ (['a'], ['a']),
+ (['a', 'or', 'b'], [['OR', 'a', 'b']]),
+ (['a', 'or', 'b', 'or', 'c'], [['OR', ['OR', 'a', 'b'], 'c']]),
+ (['a', 'b', 'or', 'c'], ['a', ['OR', 'b', 'c']]),
+ (['a', 'or', 'b', 'c'], [['OR', 'a', 'b'], 'c']),
+ (['a', iter(['b', 'c'])], ['a', ['b', 'c']]),
+ (['a', iter(['b', 'c']), 'd'], ['a', ['b', 'c'], 'd']),
+ (['a', 'or', iter(['b', 'c'])], [['OR', 'a', ['b', 'c']]]),
+ (['a', 'or', iter(['b', 'c']), 'd'],
+ [['OR', 'a', ['b', 'c']], 'd']),
+ (['a', iter(['b', 'c']), 'or', 'd'],
+ ['a', ['OR', ['b', 'c'], 'd']]),
+ (['a', 'or', iter(['b', 'or', 'c'])],
+ [['OR', 'a', [['OR', 'b', 'c']]]]),
+ (['or'], []),
+ (['or', 'a'], ['a']),
+ (['a', iter(['or', 'b'])], ['a', ['b']]),
+ (['a', 'or', 'or', 'b'], [['OR', 'a', 'b']]),
+ (['or', 'or', 'a'], ['a']),
+ (['or', 'or', 'a', 'b'], ['a', 'b']),
+ (['or', 'or', 'a', 'or', 'b'], [['OR', 'a', 'b']]),
+ (['a', iter(['b', 'or', 'c'])], ['a', [['OR', 'b', 'c']]]),
+ ([a, iter([b, ('or',), c])], [a, [['OR', b, c]]]),
+ (['a', iter(['b', 'or'])], ['a', [['OR', 'b']]]),
+ ([null_], [null_]),
+ ([null_, 'or', double_null_], [['OR', null_, double_null_]]),
+ ):
+ self.assertEqual(
+ rlist(operatorize(iter(value))), result,
+ msg="operatorize(%r)" % value)
+
+ def test_stringable(self):
+ "Test stringable"
+ dom = DomainParser({
+ 'name': {
+ 'string': 'Name',
+ 'type': 'char',
+ },
+ 'multiselection': {
+ 'string': "MultiSelection",
+ 'type': 'multiselection',
+ 'selection': [
+ ('foo', "Foo"),
+ ('bar', "Bar"),
+ ('baz', "Baz"),
+ ],
+ },
+ 'relation': {
+ 'string': 'Relation',
+ 'type': 'many2one',
+ 'relation_fields': {
+ 'name': {
+ 'string': "Name",
+ 'type': 'char',
+ },
+ },
+ },
+ 'relations': {
+ 'string': 'Relations',
+ 'type': 'many2many',
+ },
+ })
+ valid = ('name', '=', 'Doe')
+ invalid = ('surname', '=', 'John')
+ self.assertTrue(dom.stringable([valid]))
+ self.assertFalse(dom.stringable([invalid]))
+ self.assertTrue(dom.stringable(['AND', valid]))
+ self.assertFalse(dom.stringable(['AND', valid, invalid]))
+ self.assertTrue(dom.stringable([[valid]]))
+ self.assertFalse(dom.stringable([[valid], [invalid]]))
+ self.assertTrue(dom.stringable([('multiselection', '=', None)]))
+ self.assertTrue(dom.stringable([('multiselection', '=', '')]))
+ self.assertFalse(dom.stringable([('multiselection', '=', 'foo')]))
+ self.assertTrue(dom.stringable([('multiselection', '=', ['foo'])]))
+ self.assertTrue(dom.stringable([('relation', '=', None)]))
+ self.assertTrue(dom.stringable([('relation', '=', "Foo")]))
+ self.assertTrue(dom.stringable([('relation.rec_name', '=', "Foo")]))
+ self.assertFalse(dom.stringable([('relation', '=', 1)]))
+ self.assertTrue(dom.stringable([('relations', '=', "Foo")]))
+ self.assertTrue(dom.stringable([('relations', 'in', ["Foo"])]))
+ self.assertFalse(dom.stringable([('relations', 'in', [42])]))
+ self.assertTrue(dom.stringable([('relation.name', '=', "Foo")]))
+
+ def test_string(self):
+ dom = DomainParser({
+ 'name': {
+ 'string': 'Name',
+ 'type': 'char',
+ },
+ 'surname': {
+ 'string': '(Sur)Name',
+ 'type': 'char',
+ },
+ 'date': {
+ 'string': 'Date',
+ 'type': 'date',
+ },
+ 'selection': {
+ 'string': 'Selection',
+ 'type': 'selection',
+ 'selection': [
+ ('male', 'Male'),
+ ('female', 'Female'),
+ ('', ''),
+ ],
+ },
+ 'multiselection': {
+ 'string': "MultiSelection",
+ 'type': 'multiselection',
+ 'selection': [
+ ('foo', "Foo"),
+ ('bar', "Bar"),
+ ('baz', "Baz"),
+ ],
+ },
+ 'reference': {
+ 'string': 'Reference',
+ 'type': 'reference',
+ 'selection': [
+ ('spam', 'Spam'),
+ ('ham', 'Ham'),
+ ]
+ },
+ 'many2one': {
+ 'string': 'Many2One',
+ 'name': 'many2one',
+ 'type': 'many2one',
+ 'relation_fields': {
+ 'name': {
+ 'string': "Name",
+ 'type': 'char',
+ },
+ },
+ },
+ })
+ self.assertEqual(dom.string([('name', '=', 'Doe')]), 'Name: =Doe')
+ self.assertEqual(dom.string([('name', '=', None)]), 'Name: =')
+ self.assertEqual(dom.string([('name', '=', '')]), 'Name: =""')
+ self.assertEqual(dom.string([('name', 'ilike', '%')]), 'Name: ')
+ self.assertEqual(dom.string([('name', 'ilike', '%Doe%')]), 'Name: Doe')
+ self.assertEqual(
+ dom.string([('name', 'ilike', '%<%')]), 'Name: "" "<"')
+ self.assertEqual(dom.string([('name', 'ilike', 'Doe')]), 'Name: =Doe')
+ self.assertEqual(dom.string([('name', 'ilike', 'Doe%')]), 'Name: Doe%')
+ self.assertEqual(
+ dom.string([('name', 'ilike', 'Doe%%')]), 'Name: =Doe%')
+ self.assertEqual(
+ dom.string([('name', 'not ilike', '%Doe%')]), 'Name: !Doe')
+ self.assertEqual(
+ dom.string([('name', 'in', ['John', 'Jane'])]), 'Name: John;Jane')
+ self.assertEqual(
+ dom.string([('name', 'not in', ['John', 'Jane'])]),
+ 'Name: !John;Jane')
+ self.assertEqual(
+ dom.string([
+ ('name', 'ilike', '%Doe%'),
+ ('name', 'ilike', '%Jane%')]),
+ 'Name: Doe Name: Jane')
+ self.assertEqual(
+ dom.string(['AND',
+ ('name', 'ilike', '%Doe%'),
+ ('name', 'ilike', '%Jane%')]),
+ 'Name: Doe Name: Jane')
+ self.assertEqual(
+ dom.string(['OR',
+ ('name', 'ilike', '%Doe%'),
+ ('name', 'ilike', '%Jane%')]),
+ 'Name: Doe or Name: Jane')
+ self.assertEqual(
+ dom.string([
+ ('name', 'ilike', '%Doe%'),
+ ['OR',
+ ('name', 'ilike', '%John%'),
+ ('name', 'ilike', '%Jane%')]]),
+ 'Name: Doe (Name: John or Name: Jane)')
+ self.assertEqual(dom.string([]), '')
+ self.assertEqual(
+ dom.string([('surname', 'ilike', '%Doe%')]), '"(Sur)Name": Doe')
+ self.assertEqual(
+ dom.string([('date', '>=', dt.date(2012, 10, 24))]),
+ dt.date(2012, 10, 24).strftime('Date: >=%x'))
+ self.assertEqual(dom.string([('selection', '=', '')]), 'Selection: ')
+ self.assertEqual(dom.string([('selection', '=', None)]), 'Selection: ')
+ self.assertEqual(
+ dom.string([('selection', '!=', '')]), 'Selection: !""')
+ self.assertEqual(
+ dom.string([('selection', '=', 'male')]), 'Selection: Male')
+ self.assertEqual(
+ dom.string([('selection', '!=', 'male')]), 'Selection: !Male')
+ self.assertEqual(
+ dom.string([('multiselection', '=', None)]), "MultiSelection: =")
+ self.assertEqual(
+ dom.string([('multiselection', '=', '')]), "MultiSelection: =")
+ self.assertEqual(
+ dom.string([('multiselection', '!=', '')]), "MultiSelection: !=")
+ self.assertEqual(
+ dom.string([('multiselection', '=', ['foo'])]),
+ "MultiSelection: =Foo")
+ self.assertEqual(
+ dom.string([('multiselection', '!=', ['foo'])]),
+ "MultiSelection: !=Foo")
+ self.assertEqual(
+ dom.string([('multiselection', '=', ['foo', 'bar'])]),
+ "MultiSelection: =Foo;Bar")
+ self.assertEqual(
+ dom.string([('multiselection', '!=', ['foo', 'bar'])]),
+ "MultiSelection: !=Foo;Bar")
+ self.assertEqual(
+ dom.string([('multiselection', 'in', ['foo'])]),
+ "MultiSelection: Foo")
+ self.assertEqual(
+ dom.string([('multiselection', 'not in', ['foo'])]),
+ "MultiSelection: !Foo")
+ self.assertEqual(
+ dom.string([('multiselection', '=', ['foo', 'bar'])]),
+ "MultiSelection: =Foo;Bar")
+ self.assertEqual(
+ dom.string([('multiselection', '!=', ['foo', 'bar'])]),
+ "MultiSelection: !=Foo;Bar")
+ self.assertEqual(
+ dom.string([('multiselection', 'in', ['foo', 'bar'])]),
+ "MultiSelection: Foo;Bar")
+ self.assertEqual(
+ dom.string([('multiselection', 'not in', ['foo', 'bar'])]),
+ "MultiSelection: !Foo;Bar")
+ self.assertEqual(
+ dom.string([('reference', 'ilike', '%foo%')]),
+ 'Reference: foo')
+ self.assertEqual(
+ dom.string([('reference.rec_name', 'ilike', '%bar%', 'spam')]),
+ 'Reference: Spam,bar')
+ self.assertEqual(
+ dom.string([('reference', 'in', ['foo', 'bar'])]),
+ 'Reference: foo;bar')
+ self.assertEqual(
+ dom.string([('many2one', 'ilike', '%John%')]), 'Many2One: John')
+ self.assertEqual(
+ dom.string([('many2one.rec_name', 'in', ['John', 'Jane'])]),
+ 'Many2One: John;Jane')
+ self.assertEqual(
+ dom.string([('many2one.name', 'ilike', '%Foo%')]),
+ "Many2One.Name: Foo")
+
+ def test_group(self):
+ "Test group"
+ dom = DomainParser({
+ 'name': {
+ 'string': 'Name',
+ },
+ 'firstname': {
+ 'string': 'First Name',
+ },
+ 'surname': {
+ 'string': '(Sur)Name',
+ },
+ 'relation': {
+ 'string': "Relation",
+ 'relation': 'relation',
+ 'relation_fields': {
+ 'name': {
+ 'string': "Name",
+ },
+ },
+ },
+ })
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: Doe'))), [('Name', None, 'Doe')])
+ self.assertEqual(
+ rlist(dom.group(udlex('"(Sur)Name": Doe'))), [
+ ('(Sur)Name', None, 'Doe'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: Doe Name: John'))), [
+ ('Name', None, 'Doe'),
+ ('Name', None, 'John'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: Name: John'))), [
+ ('Name', None, None),
+ ('Name', None, 'John')])
+ self.assertEqual(
+ rlist(dom.group(udlex('First Name: John'))), [
+ ('First Name', None, 'John'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: Doe First Name: John'))), [
+ ('Name', None, 'Doe'),
+ ('First Name', None, 'John'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('First Name: John Name: Doe'))), [
+ ('First Name', None, 'John'),
+ ('Name', None, 'Doe'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('First Name: John First Name: Jane'))), [
+ ('First Name', None, 'John'),
+ ('First Name', None, 'Jane'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: John Doe'))), [
+ ('Name', None, 'John'),
+ ('Doe',),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: "John Doe"'))), [
+ ('Name', None, 'John Doe'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Doe Name: John'))), [
+ ('Doe',),
+ ('Name', None, 'John'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: =Doe'))), [('Name', '=', 'Doe')])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: =Doe Name: >John'))), [
+ ('Name', '=', 'Doe'),
+ ('Name', '>', 'John'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('First Name: =John First Name: =Jane'))), [
+ ('First Name', '=', 'John'),
+ ('First Name', '=', 'Jane'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: John;Jane'))), [
+ ('Name', None, ['John', 'Jane'])
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: John;'))), [
+ ('Name', None, ['John'])
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: John;Jane Name: Doe'))), [
+ ('Name', None, ['John', 'Jane']),
+ ('Name', None, 'Doe'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: John; Name: Doe'))), [
+ ('Name', None, ['John']),
+ ('Name', None, 'Doe'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name:'))), [
+ ('Name', None, None),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: ='))), [
+ ('Name', '=', None),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: =""'))), [
+ ('Name', '=', ''),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: = ""'))), [
+ ('Name', '=', ''),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: = Name: Doe'))), [
+ ('Name', '=', None),
+ ('Name', None, 'Doe'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: \\"foo\\"'))), [
+ ('Name', None, '"foo"'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Name: "" <'))), [
+ ('Name', '', '<'),
+ ])
+ self.assertEqual(
+ rlist(dom.group(udlex('Relation.Name: Test'))), [
+ ('Relation.Name', None, "Test"),
+ ])
+
+ def test_parse_clause(self):
+ "Test parse clause"
+ dom = DomainParser({
+ 'name': {
+ 'string': 'Name',
+ 'name': 'name',
+ 'type': 'char',
+ },
+ 'integer': {
+ 'string': 'Integer',
+ 'name': 'integer',
+ 'type': 'integer',
+ },
+ 'selection': {
+ 'string': 'Selection',
+ 'name': 'selection',
+ 'type': 'selection',
+ 'selection': [
+ ('male', 'Male'),
+ ('female', 'Female'),
+ ],
+ },
+ 'multiselection': {
+ 'string': "MultiSelection",
+ 'name': 'multiselection',
+ 'type': 'multiselection',
+ 'selection': [
+ ('foo', "Foo"),
+ ('bar', "Bar"),
+ ('baz', "Baz"),
+ ],
+ },
+ 'reference': {
+ 'string': 'Reference',
+ 'name': 'reference',
+ 'type': 'reference',
+ 'selection': [
+ ('spam', 'Spam'),
+ ('ham', 'Ham'),
+ ]
+ },
+ 'many2one': {
+ 'string': 'Many2One',
+ 'name': 'many2one',
+ 'type': 'many2one',
+ },
+ 'relation': {
+ 'string': "Relation",
+ 'relation': 'relation',
+ 'name': 'relation',
+ 'relation_fields': {
+ 'name': {
+ 'string': "Name",
+ 'name': 'name',
+ 'type': 'char',
+ },
+ },
+ },
+ })
+ self.assertEqual(
+ rlist(dom.parse_clause([('John',)])), [
+ ('rec_name', 'ilike', '%John%'),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Name', None, None)])), [
+ ('name', 'ilike', '%'),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Name', '', None)])), [
+ ('name', 'ilike', '%'),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Name', '=', None)])), [
+ ('name', '=', None),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Name', '=', '')])), [
+ ('name', '=', ''),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Name', None, 'Doe')])), [
+ ('name', 'ilike', '%Doe%'),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Name', '!', 'Doe')])), [
+ ('name', 'not ilike', '%Doe%'),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Name', None, ['John', 'Jane'])])), [
+ ('name', 'in', ['John', 'Jane']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Name', '!', ['John', 'Jane'])])), [
+ ('name', 'not in', ['John', 'Jane']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Selection', None, None)])), [
+ ('selection', '=', None),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Selection', None, '')])), [
+ ('selection', '=', ''),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Selection', None, ['Male', 'Female'])])),
+ [('selection', 'in', ['male', 'female'])])
+ self.assertEqual(
+ rlist(dom.parse_clause([('MultiSelection', None, None)])), [
+ ('multiselection', '=', None),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('MultiSelection', None, '')])), [
+ ('multiselection', 'in', ['']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('MultiSelection', '=', '')])), [
+ ('multiselection', '=', ['']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('MultiSelection', '!', '')])), [
+ ('multiselection', 'not in', ['']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('MultiSelection', '!=', '')])), [
+ ('multiselection', '!=', ['']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause(
+ [('MultiSelection', None, ['Foo', 'Bar'])])), [
+ ('multiselection', 'in', ['foo', 'bar']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause(
+ [('MultiSelection', '=', ['Foo', 'Bar'])])), [
+ ('multiselection', '=', ['foo', 'bar']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause(
+ [('MultiSelection', '!', ['Foo', 'Bar'])])), [
+ ('multiselection', 'not in', ['foo', 'bar']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause(
+ [('MultiSelection', '!=', ['Foo', 'Bar'])])), [
+ ('multiselection', '!=', ['foo', 'bar']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Integer', None, None)])), [
+ ('integer', '=', None),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Integer', None, '3..5')])), [[
+ ('integer', '>=', 3),
+ ('integer', '<=', 5),
+ ]])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Reference', None, 'foo')])), [
+ ('reference', 'ilike', '%foo%'),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Reference', None, 'Spam')])), [
+ ('reference', 'ilike', '%spam%'),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Reference', None, 'Spam,bar')])), [
+ ('reference.rec_name', 'ilike', '%bar%', 'spam'),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Reference', None, ['foo', 'bar'])])), [
+ ('reference', 'in', ['foo', 'bar']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause(['OR',
+ ('Name', None, 'John'), ('Name', None, 'Jane')])),
+ ['OR',
+ ('name', 'ilike', '%John%'),
+ ('name', 'ilike', '%Jane%'),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Many2One', None, 'John')])), [
+ ('many2one', 'ilike', '%John%'),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause([('Many2One', None, ['John', 'Jane'])])), [
+ ('many2one.rec_name', 'in', ['John', 'Jane']),
+ ])
+ self.assertEqual(
+ rlist(dom.parse_clause(iter([iter([['John']])]))), [
+ [('rec_name', 'ilike', '%John%')]])
+ self.assertEqual(
+ rlist(dom.parse_clause(iter([['Relation.Name', None, "Test"]]))),
+ [('relation.name', 'ilike', "%Test%")])
+ self.assertEqual(
+ rlist(dom.parse_clause(iter([['OR']]))),
+ [('rec_name', 'ilike', "%OR%")])
+ self.assertEqual(
+ rlist(dom.parse_clause(iter([['AND']]))),
+ [('rec_name', 'ilike', "%AND%")])
+
+ def test_completion_char(self):
+ "Test completion char"
+ dom = DomainParser({
+ 'name': {
+ 'string': 'Name',
+ 'name': 'name',
+ 'type': 'char',
+ },
+ })
+ self.assertEqual(list(dom.completion('Nam')), ['Name: '])
+ self.assertEqual(list(dom.completion('Name:')), ['Name: '])
+ self.assertEqual(list(dom.completion('Name: foo')), [])
+ self.assertEqual(list(dom.completion('Name: !=')), [])
+ self.assertEqual(list(dom.completion('Name: !=foo')), [])
+ self.assertEqual(list(dom.completion('')), ['Name: '])
+ self.assertEqual(list(dom.completion(' ')), ['', 'Name: '])
+
+ def test_completion_many2one(self):
+ "Test completion many2one"
+ dom = DomainParser({
+ 'relation': {
+ 'name': 'relation',
+ 'string': "Relation",
+ 'type': 'many2one',
+ 'relation_fields': {
+ 'name': {
+ 'name': 'name',
+ 'string': "Name",
+ 'type': 'char',
+ },
+ },
+ },
+ })
+ self.assertEqual(
+ list(dom.completion('Relatio')),
+ ['Relation: ', 'Relation.Name: '])
+
+ def test_completion_boolean(self):
+ "Test completion boolean"
+ dom = DomainParser({
+ 'name': {
+ 'string': "Active",
+ 'name': 'active',
+ 'type': 'boolean',
+ },
+ })
+
+ self.assertEqual(list(dom.completion("Act")), ["Active: "])
+ self.assertEqual(list(dom.completion("Active:")),
+ ["Active: ", "Active: True", "Active: False"])
+ self.assertEqual(
+ list(dom.completion("Active: t")),
+ ["Active: True", "Active: False"])
+ self.assertEqual(
+ list(dom.completion("Active: f")),
+ ["Active: False", "Active: True"])
diff -r a70914b38278 -r e032ae3f4015 tryton/tests/test_common_selection.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tryton/tests/test_common_selection.py Wed Dec 18 22:41:05 2019 +0100
@@ -0,0 +1,18 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from unittest import TestCase
+
+from tryton.common.selection import freeze_value
+
+
+class SelectionTestCase(TestCase):
+ "Test common selection"
+
+ def test_freeze_value(self):
+ "Test freeze_value"
+ self.assertEqual(freeze_value({'foo': 'bar'}), (('foo', 'bar'),))
+ self.assertEqual(freeze_value([1, 42, 2, 3]), (1, 42, 2, 3))
+ self.assertEqual(freeze_value('foo'), 'foo')
+ self.assertEqual(
+ freeze_value({'foo': {'bar': 42}}), (('foo', (('bar', 42),)),))
+
diff -r a70914b38278 -r e032ae3f4015 tryton/tests/test_common_timedelta.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tryton/tests/test_common_timedelta.py Wed Dec 18 22:41:05 2019 +0100
@@ -0,0 +1,54 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import datetime as dt
+from unittest import TestCase
+
+from tryton.common.timedelta import format, parse
+
+
+class TimeDeltaTestCase(TestCase):
+ "Test common timedelta"
+
+ def _format_values(self):
+ return [
+ (None, ''),
+ (dt.timedelta(), '00:00'),
+ (dt.timedelta(days=3, hours=5, minutes=30), '3d 05:30'),
+ (dt.timedelta(weeks=48), '11M 6d'),
+ (dt.timedelta(weeks=50), '11M 2w 6d'),
+ (dt.timedelta(weeks=52), '12M 4d'),
+ (dt.timedelta(days=360), '12M'),
+ (dt.timedelta(days=364), '12M 4d'),
+ (dt.timedelta(days=365), '1Y'),
+ (dt.timedelta(days=366), '1Y 1d'),
+ (dt.timedelta(hours=2, minutes=5, seconds=10), '02:05:10'),
+ (dt.timedelta(minutes=15, microseconds=42), '00:15:00.000042'),
+ (dt.timedelta(days=1, microseconds=42), '1d .000042'),
+ (dt.timedelta(seconds=-1), '-00:00:01'),
+ (dt.timedelta(days=-1, hours=-5, minutes=-30), '-1d 05:30'),
+ ]
+
+ def test_format(self):
+ "Test format"
+ for timedelta, text in self._format_values():
+ self.assertEqual(format(timedelta), text,
+ msg="format(%r)" % timedelta)
+
+ def _parse_values(self):
+ return self._format_values() + [
+ (dt.timedelta(), ' '),
+ (dt.timedelta(), 'foo'),
+ (dt.timedelta(days=1.5), '1.5d'),
+ (dt.timedelta(days=-2), '1d -1d'),
+ (dt.timedelta(hours=1, minutes=5, seconds=10), '1:5:10:42'),
+ (dt.timedelta(hours=2), '1: 1:'),
+ (dt.timedelta(hours=.25), ':15'),
+ (dt.timedelta(hours=1), '1h'),
+ (dt.timedelta(hours=.25), '.25h'),
+ ]
+
+ def test_parse(self):
+ "Test parse"
+ for timedelta, text in self._parse_values():
+ self.assertEqual(parse(text), timedelta,
+ msg="parse(%r)" % text)