summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2021-02-09 09:57:45 +0100
committerElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2021-02-09 09:57:45 +0100
commit98f51779ca658d448ee62384d1e7348b77f2d5c1 (patch)
tree3551e3a883e9eea327a71ad02695c07bed7bf318
parent9283f3a34528a62c4e6a0434dc9bace2498bc800 (diff)
Add the ability for field types to update themselves
-rw-r--r--lesana/types.py40
-rw-r--r--tests/test_types.py110
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