irongit

A parser inspired by the django orm.

field tests work

huncholanehuncholaneauthored
parent bfb8ddecommit 53d949ebe814a6e76aae8537a0a4e2620a2f1ee3Browse files

7 files changed, +118 -13

+1-1parsers/fields.py
@@ -1,7 +1,7 @@
11 from . import translators
22
33
4-def default_function(x):
4+def default_function(cls, x):
55 return x
66
77
+7-6parsers/manager.py
@@ -34,18 +34,19 @@ class Manager:
3434 return True
3535 return False
3636
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]
37+ def raise_unique_constraints(self, o2):
38+ unique_fields = o2.unique_fields
4039 unique_together = o2.Meta.unique_together
4140 for o in self.objects:
4241 for key in unique_fields:
43- if o[key] == o2[key]:
44- raise UniqueFieldParseError(self.cls, key, o[key])
42+ oval = o.__dict__[key]
43+ o2val = o2.__dict__[key]
44+ if o.__dict__[key] == o2.__dict__[key]:
45+ raise UniqueFieldParseError(self.cls, key, o.__dict__[key])
4546 unique_together_violation = True
4647 vals = []
4748 for key in unique_together:
48- if o[key] != o2[key]:
49+ if o.__dict__[key] != o2.__dict__[key]:
4950 unique_together_violation = False
5051 break
5152 else:
+3-1parsers/parser.py
@@ -11,6 +11,8 @@ class Parser:
1111 unique_together = []
1212
1313 def __init__(self, **kwargs):
14+ self.unique_fields = [key for key,
15+ val in self.field_items() if val.unique]
1416 self.objects.set_cls(type(self))
1517 missing_fields = set(self.fields())-set(kwargs)
1618 if 'id' not in missing_fields:
@@ -26,7 +28,7 @@ class Parser:
2628 setattr(self, name, field.convert(kwargs[name]))
2729
2830 def save(self):
29- self.objects.raise_unique_constraints()
31+ self.objects.raise_unique_constraints(self)
3032 self.objects.append(self)
3133
3234 def fields(self):
+6-1parsers/translators.py
@@ -7,6 +7,9 @@ import datetime as dt
77
88 def split_hour_minute(str):
99 """Extracts hours and minutes into separate strings"""
10+ if ':' in str and len(str) < 5 or len(str) < 4:
11+ raise ValueError(
12+ f'Hours and minutes must have at least 4 characters without : and 5 with :.')
1013 str = ''.join(re.findall(r'\d+', str))
1114 return str[:-2], str[-2:]
1215
@@ -25,7 +28,9 @@ def hour_minute_to_int(cls, str):
2528
2629 def phone(cls, str):
2730 """Converts numbers to a phone number with country code readiness"""
28- nums = ''.join(re.findall(r'\d+'), str)
31+ nums = ''.join(re.findall(r'\d+', str))
32+ if len(nums) < 4:
33+ raise TypeError(f'Impossible phone number {str}.')
2934 if nums[:3] == '011':
3035 return '+'+nums[3:]
3136 else:
+0-1tests/__init__.py
@@ -1 +0,0 @@
1-from
+3-2tests/test_exceptions.py
@@ -12,7 +12,7 @@ class Test(parsers.Parser):
1212 unique_together = ['a', 'b', 'c']
1313
1414
15-def double_d():
15+def raise_unique_error():
1616 t1 = Test(a='a1', b='b1', c='c1', d='d')
1717 t1.save()
1818 t2 = Test(a='a2', b='b2', c='c2', d='d')
@@ -27,4 +27,5 @@ def raise_unique_together():
2727 class TestExceptions(unittest.TestCase):
2828
2929 def test_unique(self):
30- self.assertRaises(parsers.UniqueFieldParseError, double_d)
30+ self.assertRaises(
31+ parsers.exceptions.UniqueFieldParseError, raise_unique_error)
+98-1tests/test_fields.py
@@ -1 +1,98 @@
1-import uni
1+import unittest
2+import parsers
3+import datetime as dt
4+
5+
6+class FieldParser(parsers.Parser):
7+ a = parsers.Field()
8+
9+
10+class HourMinuteIntParser(parsers.Parser):
11+ a = parsers.HourMinuteIntField()
12+
13+
14+class HourMinuteDeltaParser(parsers.Parser):
15+ a = parsers.HourMinuteDeltaField()
16+
17+
18+class PhoneParser(parsers.Parser):
19+ a = parsers.PhoneField()
20+
21+
22+class StrParser(parsers.Parser):
23+ a = parsers.StrField()
24+
25+
26+class IntParser(parsers.Parser):
27+ a = parsers.IntField()
28+
29+
30+class FloatParser(parsers.Parser):
31+ a = parsers.FloatField()
32+
33+
34+class BoolParser(parsers.Parser):
35+ a = parsers.BooleanField()
36+
37+
38+class TestField(unittest.TestCase):
39+ cls = FieldParser
40+ good_vals = ['a']
41+ bad_vals = []
42+ type = str
43+
44+ def test_good_vals(self):
45+ for val in self.good_vals:
46+ t = self.cls(a=val)
47+ self.assertEqual(type(t.a), self.type)
48+
49+ def test_bad_vals(self):
50+ def func():
51+ self.cls(a=val)
52+ for val in self.bad_vals:
53+ self.assertRaises(Exception, func)
54+
55+
56+class TestHourMinuteDeltaField(TestField):
57+ cls = HourMinuteDeltaParser
58+ good_vals = ['23421', '23:32', '234:21', '2323'].copy()
59+ bad_vals = ['fds', '234', '3:3'].copy()
60+ type = dt.timedelta
61+
62+
63+class TestHourMinuteIntField(TestHourMinuteDeltaField):
64+ cls = HourMinuteIntParser
65+ type = int
66+
67+
68+class TestPhoneField(TestField):
69+ cls = PhoneParser
70+ good_vals = ['32452345', '232-234-234-']
71+ bad_vals = ['asedrfaw']
72+
73+ def test_foreign(self):
74+ t = self.cls(a='011-123-456-789')
75+ self.assertEqual(t.a, '+123456789')
76+
77+ def test_us(self):
78+ t = self.cls(a='123456789')
79+ self.assertEqual(t.a, '+1123456789')
80+
81+
82+class TestStrField(TestField):
83+ cls = StrParser
84+ good_vals = ['asdf']
85+
86+
87+class TestIntField(TestField):
88+ cls = IntParser
89+ good_vals = ['2314', '32']
90+ bad_vals = ['adsf']
91+ type = int
92+
93+
94+class TestFloatField(TestField):
95+ cls = FloatParser
96+ good_vals = ['223.23', '23']
97+ bad_vals = ['asdf']
98+ type = float