newitem fields: dropped support in to_python() for converting from None for default value, improved raising of TypeError instead of ValueError when appropiate, added and adapted unittests

This commit is contained in:
Pablo Hoffman 2009-07-13 21:10:29 -03:00
parent 72457c3e4e
commit c73ff8198b
2 changed files with 104 additions and 77 deletions

View File

@ -41,73 +41,76 @@ class DateField(BaseField):
ansi_date_re = re.compile(r'^\d{4}-\d{1,2}-\d{1,2}$')
def to_python(self, value):
if value is None:
return value
if isinstance(value, datetime.datetime):
return value.date()
if isinstance(value, datetime.date):
elif isinstance(value, datetime.date):
return value
elif isinstance(value, basestring):
if not self.ansi_date_re.search(value):
raise ValueError("Enter a valid date in YYYY-MM-DD format.")
if not self.ansi_date_re.search(value):
raise ValueError("Enter a valid date in YYYY-MM-DD format.")
year, month, day = map(int, value.split('-'))
try:
return datetime.date(year, month, day)
except ValueError, e:
raise ValueError("Invalid date: %s" % str(e))
year, month, day = map(int, value.split('-'))
try:
return datetime.date(year, month, day)
except ValueError, e:
raise ValueError("Invalid date: %s" % str(e))
else:
raise TypeError("Cannot instatiante %s with %s" \
% (self.__class__.__name__, type(value).__name__))
class DateTimeField(BaseField):
def to_python(self, value):
if value is None:
return value
if isinstance(value, datetime.datetime):
return value
if isinstance(value, datetime.date):
elif isinstance(value, datetime.date):
return datetime.datetime(value.year, value.month, value.day)
# Attempt to parse a datetime:
value = str(value)
# split usecs, because they are not recognized by strptime.
if '.' in value:
try:
value, usecs = value.split('.')
usecs = int(usecs)
except ValueError:
raise ValueError('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.')
else:
usecs = 0
kwargs = {'microsecond': usecs}
try: # Seconds are optional, so try converting seconds first.
return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6],
**kwargs)
except ValueError:
try: # Try without seconds.
return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5],
**kwargs)
except ValueError: # Try without hour/minutes/seconds.
elif isinstance(value, basestring):
# Attempt to parse a datetime:
value = str(value)
# split usecs, because they are not recognized by strptime.
if '.' in value:
try:
return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3],
**kwargs)
value, usecs = value.split('.')
usecs = int(usecs)
except ValueError:
raise ValueError('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.')
else:
usecs = 0
kwargs = {'microsecond': usecs}
try: # Seconds are optional, so try converting seconds first.
return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6],
**kwargs)
except ValueError:
try: # Try without seconds.
return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5],
**kwargs)
except ValueError: # Try without hour/minutes/seconds.
try:
return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3],
**kwargs)
except ValueError:
raise ValueError('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.')
else:
raise TypeError("Cannot instatiante %s with %s" \
% (self.__class__.__name__, type(value).__name__))
class DecimalField(BaseField):
def to_python(self, value):
return decimal.Decimal(value) if value is not None else None
return decimal.Decimal(value)
class FloatField(BaseField):
def to_python(self, value):
return float(value) if value is not None else None
return float(value)
class IntegerField(BaseField):
def to_python(self, value):
return int(value) if value is not None else None
return int(value)
class TextField(BaseField):
@ -116,46 +119,44 @@ class TextField(BaseField):
return self.to_python(self.to_single(value))
elif isinstance(value, unicode):
return value
elif value is None:
return value
else:
raise ValueError("TextField expects a unicode, got %s" \
% type(value).__name__)
raise TypeError("%s requires a unicode (or iterable of unicodes), got %s" \
% (self.__class__.__name__, type(value).__name__))
def to_single(self, value):
"Converts the input iterable into a single value."
return ' '.join(value)
"""Converts the input iterable into a single value"""
return ' '.join((self.to_python(x) for x in value))
class TimeField(BaseField):
def to_python(self, value):
if value is None:
return None
if isinstance(value, datetime.time):
return value
if isinstance(value, datetime.datetime):
return value.time
elif isinstance(value, basestring):
# Attempt to parse a datetime:
value = str(value)
# split usecs, because they are not recognized by strptime.
if '.' in value:
try:
value, usecs = value.split('.')
usecs = int(usecs)
except ValueError:
raise ValueError('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.')
else:
usecs = 0
kwargs = {'microsecond': usecs}
# Attempt to parse a datetime:
value = str(value)
# split usecs, because they are not recognized by strptime.
if '.' in value:
try:
value, usecs = value.split('.')
usecs = int(usecs)
try: # Seconds are optional, so try converting seconds first.
return datetime.time(*time.strptime(value, '%H:%M:%S')[3:6],
**kwargs)
except ValueError:
raise ValueError('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.')
try: # Try without seconds.
return datetime.time(*time.strptime(value, '%H:%M')[3:5],
**kwargs)
except ValueError:
raise ValueError('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.')
else:
usecs = 0
kwargs = {'microsecond': usecs}
try: # Seconds are optional, so try converting seconds first.
return datetime.time(*time.strptime(value, '%H:%M:%S')[3:6],
**kwargs)
except ValueError:
try: # Try without seconds.
return datetime.time(*time.strptime(value, '%H:%M')[3:5],
**kwargs)
except ValueError:
raise ValueError('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.')
raise TypeError("Cannot instatiante %s with %s" \
% (self.__class__.__name__, type(value).__name__))

