Add TimeDelta field
And remove float_time widget. issue4026 review5911002
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
* Remove float_time widget
|
||||
* Add TimeDelta field
|
||||
* search_global yields record instead of id
|
||||
* Add ModelTestCase
|
||||
* Add test for missing default model access
|
||||
|
||||
@@ -364,6 +364,20 @@ A time, represented in Python by a ``datetime.time`` instance.
|
||||
|
||||
Same as :attr:`DateTime.format`
|
||||
|
||||
TimeDelta
|
||||
---------
|
||||
|
||||
.. class::TimeDelta(string[, converter[, \**options]])
|
||||
|
||||
An interval, represented in Python by a ``datetime.timedelta`` instance.
|
||||
|
||||
.. attribute:: TimeDelta.converter
|
||||
|
||||
The name of the context key containing the time converter.
|
||||
A time converter is a dictionary with the keys: ``s`` (second), ``m``
|
||||
(minute), ``h`` (hour), ``d`` (day), ``w`` (week), ``M`` (month), ``Y``
|
||||
(year) and the value in second.
|
||||
|
||||
Binary
|
||||
------
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
|
||||
from psycopg2.extensions import register_type, register_adapter
|
||||
from psycopg2.extensions import UNICODE, AsIs
|
||||
try:
|
||||
from psycopg2.extensions import PYDATE, PYDATETIME, PYTIME
|
||||
from psycopg2.extensions import PYDATE, PYDATETIME, PYTIME, PYINTERVAL
|
||||
except ImportError:
|
||||
PYDATE, PYDATETIME, PYTIME = None, None, None
|
||||
PYDATE, PYDATETIME, PYTIME, PYINTERVAL = None, None, None, None
|
||||
from psycopg2 import IntegrityError as DatabaseIntegrityError
|
||||
from psycopg2 import OperationalError as DatabaseOperationalError
|
||||
import time
|
||||
@@ -379,5 +379,7 @@ if PYDATETIME:
|
||||
register_type(PYDATETIME)
|
||||
if PYTIME:
|
||||
register_type(PYTIME)
|
||||
if PYINTERVAL:
|
||||
register_type(PYINTERVAL)
|
||||
register_adapter(float, lambda value: AsIs(repr(value)))
|
||||
register_adapter(Decimal, lambda value: AsIs(str(value)))
|
||||
|
||||
@@ -419,3 +419,6 @@ sqlite.register_adapter(datetime.datetime, adapt_datetime)
|
||||
sqlite.register_adapter(datetime.time, lambda val: val.isoformat())
|
||||
sqlite.register_converter('TIME', lambda val: datetime.time(*map(int,
|
||||
val.split(':'))))
|
||||
sqlite.register_adapter(datetime.timedelta, lambda val: val.total_seconds())
|
||||
sqlite.register_converter('INTERVAL', lambda val: datetime.timedelta(
|
||||
seconds=float(val)))
|
||||
|
||||
+32
-9
@@ -2,7 +2,7 @@
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
import datetime
|
||||
import time
|
||||
from sql import Literal
|
||||
from sql import Literal, Null
|
||||
from sql.aggregate import Count, Max
|
||||
|
||||
from ..model import ModelView, ModelSQL, fields
|
||||
@@ -45,9 +45,10 @@ class Trigger(ModelSQL, ModelView):
|
||||
limit_number = fields.Integer('Limit Number', required=True,
|
||||
help='Limit the number of call to "Action Function" by records.\n'
|
||||
'0 for no limit.')
|
||||
minimum_delay = fields.Float('Minimum Delay', help='Set a minimum delay '
|
||||
'in minutes between call to "Action Function" for the same record.\n'
|
||||
'0 for no delay.')
|
||||
minimum_time_delay = fields.TimeDelta('Minimum Delay',
|
||||
help='Set a minimum time delay between call to "Action Function" '
|
||||
'for the same record.\n'
|
||||
'empty for no delay.')
|
||||
action_model = fields.Many2One('ir.model', 'Action Model', required=True)
|
||||
action_function = fields.Char('Action Function', required=True)
|
||||
_get_triggers_cache = Cache('ir_trigger.get_triggers')
|
||||
@@ -66,6 +67,29 @@ class Trigger(ModelSQL, ModelView):
|
||||
})
|
||||
cls._order.insert(0, ('name', 'ASC'))
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module_name):
|
||||
TableHandler = backend.get('TableHandler')
|
||||
cursor = Transaction().cursor
|
||||
table = TableHandler(cursor, cls, module_name)
|
||||
sql_table = cls.__table__()
|
||||
|
||||
super(Trigger, cls).__register__(module_name)
|
||||
|
||||
# Migration from 3.4:
|
||||
# change minimum_delay into timedelta minimu_time_delay
|
||||
if table.column_exist('minimum_delay'):
|
||||
cursor.execute(*sql_table.select(
|
||||
sql_table.id, sql_table.minimum_delay,
|
||||
where=sql_table.minimum_delay != Null))
|
||||
for id_, delay in cursor.fetchall():
|
||||
delay = datetime.timedelta(hours=delay)
|
||||
cursor.execute(*sql_table.update(
|
||||
[sql_table.minimu_time_delay],
|
||||
[delay],
|
||||
where=sql_table.id == id_))
|
||||
table.drop_column('minimum_delay')
|
||||
|
||||
@classmethod
|
||||
def validate(cls, triggers):
|
||||
super(Trigger, cls).validate(triggers)
|
||||
@@ -182,8 +206,8 @@ class Trigger(ModelSQL, ModelView):
|
||||
new_ids.append(record_id)
|
||||
ids = new_ids
|
||||
|
||||
# Filter on minimum_delay
|
||||
if trigger.minimum_delay:
|
||||
# Filter on minimum_time_delay
|
||||
if trigger.minimum_time_delay:
|
||||
new_ids = []
|
||||
for sub_ids in grouped_slice(ids):
|
||||
sub_ids = list(sub_ids)
|
||||
@@ -211,15 +235,14 @@ class Trigger(ModelSQL, ModelView):
|
||||
delay[record_id] = datetime.datetime(year, month, day,
|
||||
hours, minutes, seconds, microseconds)
|
||||
if (datetime.datetime.now() - delay[record_id]
|
||||
>= datetime.timedelta(
|
||||
minutes=trigger.minimum_delay)):
|
||||
>= trigger.minimum_time_delay):
|
||||
new_ids.append(record_id)
|
||||
ids = new_ids
|
||||
|
||||
records = Model.browse(ids)
|
||||
if records:
|
||||
getattr(ActionModel, trigger.action_function)(records, trigger)
|
||||
if trigger.limit_number or trigger.minimum_delay:
|
||||
if trigger.limit_number or trigger.minimum_time_delay:
|
||||
to_create = []
|
||||
for record in records:
|
||||
to_create.append({
|
||||
|
||||
@@ -49,7 +49,7 @@ attlist.field &=
|
||||
| "selection"
|
||||
| "char"
|
||||
| "password"
|
||||
| "float_time"
|
||||
| "timedelta"
|
||||
| "boolean"
|
||||
| "reference"
|
||||
| "binary"
|
||||
@@ -98,7 +98,6 @@ attlist.field &=
|
||||
| "top_to_bottom"
|
||||
}?
|
||||
attlist.field &= attribute spell { text }?
|
||||
attlist.field &= attribute float_time { text }?
|
||||
attlist.field &=
|
||||
[a:defaultValue = "0"] attribute filename_visible { "0" | "1" }?
|
||||
attlist.field &= [a:defaultValue = "0"] attribute pre_validate { "0" | "1" }?
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
<value>selection</value>
|
||||
<value>char</value>
|
||||
<value>password</value>
|
||||
<value>float_time</value>
|
||||
<value>timedelta</value>
|
||||
<value>boolean</value>
|
||||
<value>reference</value>
|
||||
<value>binary</value>
|
||||
@@ -327,11 +327,6 @@
|
||||
<attribute name="spell"/>
|
||||
</optional>
|
||||
</define>
|
||||
<define name="attlist.field" combine="interleave">
|
||||
<optional>
|
||||
<attribute name="float_time"/>
|
||||
</optional>
|
||||
</define>
|
||||
<define name="attlist.field" combine="interleave">
|
||||
<optional>
|
||||
<attribute name="filename_visible" a:defaultValue="0">
|
||||
|
||||
@@ -23,8 +23,7 @@ attlist.field &= attribute domain { text }?
|
||||
attlist.field &= attribute fill { "0" | "1" }?
|
||||
attlist.field &= attribute empty { "0" | "1" }?
|
||||
attlist.field &= attribute color { text }?
|
||||
attlist.field &= attribute widget { "float_time" }?
|
||||
attlist.field &= attribute float_time { text }?
|
||||
attlist.field &= attribute timedelta { text }?
|
||||
attlist.field &=
|
||||
[ a:defaultValue = "linear" ]
|
||||
attribute interpolation { "constant-left" | "constant-right" | "constant-center" | "linear" }?
|
||||
|
||||
@@ -115,14 +115,7 @@
|
||||
</define>
|
||||
<define name="attlist.field" combine="interleave">
|
||||
<optional>
|
||||
<attribute name="widget">
|
||||
<value>float_time</value>
|
||||
</attribute>
|
||||
</optional>
|
||||
</define>
|
||||
<define name="attlist.field" combine="interleave">
|
||||
<optional>
|
||||
<attribute name="float_time"/>
|
||||
<attribute name="timedelta"/>
|
||||
</optional>
|
||||
</define>
|
||||
<define name="attlist.field" combine="interleave">
|
||||
|
||||
@@ -27,7 +27,7 @@ attlist.field &=
|
||||
| "selection"
|
||||
| "float"
|
||||
| "numeric"
|
||||
| "float_time"
|
||||
| "timedelta"
|
||||
| "integer"
|
||||
| "datetime"
|
||||
| "time"
|
||||
@@ -58,7 +58,6 @@ attlist.field &=
|
||||
| "bottom_to_top"
|
||||
| "top_to_bottom"
|
||||
}?
|
||||
attlist.field &= attribute float_time { text }?
|
||||
attlist.field &= [a:defaultValue = "0"] attribute pre_validate { "0" | "1" }?
|
||||
attlist.field &= [a:defaultValue = "1"] attribute completion { "0" | "1" }?
|
||||
attlist.field &= attribute string { text }?
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
<value>selection</value>
|
||||
<value>float</value>
|
||||
<value>numeric</value>
|
||||
<value>float_time</value>
|
||||
<value>timedelta</value>
|
||||
<value>integer</value>
|
||||
<value>datetime</value>
|
||||
<value>time</value>
|
||||
@@ -168,11 +168,6 @@
|
||||
</attribute>
|
||||
</optional>
|
||||
</define>
|
||||
<define name="attlist.field" combine="interleave">
|
||||
<optional>
|
||||
<attribute name="float_time"/>
|
||||
</optional>
|
||||
</define>
|
||||
<define name="attlist.field" combine="interleave">
|
||||
<optional>
|
||||
<attribute name="pre_validate" a:defaultValue="0">
|
||||
|
||||
@@ -22,8 +22,8 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="condition" colspan="3"/>
|
||||
<label name="limit_number"/>
|
||||
<field name="limit_number"/>
|
||||
<label name="minimum_delay"/>
|
||||
<field name="minimum_delay" widget="float_time"/>
|
||||
<label name="minimum_time_delay"/>
|
||||
<field name="minimum_time_delay"/>
|
||||
<label name="action_model"/>
|
||||
<field name="action_model"/>
|
||||
<label name="action_function"/>
|
||||
|
||||
@@ -134,3 +134,36 @@ class Time(DateTime):
|
||||
|
||||
def sql_type(self):
|
||||
return SQLType('TIME', 'TIME')
|
||||
|
||||
|
||||
class TimeDelta(Field):
|
||||
'''
|
||||
Define a timedelta field (``timedelta``).
|
||||
'''
|
||||
_type = 'timedelta'
|
||||
|
||||
def __init__(self, string='', converter=None, help='', required=False,
|
||||
readonly=False, domain=None, states=None, select=False,
|
||||
on_change=None, on_change_with=None, depends=None,
|
||||
context=None, loading='eager'):
|
||||
'''
|
||||
:param converter: The name of the context key containing
|
||||
the time converter.
|
||||
'''
|
||||
super(TimeDelta, self).__init__(string=string, help=help,
|
||||
required=required, readonly=readonly, domain=domain, states=states,
|
||||
select=select, on_change=on_change, on_change_with=on_change_with,
|
||||
depends=depends, context=context, loading=loading)
|
||||
self.converter = converter
|
||||
|
||||
@staticmethod
|
||||
def sql_format(value):
|
||||
if isinstance(value, (Query, Expression)):
|
||||
return value
|
||||
if value is None:
|
||||
return None
|
||||
assert(isinstance(value, datetime.timedelta))
|
||||
return value
|
||||
|
||||
def sql_type(self):
|
||||
return SQLType('INTERVAL', 'INTERVAL')
|
||||
|
||||
@@ -212,6 +212,7 @@ class Model(WarningErrorMixin, URLMixin, PoolBase):
|
||||
'filename',
|
||||
'selection_change_with',
|
||||
'domain',
|
||||
'converter',
|
||||
):
|
||||
if getattr(cls._fields[field], arg, None) is not None:
|
||||
value = getattr(cls._fields[field], arg)
|
||||
|
||||
@@ -55,6 +55,8 @@ JSONDecoder.register('date',
|
||||
JSONDecoder.register('time',
|
||||
lambda dct: datetime.time(dct['hour'], dct['minute'], dct['second'],
|
||||
dct['microsecond']))
|
||||
JSONDecoder.register('timedelta',
|
||||
lambda dct: datetime.timedelta(seconds=dct['seconds']))
|
||||
JSONDecoder.register('buffer', lambda dct:
|
||||
buffer(base64.decodestring(dct['base64'])))
|
||||
JSONDecoder.register('Decimal', lambda dct: Decimal(dct['decimal']))
|
||||
@@ -105,6 +107,11 @@ JSONEncoder.register(datetime.time,
|
||||
'second': o.second,
|
||||
'microsecond': o.microsecond,
|
||||
})
|
||||
JSONEncoder.register(datetime.timedelta,
|
||||
lambda o: {
|
||||
'__class__': 'timedelta',
|
||||
'seconds': o.total_seconds(),
|
||||
})
|
||||
JSONEncoder.register(buffer,
|
||||
lambda o: {
|
||||
'__class__': 'buffer',
|
||||
|
||||
@@ -54,11 +54,19 @@ def dump_time(self, value, write):
|
||||
}
|
||||
self.dump_struct(value, write)
|
||||
|
||||
|
||||
def dump_timedelta(self, value, write):
|
||||
value = {'__class__': 'timedelta',
|
||||
'seconds': value.total_seconds(),
|
||||
}
|
||||
self.dump_struct(value, write)
|
||||
|
||||
xmlrpclib.Marshaller.dispatch[Decimal] = dump_decimal
|
||||
xmlrpclib.Marshaller.dispatch[type(None)] = \
|
||||
lambda self, value, write: write("<value><nil/></value>")
|
||||
xmlrpclib.Marshaller.dispatch[datetime.date] = dump_date
|
||||
xmlrpclib.Marshaller.dispatch[datetime.time] = dump_time
|
||||
xmlrpclib.Marshaller.dispatch[datetime.timedelta] = dump_timedelta
|
||||
xmlrpclib.Marshaller.dispatch[buffer] = dump_buffer
|
||||
|
||||
|
||||
@@ -94,6 +102,8 @@ XMLRPCDecoder.register('date',
|
||||
XMLRPCDecoder.register('time',
|
||||
lambda dct: datetime.time(dct['hour'], dct['minute'], dct['second'],
|
||||
dct['microsecond']))
|
||||
XMLRPCDecoder.register('timedelta',
|
||||
lambda dct: datetime.timedelta(seconds=dct['seconds']))
|
||||
XMLRPCDecoder.register('Decimal', lambda dct: Decimal(dct['decimal']))
|
||||
|
||||
|
||||
|
||||
@@ -54,6 +54,9 @@ def register():
|
||||
TimeDefault,
|
||||
TimeRequired,
|
||||
TimeFormat,
|
||||
TimeDelta,
|
||||
TimeDeltaDefault,
|
||||
TimeDeltaRequired,
|
||||
One2One,
|
||||
One2OneTarget,
|
||||
One2OneRelation,
|
||||
|
||||
@@ -16,6 +16,7 @@ __all__ = [
|
||||
'Date', 'DateDefault', 'DateRequired',
|
||||
'DateTime', 'DateTimeDefault', 'DateTimeRequired', 'DateTimeFormat',
|
||||
'Time', 'TimeDefault', 'TimeRequired', 'TimeFormat',
|
||||
'TimeDelta', 'TimeDeltaDefault', 'TimeDeltaRequired',
|
||||
'One2One', 'One2OneTarget', 'One2OneRelation', 'One2OneRequired',
|
||||
'One2OneRequiredRelation', 'One2OneDomain', 'One2OneDomainRelation',
|
||||
'One2Many', 'One2ManyTarget',
|
||||
@@ -315,6 +316,31 @@ class TimeFormat(ModelSQL):
|
||||
time = fields.Time(string='Time', format='%H:%M')
|
||||
|
||||
|
||||
class TimeDelta(ModelSQL):
|
||||
'TimeDelta'
|
||||
__name__ = 'test.timedelta'
|
||||
timedelta = fields.TimeDelta(string='TimeDelta', help='Test timedelta',
|
||||
required=False)
|
||||
|
||||
|
||||
class TimeDeltaDefault(ModelSQL):
|
||||
'TimeDelta Default'
|
||||
__name__ = 'test.timedelta_default'
|
||||
timedelta = fields.TimeDelta(string='TimeDelta', help='Test timedelta',
|
||||
required=False)
|
||||
|
||||
@staticmethod
|
||||
def default_timedelta():
|
||||
return datetime.timedelta(seconds=3600)
|
||||
|
||||
|
||||
class TimeDeltaRequired(ModelSQL):
|
||||
'TimeDelta Required'
|
||||
__name__ = 'test.timedelta_required'
|
||||
timedelta = fields.TimeDelta(string='TimeDelta', help='Test timedelta',
|
||||
required=True)
|
||||
|
||||
|
||||
class One2One(ModelSQL):
|
||||
'One2One'
|
||||
__name__ = 'test.one2one'
|
||||
|
||||
@@ -67,6 +67,10 @@ class FieldsTestCase(unittest.TestCase):
|
||||
self.time_required = POOL.get('test.time_required')
|
||||
self.time_format = POOL.get('test.time_format')
|
||||
|
||||
self.timedelta = POOL.get('test.timedelta')
|
||||
self.timedelta_default = POOL.get('test.timedelta_default')
|
||||
self.timedelta_required = POOL.get('test.timedelta_required')
|
||||
|
||||
self.one2one = POOL.get('test.one2one')
|
||||
self.one2one_target = POOL.get('test.one2one.target')
|
||||
self.one2one_required = POOL.get('test.one2one_required')
|
||||
@@ -3258,6 +3262,222 @@ class FieldsTestCase(unittest.TestCase):
|
||||
|
||||
transaction.cursor.rollback()
|
||||
|
||||
def test0200timedelta(self):
|
||||
'Test timedelta'
|
||||
with Transaction().start(DB_NAME, USER,
|
||||
context=CONTEXT) as transaction:
|
||||
|
||||
minute = datetime.timedelta(minutes=1)
|
||||
hour = datetime.timedelta(hours=1)
|
||||
day = datetime.timedelta(days=1)
|
||||
default_timedelta = datetime.timedelta(seconds=3600)
|
||||
|
||||
timedelta1, = self.timedelta.create([{
|
||||
'timedelta': hour,
|
||||
}])
|
||||
self.assert_(timedelta1)
|
||||
self.assertEqual(timedelta1.timedelta, hour)
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '=', hour),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '=', day),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '=', None),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '!=', day),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '!=', None),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'in', [hour]),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'in', [day]),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'in', [minute]),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'in', [None]),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'in', []),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'not in', [hour]),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'not in', [day]),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'not in', [None]),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'not in', []),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '<', day),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '<', minute),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '<', hour),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '<=', hour),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '<=', minute),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '<=', day),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '>', day),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '>', minute),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '>', hour),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '>=', day),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '>=', minute),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '>=', hour),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1])
|
||||
|
||||
timedelta2, = self.timedelta.create([{
|
||||
'timedelta': minute,
|
||||
}])
|
||||
self.assert_(timedelta2)
|
||||
self.assertEqual(timedelta2.timedelta, minute)
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', '=', minute),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta2])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'in', [minute, hour]),
|
||||
])
|
||||
self.assertEqual(timedelta, [timedelta1, timedelta2])
|
||||
|
||||
timedelta = self.timedelta.search([
|
||||
('timedelta', 'not in', [minute, hour]),
|
||||
])
|
||||
self.assertEqual(timedelta, [])
|
||||
|
||||
timedelta3, = self.timedelta.create([{}])
|
||||
self.assert_(timedelta3)
|
||||
self.assertEqual(timedelta3.timedelta, None)
|
||||
|
||||
timedelta4, = self.timedelta_default.create([{}])
|
||||
self.assert_(timedelta4)
|
||||
self.assertEqual(timedelta4.timedelta, default_timedelta)
|
||||
|
||||
self.timedelta.write([timedelta1], {
|
||||
'timedelta': minute,
|
||||
})
|
||||
self.assertEqual(timedelta1.timedelta, minute)
|
||||
|
||||
self.timedelta.write([timedelta2], {
|
||||
'timedelta': day,
|
||||
})
|
||||
self.assertEqual(timedelta2.timedelta, day)
|
||||
|
||||
self.assertRaises(Exception, self.timedelta.create, [{
|
||||
'timedelta': 'test',
|
||||
}])
|
||||
|
||||
self.assertRaises(Exception, self.timedelta.write, [timedelta1], {
|
||||
'timedelta': 'test',
|
||||
})
|
||||
|
||||
self.assertRaises(Exception, self.timedelta.create, [{
|
||||
'timedelta': 1,
|
||||
}])
|
||||
|
||||
self.assertRaises(Exception, self.timedelta.write, [timedelta1], {
|
||||
'timedelta': 1,
|
||||
})
|
||||
|
||||
self.assertRaises(UserError, self.timedelta_required.create, [{}])
|
||||
transaction.cursor.rollback()
|
||||
|
||||
timedelta6, = self.timedelta_required.create([{
|
||||
'timedelta': day,
|
||||
}])
|
||||
self.assert_(timedelta6)
|
||||
|
||||
timedelta7, = self.timedelta.create([{
|
||||
'timedelta': None,
|
||||
}])
|
||||
self.assert_(timedelta7)
|
||||
|
||||
transaction.cursor.rollback()
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(FieldsTestCase)
|
||||
|
||||
Reference in New Issue
Block a user