diff options
| -rw-r--r-- | lesana/types.py | 40 | ||||
| -rw-r--r-- | tests/test_types.py | 110 | 
2 files changed, 148 insertions, 2 deletions
| diff --git a/lesana/types.py b/lesana/types.py index 500f21e..7f182ea 100644 --- a/lesana/types.py +++ b/lesana/types.py @@ -27,6 +27,16 @@ class LesanaType:      def empty(self):          raise NotImplementedError +    def update(self, value): +        """ +        Return an updated value, as appropriate for the field. + +        Default is to return the value itself, but types can use their +        configuration to e.g. increment a numerical value or return the +        current date(time). +        """ +        return value +      def _to_index_text(self, value):          """          Prepare a value for indexing. @@ -212,11 +222,24 @@ class LesanaDatetime(LesanaType):              )      def empty(self): -        if self.field.get('auto', False) == 'creation': +        if self.field.get('auto', False) in ('creation', 'update'):              return datetime.datetime.now(datetime.timezone.utc)          return None +    def update(self, value): +        """ +        Return an updated value. + +        If the field settings ``auto`` is ``update`` return the current +        datetime, otherwise the old value. + +        """ +        if self.field.get('auto', False) == 'update': +            return datetime.datetime.now(datetime.timezone.utc) + +        return value +  class LesanaDate(LesanaType):      """ @@ -239,11 +262,24 @@ class LesanaDate(LesanaType):              )      def empty(self): -        if self.field.get('auto', False) == 'creation': +        if self.field.get('auto', False) in ('creation', 'update'):              return datetime.date.today()          return None +    def update(self, value): +        """ +        Return an updated value. + +        If the field settings ``auto`` is ``update`` return the current +        date, otherwise the old value. + +        """ +        if self.field.get('auto', False) == 'update': +            return datetime.date.today() + +        return value +  class LesanaBoolean(LesanaType):      """ diff --git a/tests/test_types.py b/tests/test_types.py index 9663288..260167c 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -42,6 +42,9 @@ class testTypes(unittest.TestCase):          s = checker.load(None)          self.assertEqual(s, None) +        v = checker.update("Hello World!") +        self.assertEqual(v, "Hello World!") +      def test_text(self):          checker = types.LesanaText(self._get_field_def('text'), {}) @@ -54,6 +57,9 @@ class testTypes(unittest.TestCase):          s = checker.load(None)          self.assertEqual(s, None) +        v = checker.update("Hello World!") +        self.assertEqual(v, "Hello World!") +      def test_int(self):          checker = types.LesanaInt(self._get_field_def('integer'), {}) @@ -73,6 +79,9 @@ class testTypes(unittest.TestCase):          v = checker.load(None)          self.assertEqual(v, None) +        v = checker.update(10) +        self.assertEqual(v, 10) +      def test_float(self):          checker = types.LesanaFloat(self._get_field_def('float'), {}) @@ -95,6 +104,9 @@ class testTypes(unittest.TestCase):          v = checker.load(None)          self.assertEqual(v, None) +        v = checker.update(10.5) +        self.assertEqual(v, 10.5) +      def test_decimal(self):          checker = types.LesanaDecimal(self._get_field_def('decimal'), {}) @@ -117,6 +129,9 @@ class testTypes(unittest.TestCase):          v = checker.load(None)          self.assertEqual(v, None) +        v = checker.update(decimal.Decimal("10.5")) +        self.assertEqual(v, decimal.Decimal("10.5")) +      def test_timestamp(self):          checker = types.LesanaTimestamp(self._get_field_def('timestamp'), {}) @@ -147,6 +162,9 @@ class testTypes(unittest.TestCase):          v = checker.load(None)          self.assertEqual(v, None) +        v = checker.update(today) +        self.assertEqual(v, today) +      def test_datetime(self):          checker = types.LesanaDatetime(self._get_field_def('datetime'), {}) @@ -176,6 +194,9 @@ class testTypes(unittest.TestCase):          v = checker.load(None)          self.assertEqual(v, None) +        v = checker.update(now) +        self.assertEqual(v, now) +      def test_datetime_auto(self):          field_def = self._get_field_def('datetime')          field_def['auto'] = 'creation' @@ -193,6 +214,42 @@ class testTypes(unittest.TestCase):          v = checker.empty()          self.assertEqual(v, None) +        # auto=update fields should also be filled at creation time +        field_def['auto'] = 'update' +        checker = types.LesanaDatetime(field_def, {}) +        v = checker.empty() +        self.assertIsInstance(v, datetime.datetime) +        self.assertEqual(v.tzinfo, datetime.timezone.utc) +        self.assertEqual(v.year, now.year) + +    def test_datetime_auto_update(self): +        field_def = self._get_field_def('datetime') +        field_def['auto'] = 'update' +        checker = types.LesanaDatetime(field_def, {}) + +        now = datetime.datetime.now() +        past = datetime.datetime(2016, 12, 10, 21, 2) +        # we pass a date in the past +        v = checker.update(past) +        self.assertIsInstance(v, datetime.datetime) +        self.assertEqual(v.tzinfo, datetime.timezone.utc) +        # and we want to get a date in the present +        self.assertEqual(v.year, now.year) + +        # with auto=False we want our old date instead +        field_def['auto'] = False +        checker = types.LesanaDatetime(field_def, {}) + +        v = checker.update(past) +        self.assertEqual(v, past) + +        # and the same should happen with auto=creation +        field_def['auto'] = 'creation' +        checker = types.LesanaDatetime(field_def, {}) + +        v = checker.update(past) +        self.assertEqual(v, past) +      def test_date(self):          checker = types.LesanaDate(self._get_field_def('date'), {}) @@ -222,6 +279,9 @@ class testTypes(unittest.TestCase):          v = checker.load(None)          self.assertEqual(v, None) +        v = checker.update(today) +        self.assertEqual(v, today) +      def test_date_auto(self):          field_def = self._get_field_def('date')          field_def['auto'] = 'creation' @@ -238,6 +298,41 @@ class testTypes(unittest.TestCase):          v = checker.empty()          self.assertEqual(v, None) +        # auto=update fields should also be filled at creation time +        field_def['auto'] = 'update' +        checker = types.LesanaDate(field_def, {}) + +        v = checker.empty() +        self.assertIsInstance(v, datetime.date) +        self.assertEqual(v, today) + +    def test_date_auto_update(self): +        field_def = self._get_field_def('date') +        field_def['auto'] = 'update' +        checker = types.LesanaDate(field_def, {}) + +        today = datetime.date.today() +        past = datetime.date(2016, 12, 10) +        # we pass a date in the past +        v = checker.update(past) +        self.assertIsInstance(v, datetime.date) +        # and we want to get a date in the present +        self.assertEqual(v, today) + +        # with auto=False we want our old date instead +        field_def['auto'] = False +        checker = types.LesanaDate(field_def, {}) + +        v = checker.update(past) +        self.assertEqual(v, past) + +        # and the same should happen with auto=creation +        field_def['auto'] = 'creation' +        checker = types.LesanaDate(field_def, {}) + +        v = checker.update(past) +        self.assertEqual(v, past) +      def test_boolean(self):          checker = types.LesanaBoolean(self._get_field_def('boolean'), {}) @@ -254,6 +349,9 @@ class testTypes(unittest.TestCase):          v = checker.load(None)          self.assertEqual(v, None) +        v = checker.update(True) +        self.assertEqual(v, True) +      def test_file(self):          checker = types.LesanaFile(self._get_field_def('file'), {}) @@ -268,6 +366,9 @@ class testTypes(unittest.TestCase):          # TODO: check for invalid file paths +        v = checker.update("relative/path/to/file") +        self.assertEqual(v, "relative/path/to/file") +      def test_url(self):          checker = types.LesanaURL(self._get_field_def('url'), {}) @@ -282,6 +383,9 @@ class testTypes(unittest.TestCase):          # TODO: check for invalid URLs +        v = checker.update("http://example.org") +        self.assertEqual(v, "http://example.org") +      def test_yaml(self):          checker = types.LesanaYAML(self._get_field_def('yaml'), {}) @@ -298,6 +402,9 @@ class testTypes(unittest.TestCase):          v = checker.load(None)          self.assertEqual(v, None) +        v = checker.update(some_data) +        self.assertEqual(v, some_data) +      def test_list(self):          field_def = self._get_field_def('yaml')          # we use one type that is easy to check for correct validation @@ -318,6 +425,9 @@ class testTypes(unittest.TestCase):              with self.assertRaises(types.LesanaValueError):                  checker.load(d) +        v = checker.update(some_data) +        self.assertEqual(v, some_data) +      def test_list_unknown_subtype(self):          field_def = self._get_field_def('yaml')          # we use one type that is easy to check for correct validation | 
