From b44409a20378afa76d07b1c584c5681a540ee527 Mon Sep 17 00:00:00 2001 From: Ismael Carnales Date: Mon, 13 Jul 2009 10:31:32 -0300 Subject: [PATCH] added TimeField to newitem --- docs/proposed/newitem-fields.rst | 9 +++++++ scrapy/contrib_exp/newitem/fields.py | 34 +++++++++++++++++++++++++ scrapy/tests/test_newitem.py | 38 ++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/docs/proposed/newitem-fields.rst b/docs/proposed/newitem-fields.rst index 3708d7ea0..39cd4ae9e 100644 --- a/docs/proposed/newitem-fields.rst +++ b/docs/proposed/newitem-fields.rst @@ -76,3 +76,12 @@ DateField .. _datetime.date: http://docs.python.org/library/datetime.html#datetime.date +TimeField +--------- + +.. class:: TimeField + + A time, represented in Python by a `datetime.time`_ instance. + +.. _datetime.time: http://docs.python.org/library/datetime.html#datetime.time + diff --git a/scrapy/contrib_exp/newitem/fields.py b/scrapy/contrib_exp/newitem/fields.py index 15773d3ab..9d4e6bb7a 100644 --- a/scrapy/contrib_exp/newitem/fields.py +++ b/scrapy/contrib_exp/newitem/fields.py @@ -3,6 +3,7 @@ import decimal import re import time + class BaseField(object): def __init__(self, default=None): self.default = default or self.to_python(None) @@ -121,3 +122,36 @@ class StringField(BaseField): "Converts the input iterable into a single value." return ' '.join(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 + + # 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} + + 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.') + diff --git a/scrapy/tests/test_newitem.py b/scrapy/tests/test_newitem.py index 68b72087d..6a15f39f2 100644 --- a/scrapy/tests/test_newitem.py +++ b/scrapy/tests/test_newitem.py @@ -246,3 +246,41 @@ class NewItemFieldsTest(unittest.TestCase): self.assertRaises(ValueError, set_invalid_value) + def test_time_field(self): + class TestItem(Item): + field = fields.TimeField() + + i = TestItem() + + dt_t = datetime.time(11, 8, 10, 100) + i.field = dt_t + assert i.field == dt_t + + dt_dt = datetime.datetime.today() + i.field = dt_dt + assert i.field == dt_dt.time + + i.field = '11:08:10.100' + assert i.field == datetime.time(11, 8, 10, 100) + + i.field = '11:08:10' + assert i.field == datetime.time(11, 8, 10) + + i.field = '11:08' + assert i.field == datetime.time(11, 8) + + def set_invalid_usecs(): + i.field = '11:08:10.usecs' + + self.assertRaises(ValueError, set_invalid_usecs) + + def set_invalid_format(): + i.field = 'string' + + self.assertRaises(ValueError, set_invalid_format) + + def set_invalid_time(): + i.field = '25:08:10' + + self.assertRaises(ValueError, set_invalid_time) +