Coverage for src/typedal/fields.py: 100%
85 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-02 16:17 +0200
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-02 16:17 +0200
1"""
2This file contains available Field types.
3"""
5import datetime as dt
6import decimal
7import typing
9from pydal.objects import Table
11from .core import TypeDAL, TypedField, TypedTable
13T = typing.TypeVar("T", bound=typing.Any)
16## general
19# def TypedField(
20# _type: typing.Type[T] | types.UnionType,
21# **kwargs: typing.Any,
22# ) -> T:
23# """
24# sneaky: its a function and not a class, because there's a return type.
25#
26# and the return type (T) is the input type in _type
27#
28# Example:
29# age: TypedField(int, default=18)
30# """
31# return typing.cast(T, TypedFieldType(_type, **kwargs))
34## specific
35def StringField(**kw: typing.Any) -> TypedField[str]:
36 """
37 Pydal type is string, Python type is str.
38 """
39 kw["type"] = "string"
40 return TypedField(str, **kw)
43String = StringField
46def TextField(**kw: typing.Any) -> TypedField[str]:
47 """
48 Pydal type is text, Python type is str.
49 """
50 kw["type"] = "text"
51 return TypedField(str, **kw)
54Text = TextField
57def BlobField(**kw: typing.Any) -> TypedField[bytes]:
58 """
59 Pydal type is blob, Python type is bytes.
60 """
61 kw["type"] = "blob"
62 return TypedField(bytes, **kw)
65Blob = BlobField
68def BooleanField(**kw: typing.Any) -> TypedField[bool]:
69 """
70 Pydal type is boolean, Python type is bool.
71 """
72 kw["type"] = "boolean"
73 return TypedField(bool, **kw)
76Boolean = BooleanField
79def IntegerField(**kw: typing.Any) -> TypedField[int]:
80 """
81 Pydal type is integer, Python type is int.
82 """
83 kw["type"] = "integer"
84 return TypedField(int, **kw)
87Integer = IntegerField
90def DoubleField(**kw: typing.Any) -> TypedField[float]:
91 """
92 Pydal type is double, Python type is float.
93 """
94 kw["type"] = "double"
95 return TypedField(float, **kw)
98Double = DoubleField
101def DecimalField(n: int, m: int, **kw: typing.Any) -> TypedField[decimal.Decimal]:
102 """
103 Pydal type is decimal, Python type is Decimal.
104 """
105 kw["type"] = f"decimal({n}, {m})"
106 return TypedField(decimal.Decimal, **kw)
109Decimal = DecimalField
112def DateField(**kw: typing.Any) -> TypedField[dt.date]:
113 """
114 Pydal type is date, Python type is datetime.date.
115 """
116 kw["type"] = "date"
117 return TypedField(dt.date, **kw)
120Date = DateField
123def TimeField(**kw: typing.Any) -> TypedField[dt.time]:
124 """
125 Pydal type is time, Python type is datetime.time.
126 """
127 kw["type"] = "time"
128 return TypedField(dt.time, **kw)
131Time = TimeField
134def DatetimeField(**kw: typing.Any) -> TypedField[dt.datetime]:
135 """
136 Pydal type is datetime, Python type is datetime.datetime.
137 """
138 kw["type"] = "datetime"
139 return TypedField(dt.datetime, **kw)
142Datetime = DatetimeField
145def PasswordField(**kw: typing.Any) -> TypedField[str]:
146 """
147 Pydal type is password, Python type is str.
148 """
149 kw["type"] = "password"
150 return TypedField(str, **kw)
153Password = PasswordField
156def UploadField(**kw: typing.Any) -> TypedField[str]:
157 """
158 Pydal type is upload, Python type is str.
159 """
160 kw["type"] = "upload"
161 return TypedField(str, **kw)
164Upload = UploadField
166T_subclass = typing.TypeVar("T_subclass", TypedTable, Table)
169def ReferenceField(
170 other_table: str | typing.Type[TypedTable] | TypedTable | Table | T_subclass, **kw: typing.Any
171) -> TypedField[int]:
172 """
173 Pydal type is reference, Python type is int (id).
174 """
175 if isinstance(other_table, str):
176 kw["type"] = f"reference {other_table}"
177 elif isinstance(other_table, Table):
178 # db.table
179 kw["type"] = f"reference {other_table._tablename}"
180 elif isinstance(other_table, type) and issubclass(other_table, TypedTable):
181 # SomeTable
182 snakename = TypeDAL.to_snake(other_table.__name__)
183 kw["type"] = f"reference {snakename}"
184 else:
185 raise ValueError(f"Don't know what to do with {type(other_table)}")
187 return TypedField(int, **kw)
190Reference = ReferenceField
193def ListStringField(**kw: typing.Any) -> TypedField[list[str]]:
194 """
195 Pydal type is list:string, Python type is list of str.
196 """
197 kw["type"] = "list:string"
198 return TypedField(list[str], **kw)
201ListString = ListStringField
204def ListIntegerField(**kw: typing.Any) -> TypedField[list[int]]:
205 """
206 Pydal type is list:integer, Python type is list of int.
207 """
208 kw["type"] = "list:integer"
209 return TypedField(list[int], **kw)
212ListInteger = ListIntegerField
215def ListReferenceField(other_table: str, **kw: typing.Any) -> TypedField[list[int]]:
216 """
217 Pydal type is list:reference, Python type is list of int (id).
218 """
219 kw["type"] = f"list:reference {other_table}"
220 return TypedField(list[int], **kw)
223ListReference = ListReferenceField
226def JSONField(**kw: typing.Any) -> TypedField[object]:
227 """
228 Pydal type is json, Python type is object (can be anything JSON-encodable).
229 """
230 kw["type"] = "json"
231 return TypedField(object, **kw)
234def BigintField(**kw: typing.Any) -> TypedField[int]:
235 """
236 Pydal type is bigint, Python type is int.
237 """
238 kw["type"] = "bigint"
239 return TypedField(int, **kw)
242Bigint = BigintField