v0.163.0
  1"""
  2Type stubs for typed model fields.
  3
  4These stubs tell type checkers that each field constructor returns the
  5typed *descriptor* (`XField[T]`), not the primitive `T`. Combined with
  6`Field.__get__`'s overloads, this gives you:
  7
  8    class User(postgres.Model):
  9        email = types.EmailField()
 10        age = types.IntegerField(allow_null=True)
 11
 12    User.email   # EmailField[str]        — typed reference
 13    user.email   # str                    — the loaded value
 14    User.age     # IntegerField[int | None]
 15    user.age     # int | None
 16
 17The return type is parameterized by nullability:
 18- allow_null=False (default) → XField[T]
 19- allow_null=True            → XField[T | None]
 20"""
 21
 22from collections.abc import Callable, Sequence
 23from datetime import date, datetime, time, timedelta
 24from decimal import Decimal
 25from typing import Any, Literal, overload
 26from uuid import UUID
 27from zoneinfo import ZoneInfo
 28
 29from plain.postgres.base import Model
 30from plain.postgres.deletion import OnDelete
 31from plain.postgres.fields.binary import BinaryField as _BinaryField
 32from plain.postgres.fields.boolean import BooleanField as _BooleanField
 33from plain.postgres.fields.duration import DurationField as _DurationField
 34from plain.postgres.fields.encrypted import EncryptedTextField as _EncryptedTextField
 35from plain.postgres.fields.network import (
 36    GenericIPAddressField as _GenericIPAddressField,
 37)
 38from plain.postgres.fields.numeric import BigIntegerField as _BigIntegerField
 39from plain.postgres.fields.numeric import DecimalField as _DecimalField
 40from plain.postgres.fields.numeric import FloatField as _FloatField
 41from plain.postgres.fields.numeric import IntegerField as _IntegerField
 42from plain.postgres.fields.numeric import SmallIntegerField as _SmallIntegerField
 43from plain.postgres.fields.primary_key import PrimaryKeyField as _PrimaryKeyField
 44from plain.postgres.fields.related_managers import (
 45    ManyToManyManager,
 46    ReverseForeignKeyManager,
 47)
 48from plain.postgres.fields.temporal import DateField as _DateField
 49from plain.postgres.fields.temporal import DateTimeField as _DateTimeField
 50from plain.postgres.fields.temporal import TimeField as _TimeField
 51from plain.postgres.fields.text import EmailField as _EmailField
 52from plain.postgres.fields.text import RandomStringField as _RandomStringField
 53from plain.postgres.fields.text import TextField as _TextField
 54from plain.postgres.fields.text import URLField as _URLField
 55from plain.postgres.fields.timezones import TimeZoneField as _TimeZoneField
 56from plain.postgres.fields.uuid import UUIDField as _UUIDField
 57from plain.postgres.query import QuerySet
 58
 59# String fields
 60@overload
 61def TextField(
 62    *,
 63    max_length: int | None = None,
 64    required: bool = True,
 65    allow_null: Literal[True],
 66    default: Any = ...,
 67    choices: Any = None,
 68    validators: Sequence[Callable[..., Any]] = (),
 69) -> _TextField[str | None]: ...
 70@overload
 71def TextField(
 72    *,
 73    max_length: int | None = None,
 74    required: bool = True,
 75    allow_null: Literal[False] = False,
 76    default: Any = ...,
 77    choices: Any = None,
 78    validators: Sequence[Callable[..., Any]] = (),
 79) -> _TextField[str]: ...
 80@overload
 81def EmailField(
 82    *,
 83    max_length: int | None = None,
 84    required: bool = True,
 85    allow_null: Literal[True],
 86    default: Any = ...,
 87    choices: Any = None,
 88    validators: Sequence[Callable[..., Any]] = (),
 89) -> _EmailField[str | None]: ...
 90@overload
 91def EmailField(
 92    *,
 93    max_length: int | None = None,
 94    required: bool = True,
 95    allow_null: Literal[False] = False,
 96    default: Any = ...,
 97    choices: Any = None,
 98    validators: Sequence[Callable[..., Any]] = (),
 99) -> _EmailField[str]: ...