View File

@ -68,7 +68,7 @@ class NewItemTest(unittest.TestCase):
class TestItem(Item):
name = fields.TextField(default=3)
self.assertRaises(ValueError, set_wrong_default)
self.assertRaises(TypeError, set_wrong_default)
def test_to_python_iter(self):
class TestItem(Item):
@ -134,16 +134,19 @@ class NewItemFieldsTest(unittest.TestCase):
i = TestItem()
i.field = True
assert i.field == True
assert i.field is True
i.field = 1
assert i.field == True
assert i.field is True
i.field = False
assert i.field == False
assert i.field is False
i.field = 0
assert i.field == False
assert i.field is False
i.field = None
assert i.field is False
def test_date_field(self):
class TestItem(Item):
@ -172,6 +175,8 @@ class NewItemFieldsTest(unittest.TestCase):
self.assertRaises(ValueError, set_invalid_date)
self.assertRaises(TypeError, setattr, i, 'field', None)
def test_datetime_field(self):
class TestItem(Item):
field = fields.DateTimeField()
@ -214,6 +219,8 @@ class NewItemFieldsTest(unittest.TestCase):
self.assertRaises(ValueError, set_invalid_date)
self.assertRaises(TypeError, setattr, i, 'field', None)
def test_decimal_field(self):
class TestItem(Item):
field = fields.DecimalField()
@ -231,6 +238,8 @@ class NewItemFieldsTest(unittest.TestCase):
self.assertRaises(decimal.InvalidOperation, set_invalid_value)
self.assertRaises(TypeError, setattr, i, 'field', None)
def test_float_field(self):
class TestItem(Item):
field = fields.FloatField()
@ -248,6 +257,8 @@ class NewItemFieldsTest(unittest.TestCase):
self.assertRaises(ValueError, set_invalid_value)
self.assertRaises(TypeError, setattr, i, 'field', None)
def test_integer_field(self):
class TestItem(Item):
field = fields.IntegerField()
@ -265,6 +276,8 @@ class NewItemFieldsTest(unittest.TestCase):
self.assertRaises(ValueError, set_invalid_value)
self.assertRaises(TypeError, setattr, i, 'field', None)
def test_text_field(self):
class TestItem(Item):
field = fields.TextField()
@ -278,12 +291,23 @@ class NewItemFieldsTest(unittest.TestCase):
def set_str():
i.field = 'string'
self.assertRaises(ValueError, set_str)
# must be unicode!
self.assertRaises(TypeError, set_str)
self.assertRaises(TypeError, setattr, i, 'field', None)
def set_invalid_value():
i.field = 3
self.assertRaises(ValueError, set_invalid_value)
self.assertRaises(TypeError, set_invalid_value)
i = TestItem()
i.field = [u'hello', u'world']
self.assertEqual(i.field, u'hello world')
assert isinstance(i.field, unicode)
self.assertRaises(TypeError, setattr, i, 'field', [u'hello', 3, u'world'])
self.assertRaises(TypeError, setattr, i, 'field', [u'hello', 'world'])
def test_time_field(self):
class TestItem(Item):
@ -295,6 +319,8 @@ class NewItemFieldsTest(unittest.TestCase):
i.field = dt_t
assert i.field == dt_t
self.assertRaises(TypeError, setattr, i, 'field', None)
dt_dt = datetime.datetime.today()
i.field = dt_dt
assert i.field == dt_dt.time