This repository has been archived by the owner on Aug 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
fields.py
64 lines (49 loc) · 1.89 KB
/
fields.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import decimal
import typing
import typesystem
from sqlalchemy import orm
from typesystem.unique import Uniqueness
class Decimal(typesystem.Decimal):
def serialize(self, obj: typing.Any) -> typing.Any:
return decimal.Decimal(obj) if obj is not None else None
class Email(typesystem.String):
""" A field that validates an email """
custom_errors = {"pattern": "Must be a valid email."}
def __init__(self, **kwargs: typing.Any) -> None:
kwargs.setdefault(
"pattern", r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"
)
kwargs.setdefault("format", "email")
self.errors.update(self.custom_errors)
super().__init__(**kwargs)
class Float(typesystem.Float):
def serialize(self, obj: typing.Any) -> typing.Any:
return float(obj) if obj is not None else None
class ModelChoice(typesystem.Field):
errors = {
"null": "May not be null.",
"required": "This field is required.",
"choice": "Not a valid choice.",
}
queryset: orm.Query
def __init__(self, *, queryset: orm.Query, **kwargs: typing.Any) -> None:
super().__init__(**kwargs)
self.queryset = queryset
@property
def choices(self):
return [(o.id, str(o)) for o in self.queryset]
def validate(self, value: typing.Any, *, strict: bool = False) -> typing.Any:
if value is None and self.allow_null:
return None
elif value == "" and self.allow_null:
return None
elif value == "":
raise self.validation_error("required")
elif value is None:
raise self.validation_error("null")
# just make sure the record still exists in the db
try:
instance = self.queryset.filter_by(id=value).one()
return instance.id
except orm.exc.NoResultFound:
raise self.validation_error("choice")