A parser inspired by the django orm.
building tests
15 files changed, +73 -3
+6-2main.py
| @@ -4,14 +4,18 @@ import parsers | ||
| 4 | 4 | class Test(parsers.Parser): |
| 5 | 5 | a = parsers.BooleanField() |
| 6 | 6 | b = parsers.HourMinuteIntField() |
| 7 | + c = parsers.Field() | |
| 8 | + | |
| 9 | + class Meta: | |
| 10 | + unique_together = ['a', 'b'] | |
| 7 | 11 | |
| 8 | 12 | def __str__(self): |
| 9 | 13 | return f'{self.id} {self.a}' |
| 10 | 14 | |
| 11 | 15 | |
| 12 | -t1 = Test(a='23', b='02:32') | |
| 16 | +t1 = Test(a='23', b='02:32', c='b') | |
| 13 | 17 | t1.save() |
| 14 | -t2 = Test(a='', b='2342') | |
| 18 | +t2 = Test(a='', b='2342', c='a') | |
| 15 | 19 | t2.save() |
| 16 | 20 | for obj in Test.objects.all(): |
| 17 | 21 | pass |
+1-0parsers/__init__.py
| @@ -1,2 +1,3 @@ | ||
| 1 | 1 | from .parser import Parser |
| 2 | 2 | from .fields import * |
| 3 | +from .exceptions import * |
+0-0parsers/__pycache__/__init__.cpython-310.pyc
Binary file changed.
+0-0parsers/__pycache__/exceptions.cpython-310.pyc
Binary file changed.
+0-0parsers/__pycache__/fields.cpython-310.pyc
Binary file changed.
+0-0parsers/__pycache__/manager.cpython-310.pyc
Binary file changed.
+0-0parsers/__pycache__/parser.cpython-310.pyc
Binary file changed.
+0-0parsers/__pycache__/translators.cpython-310.pyc
Binary file changed.
+12-0parsers/exceptions.py
| @@ -16,3 +16,15 @@ class ExtraFieldsParseError(Exception): | ||
| 16 | 16 | class CreateWithIdParseError(Exception): |
| 17 | 17 | def __init__(self, cls): |
| 18 | 18 | super().__init__(f'{cls} cannot use id on creation.') |
| 19 | + | |
| 20 | + | |
| 21 | +class UniqueFieldParseError(Exception): | |
| 22 | + def __init__(self, cls, field, value): | |
| 23 | + super().__init__( | |
| 24 | + f'{cls} requires {field} to be unique. Error on value {value}') | |
| 25 | + | |
| 26 | + | |
| 27 | +class UniqueTogetherParseError(Exception): | |
| 28 | + def __init__(self, cls, fields, values): | |
| 29 | + super().__init__( | |
| 30 | + f'{cls} requires the fields {fields} to be unique together. Error on values {values}') |
+1-1parsers/fields.py
| @@ -8,7 +8,7 @@ def default_function(x): | ||
| 8 | 8 | class Field: |
| 9 | 9 | translator = default_function |
| 10 | 10 | |
| 11 | - def __init__(self, translator=None, unique=True): | |
| 11 | + def __init__(self, translator=None, unique=False): | |
| 12 | 12 | if translator: |
| 13 | 13 | self.translator = translator |
| 14 | 14 | self.unique = unique |
+20-0parsers/manager.py
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | from .exceptions import * |
| 2 | +from .fields import Field | |
| 2 | 3 | |
| 3 | 4 | |
| 4 | 5 | class Manager: |
| @@ -32,3 +33,22 @@ class Manager: | ||
| 32 | 33 | if obj == newobj: |
| 33 | 34 | return True |
| 34 | 35 | return False |
| 36 | + | |
| 37 | + def raise_unique_constraints(self, **kwargs): | |
| 38 | + o2 = self.cls(**kwargs) | |
| 39 | + unique_fields = [key for key, val in o2.field_items() if val.unique] | |
| 40 | + unique_together = o2.Meta.unique_together | |
| 41 | + for o in self.objects: | |
| 42 | + for key in unique_fields: | |
| 43 | + if o[key] == o2[key]: | |
| 44 | + raise UniqueFieldParseError(self.cls, key, o[key]) | |
| 45 | + unique_together_violation = True | |
| 46 | + vals = [] | |
| 47 | + for key in unique_together: | |
| 48 | + if o[key] != o2[key]: | |
| 49 | + unique_together_violation = False | |
| 50 | + break | |
| 51 | + else: | |
| 52 | + vals.append(o[key]) | |
| 53 | + if unique_together_violation: | |
| 54 | + raise UniqueTogetherParseError(self.cls, unique_together, vals) |
+1-0parsers/parser.py
| @@ -26,6 +26,7 @@ class Parser: | ||
| 26 | 26 | setattr(self, name, field.convert(kwargs[name])) |
| 27 | 27 | |
| 28 | 28 | def save(self): |
| 29 | + self.objects.raise_unique_constraints() | |
| 29 | 30 | self.objects.append(self) |
| 30 | 31 | |
| 31 | 32 | def fields(self): |
+1-0tests/__init__.py
| @@ -0,0 +1 @@ | ||
| 1 | +from |
+30-0tests/test_exceptions.py
| @@ -0,0 +1,30 @@ | ||
| 1 | +import parsers | |
| 2 | +import unittest | |
| 3 | + | |
| 4 | + | |
| 5 | +class Test(parsers.Parser): | |
| 6 | + a = parsers.Field() | |
| 7 | + b = parsers.Field() | |
| 8 | + c = parsers.Field() | |
| 9 | + d = parsers.Field(unique=True) | |
| 10 | + | |
| 11 | + class Meta: | |
| 12 | + unique_together = ['a', 'b', 'c'] | |
| 13 | + | |
| 14 | + | |
| 15 | +def double_d(): | |
| 16 | + t1 = Test(a='a1', b='b1', c='c1', d='d') | |
| 17 | + t1.save() | |
| 18 | + t2 = Test(a='a2', b='b2', c='c2', d='d') | |
| 19 | + t2.save() | |
| 20 | + | |
| 21 | + | |
| 22 | +def raise_unique_together(): | |
| 23 | + t1 = Test(a='a', b='b', c='c', d='d1') | |
| 24 | + t2 = Test(a='a', b='b', c='c', d='d2') | |
| 25 | + | |
| 26 | + | |
| 27 | +class TestExceptions(unittest.TestCase): | |
| 28 | + | |
| 29 | + def test_unique(self): | |
| 30 | + self.assertRaises(parsers.UniqueFieldParseError, double_d) |
+1-0tests/test_fields.py
| @@ -0,0 +1 @@ | ||
| 1 | +import uni |