Coverage for src/typedal/fields.py: 100%
91 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-05 16:09 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-05 16:09 +0200
1"""
2This file contains available Field types.
3"""
5import datetime as dt
6import decimal
7import types
8import typing
10from pydal.objects import Table
12from .core import TypeDAL, TypedFieldType, TypedTable
14T = typing.TypeVar("T", bound=typing.Type[typing.Any])
17## general
20def TypedField(
21 _type: T | types.UnionType,
22 **kwargs: typing.Any,
23) -> T:
24 """
25 sneaky: its a function and not a class, because there's a return type.
27 and the return type (T) is the input type in _type
29 Example:
30 age: TypedField(int, default=18)
31 """
32 return TypedFieldType(_type, **kwargs)
35TYPE_STR = typing.Type[str]
36TYPE_INT = typing.Type[int]
37TYPE_LIST_OF_INT = typing.Type[list[int]]
40## specific
41def StringField(**kw: typing.Any) -> TYPE_STR:
42 """
43 Pydal type is string, Python type is str.
44 """
45 kw["type"] = "string"
46 return TypedField(str, **kw)
49String = StringField
52def TextField(**kw: typing.Any) -> TYPE_STR:
53 """
54 Pydal type is text, Python type is str.
55 """
56 kw["type"] = "text"
57 return TypedField(str, **kw)
60Text = TextField
63def BlobField(**kw: typing.Any) -> typing.Type[bytes]:
64 """
65 Pydal type is blob, Python type is bytes.
66 """
67 kw["type"] = "blob"
68 return TypedField(bytes, **kw)
71Blob = BlobField
74def BooleanField(**kw: typing.Any) -> typing.Type[bool]:
75 """
76 Pydal type is boolean, Python type is bool.
77 """
78 kw["type"] = "boolean"
79 return TypedField(bool, **kw)
82Boolean = BooleanField
85def IntegerField(**kw: typing.Any) -> typing.Type[int]:
86 """
87 Pydal type is integer, Python type is int.
88 """
89 kw["type"] = "integer"
90 return TypedField(int, **kw)
93Integer = IntegerField
96def DoubleField(**kw: typing.Any) -> typing.Type[float]:
97 """
98 Pydal type is double, Python type is float.
99 """
100 kw["type"] = "double"
101 return TypedField(float, **kw)
104Double = DoubleField
107def DecimalField(n: int, m: int, **kw: typing.Any) -> typing.Type[decimal.Decimal]:
108 """
109 Pydal type is decimal, Python type is Decimal.
110 """
111 kw["type"] = f"decimal({n}, {m})"
112 return TypedField(decimal.Decimal, **kw)
115Decimal = DecimalField
118def DateField(**kw: typing.Any) -> typing.Type[dt.date]:
119 """
120 Pydal type is date, Python type is datetime.date.
121 """
122 kw["type"] = "date"
123 return TypedField(dt.date, **kw)
126Date = DateField
129def TimeField(**kw: typing.Any) -> typing.Type[dt.time]:
130 """
131 Pydal type is time, Python type is datetime.time.
132 """
133 kw["type"] = "time"
134 return TypedField(dt.time, **kw)
137Time = TimeField
140def DatetimeField(**kw: typing.Any) -> typing.Type[dt.datetime]:
141 """
142 Pydal type is datetime, Python type is datetime.datetime.
143 """
144 kw["type"] = "datetime"
145 return TypedField(dt.datetime, **kw)
148Datetime = DatetimeField
151def PasswordField(**kw: typing.Any) -> TYPE_STR:
152 """
153 Pydal type is password, Python type is str.
154 """
155 kw["type"] = "password"
156 return TypedField(str, **kw)
159Password = PasswordField
162def UploadField(**kw: typing.Any) -> TYPE_STR:
163 """
164 Pydal type is upload, Python type is str.
165 """
166 kw["type"] = "upload"
167 return TypedField(str, **kw)
170Upload = UploadField
172T_subclass = typing.TypeVar("T_subclass", TypedTable, Table)
175def ReferenceField(other_table: str | TypedTable | Table | T_subclass, **kw: typing.Any) -> TYPE_INT:
176 """
177 Pydal type is reference, Python type is int (id).
178 """
179 if isinstance(other_table, str):
180 kw["type"] = f"reference {other_table}"
181 elif isinstance(other_table, Table):
182 # db.table
183 kw["type"] = f"reference {other_table._tablename}"
184 elif issubclass(type(other_table), type) and issubclass(other_table, TypedTable):
185 # SomeTable
186 snakename = TypeDAL._to_snake(other_table.__name__)
187 kw["type"] = f"reference {snakename}"
188 else:
189 raise ValueError(f"Don't know what to do with {type(other_table)}")
191 return TypedField(int, **kw)
194Reference = ReferenceField
197def ListStringField(**kw: typing.Any) -> typing.Type[list[str]]:
198 """
199 Pydal type is list:string, Python type is list of str.
200 """
201 kw["type"] = "list:string"
202 return TypedField(list[str], **kw)
205ListString = ListStringField
208def ListIntegerField(**kw: typing.Any) -> TYPE_LIST_OF_INT:
209 """
210 Pydal type is list:integer, Python type is list of int.
211 """
212 kw["type"] = "list:integer"
213 return TypedField(list[int], **kw)
216ListInteger = ListIntegerField
219def ListReferenceField(other_table: str, **kw: typing.Any) -> TYPE_LIST_OF_INT:
220 """
221 Pydal type is list:reference, Python type is list of int (id).
222 """
223 kw["type"] = f"list:reference {other_table}"
224 return TypedField(list[int], **kw)
227ListReference = ListReferenceField
230def JSONField(**kw: typing.Any) -> typing.Type[object]:
231 """
232 Pydal type is json, Python type is object (can be anything JSON-encodable).
233 """
234 kw["type"] = "json"
235 return TypedField(object, **kw)
238def BigintField(**kw: typing.Any) -> TYPE_INT:
239 """
240 Pydal type is bigint, Python type is int.
241 """
242 kw["type"] = "bigint"
243 return TypedField(int, **kw)
246Bigint = BigintField