Add time format validation

review342002
This commit is contained in:
Cédric Krier committed 2012-05-16 13:04:36 +02:00
1 parent 3a42c2ef49
commit 3ebda5c8ee
8 files changed
+108 -5

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
* Add time format validation
* Remove ModelSQL.default_sequence
Version 2.4.0 - 2012-04-23
+12 -2
View File
@@ -272,17 +272,27 @@ A date, represented in Python by a ``datetime.date`` instance.
DateTime
--------
.. class:: DateTime(string[, \**options])
.. class:: DateTime(string[, format, \**options])
A date and time, represented in Python by a ``datetime.datetime`` instance.
.. attribute:: DateTime.format
A string format as used by strftime. This format will be used to display
the time part of the field. The default value is `%H:%M:%S`.
The value can be replaced by a :class:`~trytond.pyson.PYSON` statement.
Time
----
.. class:: Time(string[, \**options])
.. class:: Time(string[, format, \**options])
A time, represented in Python by a ``datetime.time`` instance.
.. attribute:: Time.format
Same as :attr:`DateTime.format`
Binary
------
+9
View File
@@ -177,6 +177,15 @@ this repository contains the full copyright notices and license terms. -->
<field name="module">ir</field>
<field name="fuzzy" eval="False"/>
</record>
<record model="ir.translation" id="translation_time_format_validation_record">
<field name="name">time_format_validation_record</field>
<field name="lang">en_US</field>
<field name="type">error</field>
<field name="src">The time value of field "%s" on "%s" is not valid.</field>
<field name="value">The time value of field "%s" on "%s" is not valid.</field>
<field name="module">ir</field>
<field name="fuzzy" eval="False"/>
</record>
<record model="ir.translation" id="translation_access_error">
<field name="name">access_error</field>
<field name="lang">en_US</field>
+17 -1
View File
@@ -17,8 +17,24 @@ class DateTime(Field):
'''
_type = 'datetime'
def __init__(self, string='', format='%H:%M:%S', help='', required=False,
readonly=False, domain=None, states=None, select=False,
on_change=None, on_change_with=None, depends=None,
order_field=None, context=None, loading='eager'):
'''
:param format: The validation format as used by strftime.
'''
super(DateTime, 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, order_field=order_field, context=context,
loading=loading)
self.format = format
class Time(Field):
__init__.__doc__ += Field.__init__.__doc__
class Time(DateTime):
'''
Define a time field (``time``).
'''
+3 -1
View File
@@ -554,10 +554,12 @@ class Model(WarningErrorMixin, URLMixin):
and hasattr(self._columns[field], 'field'):
res[field]['relation_field'] = copy.copy(
self._columns[field].field)
if res[field]['type'] in ('datetime', 'time'):
res[field]['format'] = copy.copy(self._columns[field].format)
# convert attributes into pyson
for attr in ('states', 'domain', 'context', 'digits',
'add_remove'):
'add_remove', 'format'):
if attr in res[field]:
res[field][attr] = encoder.encode(res[field][attr])
+30 -1
View File
@@ -19,7 +19,7 @@ from trytond.model import fields
from trytond.model.browse import BrowseRecordList, BrowseRecord, \
BrowseRecordNull
from trytond.model.browse import EvalEnvironment
from trytond.tools import safe_eval, reduce_domain
from trytond.tools import safe_eval, reduce_domain, datetime_strftime
from trytond.pyson import PYSONEncoder, PYSONDecoder, PYSON
from trytond.const import OPERATORS, RECORD_CACHE_SIZE
from trytond.transaction import Transaction
@@ -1132,6 +1132,35 @@ class ModelStorage(Model):
digits_test(record[field_name], field.digits,
field_name)
def format_test(value, format, field_name):
if not value:
return
if not isinstance(value, datetime.time):
value = value.time()
if value != datetime.datetime.strptime(
value.strftime(format), format).time():
self.raise_user_error('time_format_validation_record',
error_args=self._get_error_args(field_name))
# validate time format
if (field._type in ('datetime', 'time')
and field_name not in ('create_date', 'write_date')):
if is_pyson(field.format):
pyson_format = PYSONDecoder().encode(field.format)
for record in records:
env = EvalEnvironment(record, self)
env.update(Transaction().context)
env['current_date'] = datetime.datetime.today()
env['time'] = time
env['context'] = Transaction().context
env['active_id'] = record.id
format = PYSONDecoder(env).decode(pyson_format)
format_test(record[field_name], format, field_name)
else:
for record in records:
format_test(record[field_name], field.format,
field_name)
def _clean_defaults(self, defaults):
pool = Pool()
vals = {}
+18
View File
@@ -356,6 +356,15 @@ class DateTimeRequired(ModelSQL):
DateTimeRequired()
class DateTimeFormat(ModelSQL):
'DateTime Format'
_name = 'test.datetime_format'
_description = __doc__
datetime = fields.DateTime(string='DateTime', format='%H:%M')
DateTimeFormat()
class Time(ModelSQL):
'Time'
_name = 'test.time'
@@ -386,6 +395,15 @@ class TimeRequired(ModelSQL):
TimeRequired()
class TimeFormat(ModelSQL):
'Time Format'
_name = 'test.time_format'
_description = __doc__
time = fields.Time(string='Time', format='%H:%M')
TimeFormat()
class One2One(ModelSQL):
'One2One'
_name = 'test.one2one'
+18
View File
@@ -65,10 +65,12 @@ class FieldsTestCase(unittest.TestCase):
self.datetime = POOL.get('test.datetime')
self.datetime_default = POOL.get('test.datetime_default')
self.datetime_required = POOL.get('test.datetime_required')
self.datetime_format = POOL.get('test.datetime_format')
self.time = POOL.get('test.time')
self.time_default = POOL.get('test.time_default')
self.time_required = POOL.get('test.time_required')
self.time_format = POOL.get('test.time_format')
self.one2one = POOL.get('test.one2one')
self.one2one_target = POOL.get('test.one2one.target')
@@ -2059,6 +2061,14 @@ class FieldsTestCase(unittest.TestCase):
datetime9 = self.datetime.read(datetime9_id, ['datetime'])
self.assert_(datetime9['datetime'] == today)
# Test format
self.assert_(self.datetime_format.create({
'datetime': datetime.datetime(2009, 1, 1, 12, 30),
}))
self.failUnlessRaises(Exception, self.datetime_format.create, {
'datetime': datetime.datetime(2009, 1, 1, 12, 30, 25),
})
transaction.cursor.rollback()
def test0100time(self):
@@ -2312,6 +2322,14 @@ class FieldsTestCase(unittest.TestCase):
time9 = self.time.read(time9_id, ['time'])
self.assert_(time9['time'] == evening)
# Test format
self.assert_(self.time_format.create({
'time': datetime.time(12, 30),
}))
self.failUnlessRaises(Exception, self.time_format.create, {
'time': datetime.time(12, 30, 25),
})
transaction.cursor.rollback()
def test0110one2one(self):