A parser inspired by the django orm.
null and default work
4 files changed, +43 -10
+9-1parsers/fields.py
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | from . import translators |
| 2 | +import datetime as dt | |
| 2 | 3 | |
| 3 | 4 | |
| 4 | 5 | def default_function(cls, x): |
| @@ -7,21 +8,26 @@ def default_function(cls, x): | ||
| 7 | 8 | |
| 8 | 9 | class Field: |
| 9 | 10 | translator = default_function |
| 11 | + type = str | |
| 10 | 12 | |
| 11 | - def __init__(self, translator=None, unique=False): | |
| 13 | + def __init__(self, translator=None, unique=False, default=None, null=False): | |
| 12 | 14 | if translator: |
| 13 | 15 | self.translator = translator |
| 14 | 16 | self.unique = unique |
| 17 | + self.default = default | |
| 18 | + self.null = null | |
| 15 | 19 | |
| 16 | 20 | def convert(self, val): |
| 17 | 21 | return self.translator(val) |
| 18 | 22 | |
| 19 | 23 | |
| 20 | 24 | class HourMinuteDeltaField(Field): |
| 25 | + type = dt.timedelta | |
| 21 | 26 | translator = translators.hour_minute_to_delta |
| 22 | 27 | |
| 23 | 28 | |
| 24 | 29 | class HourMinuteIntField(Field): |
| 30 | + type = int | |
| 25 | 31 | translator = translators.hour_minute_to_int |
| 26 | 32 | |
| 27 | 33 | |
| @@ -34,10 +40,12 @@ class StrField(Field): | ||
| 34 | 40 | |
| 35 | 41 | |
| 36 | 42 | class IntField(Field): |
| 43 | + type = int | |
| 37 | 44 | translator = int |
| 38 | 45 | |
| 39 | 46 | |
| 40 | 47 | class FloatField(Field): |
| 48 | + type = float | |
| 41 | 49 | translator = float |
| 42 | 50 | |
| 43 | 51 |
+17-3parsers/parser.py
| @@ -11,8 +11,18 @@ class Parser: | ||
| 11 | 11 | unique_together = [] |
| 12 | 12 | |
| 13 | 13 | def __init__(self, **kwargs): |
| 14 | - self.unique_fields = [key for key, | |
| 15 | - val in self.field_items() if val.unique] | |
| 14 | + self.unique_fields = [] | |
| 15 | + for key, val in self.field_items(): | |
| 16 | + if val.unique: | |
| 17 | + self.unique_fields.append(key) | |
| 18 | + if val.null: | |
| 19 | + kwargs[key] = kwargs.get(key) | |
| 20 | + if val.default: | |
| 21 | + if type(val.default) != val.type: | |
| 22 | + raise TypeError( | |
| 23 | + f'{key} default should be of type {val.type}') | |
| 24 | + if not kwargs.get(key): | |
| 25 | + kwargs[key] = val.default | |
| 16 | 26 | self.objects.set_cls(type(self)) |
| 17 | 27 | missing_fields = set(self.fields())-set(kwargs) |
| 18 | 28 | if 'id' not in missing_fields: |
| @@ -25,7 +35,11 @@ class Parser: | ||
| 25 | 35 | raise ExtraFieldsParseError(self, extra_fields) |
| 26 | 36 | kwargs['id'] = self.objects.count() |
| 27 | 37 | for name, field in self.field_items(): |
| 28 | - setattr(self, name, field.convert(kwargs[name])) | |
| 38 | + val = kwargs[name] | |
| 39 | + if type(val) == str: | |
| 40 | + setattr(self, name, field.convert(val)) | |
| 41 | + else: | |
| 42 | + setattr(self, name, val) | |
| 29 | 43 | |
| 30 | 44 | def save(self): |
| 31 | 45 | self.objects.raise_unique_constraints(self) |
+0-0tests/__init__.py
No content changes (mode or rename only).
+17-6tests/test_create.py
| @@ -2,15 +2,26 @@ import parsers | ||
| 2 | 2 | import unittest |
| 3 | 3 | |
| 4 | 4 | |
| 5 | -class Test(parsers.Parser): | |
| 6 | - a = parsers.Field() | |
| 7 | - | |
| 8 | - | |
| 9 | 5 | class TestCreate(unittest.TestCase): |
| 10 | 6 | |
| 11 | 7 | def test_create(self): |
| 12 | - t = Test('a') | |
| 8 | + class Test(parsers.Parser): | |
| 9 | + a = parsers.Field() | |
| 10 | + t = Test(a='a') | |
| 13 | 11 | self.assertEqual(t.a, 'a') |
| 14 | 12 | |
| 15 | 13 | def test_nullable(self): |
| 16 | - pass | |
| 14 | + class Test(parsers.Parser): | |
| 15 | + a = parsers.Field(null=True) | |
| 16 | + b = parsers.Field() | |
| 17 | + t = Test(b='32') | |
| 18 | + self.assertEqual(t.a, None) | |
| 19 | + self.assertEqual(t.b, '32') | |
| 20 | + | |
| 21 | + def test_default(self): | |
| 22 | + class Test(parsers.Parser): | |
| 23 | + a = parsers.Field(default='sdff') | |
| 24 | + b = parsers.Field() | |
| 25 | + t = Test(b='f') | |
| 26 | + self.assertEqual(t.a, 'sdff') | |
| 27 | + self.assertEqual(t.b, 'f') |