100@overload
101def URLField(
102    *,
103    max_length: int | None = None,
104    required: bool = True,
105    allow_null: Literal[True],
106    default: Any = ...,
107    choices: Any = None,
108    validators: Sequence[Callable[..., Any]] = (),
109) -> _URLField[str | None]: ...
110@overload
111def URLField(
112    *,
113    max_length: int | None = None,
114    required: bool = True,
115    allow_null: Literal[False] = False,
116    default: Any = ...,
117    choices: Any = None,
118    validators: Sequence[Callable[..., Any]] = (),
119) -> _URLField[str]: ...
120
121# Integer fields
122@overload
123def IntegerField(
124    *,
125    required: bool = True,
126    allow_null: Literal[True],
127    default: Any = ...,
128    validators: Sequence[Callable[..., Any]] = (),
129) -> _IntegerField[int | None]: ...
130@overload
131def IntegerField(
132    *,
133    required: bool = True,
134    allow_null: Literal[False] = False,
135    default: Any = ...,
136    validators: Sequence[Callable[..., Any]] = (),
137) -> _IntegerField[int]: ...
138@overload
139def BigIntegerField(
140    *,
141    required: bool = True,
142    allow_null: Literal[True],
143    default: Any = ...,
144    validators: Sequence[Callable[..., Any]] = (),
145) -> _BigIntegerField[int | None]: ...
146@overload
147def BigIntegerField(
148    *,
149    required: bool = True,
150    allow_null: Literal[False] = False,
151    default: Any = ...,
152    validators: Sequence[Callable[..., Any]] = (),
153) -> _BigIntegerField[int]: ...
154@overload
155def SmallIntegerField(
156    *,
157    required: bool = True,
158    allow_null: Literal[True],
159    default: Any = ...,
160    validators: Sequence[Callable[..., Any]] = (),
161) -> _SmallIntegerField[int | None]: ...
162@overload
163def SmallIntegerField(
164    *,
165    required: bool = True,
166    allow_null: Literal[False] = False,
167    default: Any = ...,
168    validators: Sequence[Callable[..., Any]] = (),
169) -> _SmallIntegerField[int]: ...
170def PrimaryKeyField() -> _PrimaryKeyField: ...
171
172# Numeric fields
173@overload
174def FloatField(
175    *,
176    required: bool = True,
177    allow_null: Literal[True],
178    default: Any = ...,
179    validators: Sequence[Callable[..., Any]] = (),
180) -> _FloatField[float | None]: ...
181@overload
182def FloatField(
183    *,
184    required: bool = True,
185    allow_null: Literal[False] = False,
186    default: Any = ...,
187    validators: Sequence[Callable[..., Any]] = (),
188) -> _FloatField[float]: ...
189@overload
190def DecimalField(
191    *,
192    max_digits: int | None = None,
193    decimal_places: int | None = None,
194    required: bool = True,
195    allow_null: Literal[True],
196    default: Any = ...,
197    validators: Sequence[Callable[..., Any]] = (),
198) -> _DecimalField[Decimal | None]: ...
199@overload
200def DecimalField(
201    *,
202    max_digits: int | None = None,
203    decimal_places: int | None = None,
204    required: bool = True,
205    allow_null: Literal[False] = False,
206    default: Any = ...,
207    validators: Sequence[Callable[..., Any]] = (),
208) -> _DecimalField[Decimal]: ...
209
210# Boolean field
211@overload
212def BooleanField(
213    *,
214    required: bool = True,
215    allow_null: Literal[True],
216    default: Any = ...,
217    validators: Sequence[Callable[..., Any]] = (),
218) -> _BooleanField[bool | None]: ...
219@overload
220def BooleanField(
221    *,
222    required: bool = True,
223    allow_null: Literal[False] = False,
224    default: Any = ...,
225    validators: Sequence[Callable[..., Any]] = (),
226) -> _BooleanField[bool]: ...
227
228# Date/time fields
229@overload
230def DateField(
231    *,
232    required: bool = True,
233    allow_null: Literal[True],
234    default: Any = ...,
235    validators: Sequence[Callable[..., Any]] = (),
236) -> _DateField[date | None]: ...
237@overload
238def DateField(
239    *,
240    required: bool = True,
241    allow_null: Literal[False] = False,
242    default: Any = ...,
243    validators: Sequence[Callable[..., Any]] = (),
244) -> _DateField[date]: ...
245@overload
246def DateTimeField(
247    *,
248    create_now: bool = False,
249    update_now: bool = False,
250    required: bool = True,
251    allow_null: Literal[True],
252    validators: Sequence[Callable[..., Any]] = (),
253) -> _DateTimeField[datetime | None]: ...
254@overload
255def DateTimeField(
256    *,
257    create_now: bool = False,
258    update_now: bool = False,
259    required: bool = True,
260    allow_null: Literal[False] = False,
261    validators: Sequence[Callable[..., Any]] = (),
262) -> _DateTimeField[datetime]: ...
263@overload
264def TimeField(
265    *,
266    required: bool = True,
267    allow_null: Literal[True],
268    default: Any = ...,
269    validators: Sequence[Callable[..., Any]] = (),
270) -> _TimeField[time | None]: ...
271@overload
272def TimeField(
273    *,
274    required: bool = True,
275    allow_null: Literal[False] = False,
276    default: Any = ...,
277    validators: Sequence[Callable[..., Any]] = (),
278) -> _TimeField[time]: ...
279@overload
280def DurationField(
281    *,
282    required: bool = True,
283    allow_null: Literal[True],
284    default: Any = ...,
285    validators: Sequence[Callable[..., Any]] = (),
286) -> _DurationField[timedelta | None]: ...
287@overload
288def DurationField(
289    *,
290    required: bool = True,
291    allow_null: Literal[False] = False,
292    default: Any = ...,
293    validators: Sequence[Callable[..., Any]] = (),
294) -> _DurationField[timedelta]: ...
295@overload
296def TimeZoneField(
297    *,
298    required: bool = True,
299    allow_null: Literal[True],
300    default: Any = ...,
301    validators: Sequence[Callable[..., Any]] = (),
302) -> _TimeZoneField[ZoneInfo | None]: ...
303@overload
304def TimeZoneField(
305    *,
306    required: bool = True,
307    allow_null: Literal[False] = False,
308    default: Any = ...,
309    validators: Sequence[Callable[..., Any]] = (),
310) -> _TimeZoneField[ZoneInfo]: ...
311
312# Other fields
313@overload
314def UUIDField(
315    *,
316    generate: bool = False,
317    required: bool = True,
318    allow_null: Literal[True],
319    validators: Sequence[Callable[..., Any]] = (),
320) -> _UUIDField[UUID | None]: ...
321@overload
322def UUIDField(
323    *,
324    generate: bool = False,
325    required: bool = True,
326    allow_null: Literal[False] = False,
327    validators: Sequence[Callable[..., Any]] = (),
328) -> _UUIDField[UUID]: ...
329@overload
330def RandomStringField(
331    *,
332    length: int,
333    required: bool = True,
334    allow_null: Literal[True],
335    validators: Sequence[Callable[..., Any]] = (),
336) -> _RandomStringField[str | None]: ...
337@overload
338def RandomStringField(
339    *,
340    length: int,
341    required: bool = True,
342    allow_null: Literal[False] = False,
343    validators: Sequence[Callable[..., Any]] = (),
344) -> _RandomStringField[str]: ...
345@overload
346def BinaryField(
347    *,
348    max_length: int | None = None,
349    required: bool = True,
350    allow_null: Literal[True],
351    validators: Sequence[Callable[..., Any]] = (),
352) -> _BinaryField[bytes | memoryview | None]: ...
353@overload
354def BinaryField(
355    *,
356    max_length: int | None = None,
357    required: Literal[False],
358    allow_null: Literal[True],
359    default: Literal[b""] | None,
360    validators: Sequence[Callable[..., Any]] = (),
361) -> _BinaryField[bytes | memoryview | None]: ...
362@overload
363def BinaryField(
364    *,
365    max_length: int | None = None,
366    required: bool = True,
367    allow_null: Literal[False] = False,
368    validators: Sequence[Callable[..., Any]] = (),
369) -> _BinaryField[bytes | memoryview]: ...
370@overload
371def BinaryField(
372    *,
373    max_length: int | None = None,
374    required: Literal[False],
375    allow_null: Literal[False] = False,
376    default: Literal[b""],
377    validators: Sequence[Callable[..., Any]] = (),
378) -> _BinaryField[bytes | memoryview]: ...
379@overload
380def GenericIPAddressField(
381    *,
382    protocol: str = "both",
383    unpack_ipv4: bool = False,
384    required: bool = True,
385    allow_null: Literal[True],
386    default: Any = ...,
387    validators: Sequence[Callable[..., Any]] = (),
388) -> _GenericIPAddressField[str | None]: ...
389@overload
390def GenericIPAddressField(
391    *,
392    protocol: str = "both",
393    unpack_ipv4: bool = False,
394    required: bool = True,
395    allow_null: Literal[False] = False,
396    default: Any = ...,
397    validators: Sequence[Callable[..., Any]] = (),
398) -> _GenericIPAddressField[str]: ...
399@overload
400def JSONField(
401    *,
402    encoder: Any = None,
403    decoder: Any = None,
404    required: bool = True,
405    allow_null: Literal[True],
406    default: Any = ...,
407    validators: Sequence[Callable[..., Any]] = (),
408) -> Any: ...
409@overload
410def JSONField(
411    *,
412    encoder: Any = None,
413    decoder: Any = None,
414    required: bool = True,
415    allow_null: Literal[False] = False,
416    default: Any = ...,
417    validators: Sequence[Callable[..., Any]] = (),
418) -> Any: ...
419
420# Encrypted fields
421@overload
422def EncryptedTextField(
423    *,
424    max_length: int | None = None,
425    required: bool = True,
426    allow_null: Literal[True],
427    validators: Sequence[Callable[..., Any]] = (),
428) -> _EncryptedTextField[str | None]: ...
429@overload
430def EncryptedTextField(
431    *,
432    max_length: int | None = None,
433    required: Literal[False],
434    allow_null: Literal[True],
435    default: Literal[""] | None,
436    validators: Sequence[Callable[..., Any]] = (),
437) -> _EncryptedTextField[str | None]: ...
438@overload
439def EncryptedTextField(
440    *,
441    max_length: int | None = None,
442    required: bool = True,
443    allow_null: Literal[False] = False,
444    validators: Sequence[Callable[..., Any]] = (),
445) -> _EncryptedTextField[str]: ...
446@overload
447def EncryptedTextField(
448    *,
449    max_length: int | None = None,
450    required: Literal[False],
451    allow_null: Literal[False] = False,
452    default: Literal[""],
453    validators: Sequence[Callable[..., Any]] = (),
454) -> _EncryptedTextField[str]: ...
455@overload
456def EncryptedJSONField(
457    *,
458    encoder: Any = None,
459    decoder: Any = None,
460    required: bool = True,
461    allow_null: Literal[True],
462    validators: Sequence[Callable[..., Any]] = (),
463) -> Any: ...
464@overload
465def EncryptedJSONField(
466    *,
467    encoder: Any = None,
468    decoder: Any = None,
469    required: bool = True,
470    allow_null: Literal[False] = False,
471    validators: Sequence[Callable[..., Any]] = (),
472) -> Any: ...
473
474# Related fields
475#
476# Two overload families:
477#
478# 1. Class-argument FK (`to=SomeModel`) — T is inferred from the class.
479#    Returns `_ForeignKeyDescriptor[T, V]` whose `__get__` overloads keep
480#    class-access typed as the descriptor itself (matching runtime
481#    `ForwardForeignKeyDescriptor.__get__` which returns `self` when
482#    `instance is None`) and instance-access as the related instance
483#    (or `T | None` for nullable FKs).
484#
485# 2. String-argument FK (`to="SomeModel"`, `to="self"`) — T can't be
486#    inferred from the string, so the return type falls back to bare `T`.
487#    This requires an explicit LHS annotation (`parent: TreeNode | None = …`)
488#    but preserves typing for forward references and self-references.
489#
490# `__set__` accepts the related instance, None (via V), or a bare PK
491# value (int) — matching what `ForwardForeignKeyDescriptor` already
492# accepts at runtime.
493#
494# NOTE: `bool` is a subclass of `int` in Python, so `child.parent = True`
495# type-checks here. The runtime `ForwardForeignKeyDescriptor.__set__`
496# explicitly rejects bool with `ValueError`, so this language quirk is
497# caught at runtime rather than silently coerced to PK 0/1.
498class _ForeignKeyDescriptor[T: Model, V]:
499    @overload
500    def __get__(self, instance: None, owner: type) -> _ForeignKeyDescriptor[T, V]: ...
501    @overload
502    def __get__(self, instance: Model, owner: type) -> V: ...
503    def __set__(self, instance: Model, value: V | int) -> None: ...
504
505# Class-argument FK overloads
506@overload
507def ForeignKeyField[T: Model](
508    to: type[T],
509    on_delete: OnDelete,
510    *,
511    related_query_name: str | None = None,
512    required: bool = True,
513    allow_null: Literal[True],
514    validators: Sequence[Callable[..., Any]] = (),
515) -> _ForeignKeyDescriptor[T, T | None]: ...
516@overload
517def ForeignKeyField[T: Model](
518    to: type[T],
519    on_delete: OnDelete,
520    *,
521    related_query_name: str | None = None,
522    required: bool = True,
523    allow_null: Literal[False] = False,
524    validators: Sequence[Callable[..., Any]] = (),
525) -> _ForeignKeyDescriptor[T, T]: ...
526
527# String-argument FK overloads (forward refs, self-refs) — T inferred from LHS annotation
528@overload
529def ForeignKeyField[T: Model](
530    to: str,
531    on_delete: OnDelete,
532    *,
533    related_query_name: str | None = None,
534    required: bool = True,
535    allow_null: Literal[True],
536    validators: Sequence[Callable[..., Any]] = (),
537) -> T | None: ...
538@overload
539def ForeignKeyField[T: Model](
540    to: str,
541    on_delete: OnDelete,
542    *,
543    related_query_name: str | None = None,
544    required: bool = True,
545    allow_null: Literal[False] = False,
546    validators: Sequence[Callable[..., Any]] = (),
547) -> T: ...
548def ManyToManyField[T: Model](
549    to: type[T] | str,
550    *,
551    through: Any,
552    through_fields: tuple[str, str] | None = None,
553    related_query_name: str | None = None,
554    symmetrical: bool | None = None,
555) -> ManyToManyManager[T]: ...
556
557# Reverse relation descriptors
558class ReverseForeignKey[T: Model, QS: QuerySet[Any] = QuerySet[Any]]:
559    """
560    Descriptor for the reverse side of a ForeignKeyField.
561
562    Type parameters:
563        _T: The related model type
564        _QS: The QuerySet type (use the model's custom QuerySet for proper method typing)
565
566    Example:
567        # With custom QuerySet for proper typing of custom methods like .enabled()
568        repos: ReverseForeignKey[Repo, RepoQuerySet] = ReverseForeignKey(to="Repo", field="organization")
569
570        # Usage: org.repos.query.enabled()  # .enabled() is now recognized
571    """
572    def __init__(self, *, to: type[T] | str, field: str) -> None: ...
573    @overload
574    def __get__(self, instance: None, owner: type) -> ReverseForeignKey[T, QS]: ...
575    @overload
576    def __get__(
577        self, instance: Model, owner: type
578    ) -> ReverseForeignKeyManager[T, QS]: ...
579    def __get__(
580        self, instance: Model | None, owner: type
581    ) -> ReverseForeignKey[T, QS] | ReverseForeignKeyManager[T, QS]: ...
582
583class ReverseManyToMany[T: Model, QS: QuerySet[Any] = QuerySet[Any]]:
584    """
585    Descriptor for the reverse side of a ManyToManyField.
586
587    Type parameters:
588        _T: The related model type
589        _QS: The QuerySet type (use the model's custom QuerySet for proper method typing)
590    """
591    def __init__(self, *, to: type[T] | str, field: str) -> None: ...
592    @overload
593    def __get__(self, instance: None, owner: type) -> ReverseManyToMany[T, QS]: ...
594    @overload
595    def __get__(self, instance: Model, owner: type) -> ManyToManyManager[T, QS]: ...
596    def __get__(
597        self, instance: Model | None, owner: type
598    ) -> ReverseManyToMany[T, QS] | ManyToManyManager[T, QS]: ...
599
600# Export all types (should match types.py)
601__all__ = [
602    "BigIntegerField",
603    "BinaryField",
604    "BooleanField",
605    "DateField",
606    "DateTimeField",
607    "DecimalField",
608    "DurationField",
609    "EmailField",
610    "EncryptedJSONField",
611    "EncryptedTextField",
612    "FloatField",
613    "ForeignKeyField",
614    "GenericIPAddressField",
615    "IntegerField",
616    "JSONField",
617    "ManyToManyField",
618    "ManyToManyManager",
619    "PrimaryKeyField",
620    "RandomStringField",
621    "ReverseForeignKey",
622    "ReverseForeignKeyManager",
623    "ReverseManyToMany",
624    "SmallIntegerField",
625    "TextField",
626    "TimeField",
627    "TimeZoneField",
628    "URLField",
629    "UUIDField",
630]