1"""
2Type stubs for typed model fields.
3
4These stubs tell type checkers that field constructors return primitive types,
5enabling typed model definitions like:
6 name: str = types.TextField()
7
8At runtime, these are Field instances (descriptors), but type checkers see the primitives.
9
10The return type is conditional on allow_null:
11- allow_null=False (default) returns the primitive type (e.g., str)
12- allow_null=True returns the primitive type | None (e.g., str | None)
13"""
14
15from collections.abc import Callable, Sequence
16from datetime import date, datetime, time, timedelta
17from decimal import Decimal
18from json import JSONDecoder, JSONEncoder
19from typing import Any, Literal, overload
20from uuid import UUID
21from zoneinfo import ZoneInfo
22
23# Import manager types from runtime (will be Generic[T, QS] there)
24from plain.postgres.base import Model
25from plain.postgres.deletion import OnDelete
26from plain.postgres.fields.related_managers import (
27 ManyToManyManager,
28 ReverseForeignKeyManager,
29)
30from plain.postgres.query import QuerySet
31
32# String fields
33@overload
34def TextField(
35 *,
36 max_length: int | None = None,
37 required: bool = True,
38 allow_null: Literal[True],
39 default: Any = ...,
40 choices: Any = None,
41 validators: Sequence[Callable[..., Any]] = (),
42) -> str | None: ...
43@overload
44def TextField(
45 *,
46 max_length: int | None = None,
47 required: bool = True,
48 allow_null: Literal[False] = False,
49 default: Any = ...,
50 choices: Any = None,
51 validators: Sequence[Callable[..., Any]] = (),
52) -> str: ...
53@overload
54def EmailField(
55 *,
56 max_length: int | None = None,
57 required: bool = True,
58 allow_null: Literal[True],
59 default: Any = ...,
60 choices: Any = None,
61 validators: Sequence[Callable[..., Any]] = (),
62) -> str | None: ...
63@overload
64def EmailField(
65 *,
66 max_length: int | None = None,
67 required: bool = True,
68 allow_null: Literal[False] = False,
69 default: Any = ...,
70 choices: Any = None,
71 validators: Sequence[Callable[..., Any]] = (),
72) -> str: ...
73@overload
74def URLField(
75 *,
76 max_length: int | None = None,
77 required: bool = True,
78 allow_null: Literal[True],
79 default: Any = ...,
80 choices: Any = None,
81 validators: Sequence[Callable[..., Any]] = (),
82) -> str | None: ...
83@overload
84def URLField(
85 *,
86 max_length: int | None = None,
87 required: bool = True,
88 allow_null: Literal[False] = False,
89 default: Any = ...,
90 choices: Any = None,
91 validators: Sequence[Callable[..., Any]] = (),
92) -> str: ...
93
94# Integer fields
95@overload
96def IntegerField(
97 *,
98 required: bool = True,
99 allow_null: Literal[True],
100 default: Any = ...,
101 validators: Sequence[Callable[..., Any]] = (),
102) -> int | None: ...
103@overload
104def IntegerField(
105 *,
106 required: bool = True,
107 allow_null: Literal[False] = False,
108 default: Any = ...,
109 validators: Sequence[Callable[..., Any]] = (),
110) -> int: ...
111@overload
112def BigIntegerField(
113 *,
114 required: bool = True,
115 allow_null: Literal[True],
116 default: Any = ...,
117 validators: Sequence[Callable[..., Any]] = (),
118) -> int | None: ...
119@overload
120def BigIntegerField(
121 *,
122 required: bool = True,
123 allow_null: Literal[False] = False,
124 default: Any = ...,
125 validators: Sequence[Callable[..., Any]] = (),
126) -> int: ...
127@overload
128def SmallIntegerField(
129 *,
130 required: bool = True,
131 allow_null: Literal[True],
132 default: Any = ...,
133 validators: Sequence[Callable[..., Any]] = (),
134) -> int | None: ...
135@overload
136def SmallIntegerField(
137 *,
138 required: bool = True,
139 allow_null: Literal[False] = False,
140 default: Any = ...,
141 validators: Sequence[Callable[..., Any]] = (),
142) -> int: ...
143def PrimaryKeyField() -> int: ...
144
145# Numeric fields
146@overload
147def FloatField(
148 *,
149 required: bool = True,
150 allow_null: Literal[True],
151 default: Any = ...,
152 validators: Sequence[Callable[..., Any]] = (),
153) -> float | None: ...
154@overload
155def FloatField(
156 *,
157 required: bool = True,
158 allow_null: Literal[False] = False,
159 default: Any = ...,
160 validators: Sequence[Callable[..., Any]] = (),
161) -> float: ...
162@overload
163def DecimalField(
164 *,
165 max_digits: int | None = None,
166 decimal_places: int | None = None,
167 required: bool = True,
168 allow_null: Literal[True],
169 default: Any = ...,
170 validators: Sequence[Callable[..., Any]] = (),
171) -> Decimal | None: ...
172@overload
173def DecimalField(
174 *,
175 max_digits: int | None = None,
176 decimal_places: int | None = None,
177 required: bool = True,
178 allow_null: Literal[False] = False,
179 default: Any = ...,
180 validators: Sequence[Callable[..., Any]] = (),
181) -> Decimal: ...
182
183# Boolean field
184@overload
185def BooleanField(
186 *,
187 required: bool = True,
188 allow_null: Literal[True],
189 default: Any = ...,
190 validators: Sequence[Callable[..., Any]] = (),
191) -> bool | None: ...
192@overload
193def BooleanField(
194 *,
195 required: bool = True,
196 allow_null: Literal[False] = False,
197 default: Any = ...,
198 validators: Sequence[Callable[..., Any]] = (),
199) -> bool: ...
200
201# Date/time fields
202@overload
203def DateField(
204 *,
205 required: bool = True,
206 allow_null: Literal[True],
207 default: Any = ...,
208 validators: Sequence[Callable[..., Any]] = (),
209) -> date | None: ...
210@overload
211def DateField(
212 *,
213 required: bool = True,
214 allow_null: Literal[False] = False,
215 default: Any = ...,
216 validators: Sequence[Callable[..., Any]] = (),
217) -> date: ...
218@overload
219def DateTimeField(
220 *,
221 create_now: bool = False,
222 update_now: bool = False,
223 required: bool = True,
224 allow_null: Literal[True],
225 validators: Sequence[Callable[..., Any]] = (),
226) -> datetime | None: ...
227@overload
228def DateTimeField(
229 *,
230 create_now: bool = False,
231 update_now: bool = False,
232 required: bool = True,
233 allow_null: Literal[False] = False,
234 validators: Sequence[Callable[..., Any]] = (),
235) -> datetime: ...
236@overload
237def TimeField(
238 *,
239 required: bool = True,
240 allow_null: Literal[True],
241 default: Any = ...,
242 validators: Sequence[Callable[..., Any]] = (),
243) -> time | None: ...
244@overload
245def TimeField(
246 *,
247 required: bool = True,
248 allow_null: Literal[False] = False,
249 default: Any = ...,
250 validators: Sequence[Callable[..., Any]] = (),
251) -> time: ...
252@overload
253def DurationField(
254 *,
255 required: bool = True,
256 allow_null: Literal[True],
257 default: Any = ...,
258 validators: Sequence[Callable[..., Any]] = (),
259) -> timedelta | None: ...
260@overload
261def DurationField(
262 *,
263 required: bool = True,
264 allow_null: Literal[False] = False,
265 default: Any = ...,
266 validators: Sequence[Callable[..., Any]] = (),
267) -> timedelta: ...
268@overload
269def TimeZoneField(
270 *,
271 required: bool = True,
272 allow_null: Literal[True],
273 default: Any = ...,
274 validators: Sequence[Callable[..., Any]] = (),
275) -> ZoneInfo | None: ...
276@overload
277def TimeZoneField(
278 *,
279 required: bool = True,
280 allow_null: Literal[False] = False,
281 default: Any = ...,
282 validators: Sequence[Callable[..., Any]] = (),
283) -> ZoneInfo: ...
284
285# Other fields
286@overload
287def UUIDField(
288 *,
289 generate: bool = False,
290 required: bool = True,
291 allow_null: Literal[True],
292 validators: Sequence[Callable[..., Any]] = (),
293) -> UUID | None: ...
294@overload
295def UUIDField(
296 *,
297 generate: bool = False,
298 required: bool = True,
299 allow_null: Literal[False] = False,
300 validators: Sequence[Callable[..., Any]] = (),
301) -> UUID: ...
302@overload
303def RandomStringField(
304 *,
305 length: int,
306 required: bool = True,
307 allow_null: Literal[True],
308 validators: Sequence[Callable[..., Any]] = (),
309) -> str | None: ...
310@overload
311def RandomStringField(
312 *,
313 length: int,
314 required: bool = True,
315 allow_null: Literal[False] = False,
316 validators: Sequence[Callable[..., Any]] = (),
317) -> str: ...
318@overload
319def BinaryField(
320 *,
321 max_length: int | None = None,
322 required: bool = True,
323 allow_null: Literal[True],
324 validators: Sequence[Callable[..., Any]] = (),
325) -> bytes | None: ...
326@overload
327def BinaryField(
328 *,
329 max_length: int | None = None,
330 required: bool = True,
331 allow_null: Literal[False] = False,
332 validators: Sequence[Callable[..., Any]] = (),
333) -> bytes: ...
334@overload
335def GenericIPAddressField(
336 *,
337 protocol: str = "both",
338 unpack_ipv4: bool = False,
339 required: bool = True,
340 allow_null: Literal[True],
341 default: Any = ...,
342 validators: Sequence[Callable[..., Any]] = (),
343) -> str | None: ...
344@overload
345def GenericIPAddressField(
346 *,
347 protocol: str = "both",
348 unpack_ipv4: bool = False,
349 required: bool = True,
350 allow_null: Literal[False] = False,
351 default: Any = ...,
352 validators: Sequence[Callable[..., Any]] = (),
353) -> str: ...
354@overload
355def JSONField(
356 *,
357 encoder: type[JSONEncoder] | None = None,
358 decoder: type[JSONDecoder] | None = None,
359 required: bool = True,
360 allow_null: Literal[True],
361 default: Any = ...,
362 validators: Sequence[Callable[..., Any]] = (),
363) -> Any: ...
364@overload
365def JSONField(
366 *,
367 encoder: type[JSONEncoder] | None = None,
368 decoder: type[JSONDecoder] | None = None,
369 required: bool = True,
370 allow_null: Literal[False] = False,
371 default: Any = ...,
372 validators: Sequence[Callable[..., Any]] = (),
373) -> Any: ...
374
375# Encrypted fields
376@overload
377def EncryptedTextField(
378 *,
379 max_length: int | None = None,
380 required: bool = True,
381 allow_null: Literal[True],
382 validators: Sequence[Callable[..., Any]] = (),
383) -> str | None: ...
384@overload
385def EncryptedTextField(
386 *,
387 max_length: int | None = None,
388 required: bool = True,
389 allow_null: Literal[False] = False,
390 validators: Sequence[Callable[..., Any]] = (),
391) -> str: ...
392@overload
393def EncryptedJSONField(
394 *,
395 encoder: type[JSONEncoder] | None = None,
396 decoder: type[JSONDecoder] | None = None,
397 required: bool = True,
398 allow_null: Literal[True],
399 validators: Sequence[Callable[..., Any]] = (),
400) -> Any: ...
401@overload
402def EncryptedJSONField(
403 *,
404 encoder: type[JSONEncoder] | None = None,
405 decoder: type[JSONDecoder] | None = None,
406 required: bool = True,
407 allow_null: Literal[False] = False,
408 validators: Sequence[Callable[..., Any]] = (),
409) -> Any: ...
410
411# Related fields
412@overload
413def ForeignKeyField[T: Model](
414 to: type[T] | str,
415 on_delete: OnDelete,
416 *,
417 related_query_name: str | None = None,
418 limit_choices_to: Any = None,
419 db_constraint: bool = True,
420 required: bool = True,
421 allow_null: Literal[True],
422 validators: Sequence[Callable[..., Any]] = (),
423) -> T | None: ...
424@overload
425def ForeignKeyField[T: Model](
426 to: type[T] | str,
427 on_delete: OnDelete,
428 *,
429 related_query_name: str | None = None,
430 limit_choices_to: Any = None,
431 db_constraint: bool = True,
432 required: bool = True,
433 allow_null: Literal[False] = False,
434 validators: Sequence[Callable[..., Any]] = (),
435) -> T: ...
436def ManyToManyField[T: Model](
437 to: type[T] | str,
438 *,
439 through: Any,
440 through_fields: tuple[str, str] | None = None,
441 related_query_name: str | None = None,
442 limit_choices_to: Any = None,
443 symmetrical: bool | None = None,
444) -> ManyToManyManager[T]: ...
445
446# Reverse relation descriptors
447class ReverseForeignKey[T: Model, QS: QuerySet[Any] = QuerySet[Any]]:
448 """
449 Descriptor for the reverse side of a ForeignKeyField.
450
451 Type parameters:
452 _T: The related model type
453 _QS: The QuerySet type (use the model's custom QuerySet for proper method typing)
454
455 Example:
456 # With custom QuerySet for proper typing of custom methods like .enabled()
457 repos: ReverseForeignKey[Repo, RepoQuerySet] = ReverseForeignKey(to="Repo", field="organization")
458
459 # Usage: org.repos.query.enabled() # .enabled() is now recognized
460 """
461 def __init__(self, *, to: type[T] | str, field: str) -> None: ...
462 @overload
463 def __get__(self, instance: None, owner: type) -> ReverseForeignKey[T, QS]: ...
464 @overload
465 def __get__(
466 self, instance: Model, owner: type
467 ) -> ReverseForeignKeyManager[T, QS]: ...
468 def __get__(
469 self, instance: Model | None, owner: type
470 ) -> ReverseForeignKey[T, QS] | ReverseForeignKeyManager[T, QS]: ...
471
472class ReverseManyToMany[T: Model, QS: QuerySet[Any] = QuerySet[Any]]:
473 """
474 Descriptor for the reverse side of a ManyToManyField.
475
476 Type parameters:
477 _T: The related model type
478 _QS: The QuerySet type (use the model's custom QuerySet for proper method typing)
479 """
480 def __init__(self, *, to: type[T] | str, field: str) -> None: ...
481 @overload
482 def __get__(self, instance: None, owner: type) -> ReverseManyToMany[T, QS]: ...
483 @overload
484 def __get__(self, instance: Model, owner: type) -> ManyToManyManager[T, QS]: ...
485 def __get__(
486 self, instance: Model | None, owner: type
487 ) -> ReverseManyToMany[T, QS] | ManyToManyManager[T, QS]: ...
488
489# Export all types (should match types.py)
490__all__ = [
491 "BigIntegerField",
492 "BinaryField",
493 "BooleanField",
494 "DateField",
495 "DateTimeField",
496 "DecimalField",
497 "DurationField",
498 "EmailField",
499 "EncryptedJSONField",
500 "EncryptedTextField",
501 "FloatField",
502 "ForeignKeyField",
503 "GenericIPAddressField",
504 "IntegerField",
505 "JSONField",
506 "ManyToManyField",
507 "ManyToManyManager",
508 "PrimaryKeyField",
509 "RandomStringField",
510 "ReverseForeignKey",
511 "ReverseForeignKeyManager",
512 "ReverseManyToMany",
513 "SmallIntegerField",
514 "TextField",
515 "TimeField",
516 "TimeZoneField",
517 "URLField",
518 "UUIDField",
519]