plain.models 0.49.2__py3-none-any.whl → 0.51.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. plain/models/CHANGELOG.md +27 -0
  2. plain/models/README.md +26 -42
  3. plain/models/__init__.py +2 -0
  4. plain/models/aggregates.py +42 -19
  5. plain/models/backends/base/base.py +125 -105
  6. plain/models/backends/base/client.py +11 -3
  7. plain/models/backends/base/creation.py +24 -14
  8. plain/models/backends/base/features.py +10 -4
  9. plain/models/backends/base/introspection.py +37 -20
  10. plain/models/backends/base/operations.py +187 -91
  11. plain/models/backends/base/schema.py +338 -218
  12. plain/models/backends/base/validation.py +13 -4
  13. plain/models/backends/ddl_references.py +85 -43
  14. plain/models/backends/mysql/base.py +29 -26
  15. plain/models/backends/mysql/client.py +7 -2
  16. plain/models/backends/mysql/compiler.py +13 -4
  17. plain/models/backends/mysql/creation.py +5 -2
  18. plain/models/backends/mysql/features.py +24 -22
  19. plain/models/backends/mysql/introspection.py +22 -13
  20. plain/models/backends/mysql/operations.py +107 -40
  21. plain/models/backends/mysql/schema.py +52 -28
  22. plain/models/backends/mysql/validation.py +13 -6
  23. plain/models/backends/postgresql/base.py +41 -34
  24. plain/models/backends/postgresql/client.py +7 -2
  25. plain/models/backends/postgresql/creation.py +10 -5
  26. plain/models/backends/postgresql/introspection.py +15 -8
  27. plain/models/backends/postgresql/operations.py +110 -43
  28. plain/models/backends/postgresql/schema.py +88 -49
  29. plain/models/backends/sqlite3/_functions.py +151 -115
  30. plain/models/backends/sqlite3/base.py +37 -23
  31. plain/models/backends/sqlite3/client.py +7 -1
  32. plain/models/backends/sqlite3/creation.py +9 -5
  33. plain/models/backends/sqlite3/features.py +5 -3
  34. plain/models/backends/sqlite3/introspection.py +32 -16
  35. plain/models/backends/sqlite3/operations.py +126 -43
  36. plain/models/backends/sqlite3/schema.py +127 -92
  37. plain/models/backends/utils.py +52 -29
  38. plain/models/backups/cli.py +8 -6
  39. plain/models/backups/clients.py +16 -7
  40. plain/models/backups/core.py +24 -13
  41. plain/models/base.py +221 -229
  42. plain/models/cli.py +98 -67
  43. plain/models/config.py +1 -1
  44. plain/models/connections.py +23 -7
  45. plain/models/constraints.py +79 -56
  46. plain/models/database_url.py +1 -1
  47. plain/models/db.py +6 -2
  48. plain/models/deletion.py +80 -56
  49. plain/models/entrypoints.py +1 -1
  50. plain/models/enums.py +22 -11
  51. plain/models/exceptions.py +23 -8
  52. plain/models/expressions.py +441 -258
  53. plain/models/fields/__init__.py +272 -217
  54. plain/models/fields/json.py +123 -57
  55. plain/models/fields/mixins.py +12 -8
  56. plain/models/fields/related.py +324 -290
  57. plain/models/fields/related_descriptors.py +33 -24
  58. plain/models/fields/related_lookups.py +24 -12
  59. plain/models/fields/related_managers.py +102 -79
  60. plain/models/fields/reverse_related.py +66 -63
  61. plain/models/forms.py +101 -75
  62. plain/models/functions/comparison.py +71 -18
  63. plain/models/functions/datetime.py +79 -29
  64. plain/models/functions/math.py +43 -10
  65. plain/models/functions/mixins.py +24 -7
  66. plain/models/functions/text.py +104 -25
  67. plain/models/functions/window.py +12 -6
  68. plain/models/indexes.py +57 -32
  69. plain/models/lookups.py +228 -153
  70. plain/models/meta.py +505 -0
  71. plain/models/migrations/autodetector.py +86 -43
  72. plain/models/migrations/exceptions.py +7 -3
  73. plain/models/migrations/executor.py +33 -7
  74. plain/models/migrations/graph.py +79 -50
  75. plain/models/migrations/loader.py +45 -22
  76. plain/models/migrations/migration.py +23 -18
  77. plain/models/migrations/operations/base.py +38 -20
  78. plain/models/migrations/operations/fields.py +95 -48
  79. plain/models/migrations/operations/models.py +246 -142
  80. plain/models/migrations/operations/special.py +82 -25
  81. plain/models/migrations/optimizer.py +7 -2
  82. plain/models/migrations/questioner.py +58 -31
  83. plain/models/migrations/recorder.py +27 -16
  84. plain/models/migrations/serializer.py +50 -39
  85. plain/models/migrations/state.py +232 -156
  86. plain/models/migrations/utils.py +30 -14
  87. plain/models/migrations/writer.py +17 -14
  88. plain/models/options.py +189 -518
  89. plain/models/otel.py +16 -6
  90. plain/models/preflight.py +42 -17
  91. plain/models/query.py +400 -251
  92. plain/models/query_utils.py +109 -69
  93. plain/models/registry.py +40 -21
  94. plain/models/sql/compiler.py +190 -127
  95. plain/models/sql/datastructures.py +38 -25
  96. plain/models/sql/query.py +320 -225
  97. plain/models/sql/subqueries.py +36 -25
  98. plain/models/sql/where.py +54 -29
  99. plain/models/test/pytest.py +15 -11
  100. plain/models/test/utils.py +4 -2
  101. plain/models/transaction.py +20 -7
  102. plain/models/utils.py +17 -6
  103. {plain_models-0.49.2.dist-info → plain_models-0.51.0.dist-info}/METADATA +27 -43
  104. plain_models-0.51.0.dist-info/RECORD +123 -0
  105. plain_models-0.49.2.dist-info/RECORD +0 -122
  106. {plain_models-0.49.2.dist-info → plain_models-0.51.0.dist-info}/WHEEL +0 -0
  107. {plain_models-0.49.2.dist-info → plain_models-0.51.0.dist-info}/entry_points.txt +0 -0
  108. {plain_models-0.49.2.dist-info → plain_models-0.51.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import collections.abc
2
4
  import copy
3
5
  import datetime
@@ -7,7 +9,9 @@ import operator
7
9
  import uuid
8
10
  import warnings
9
11
  from base64 import b64decode, b64encode
12
+ from collections.abc import Callable, Sequence
10
13
  from functools import cached_property, total_ordering
14
+ from typing import TYPE_CHECKING, Any
11
15
 
12
16
  from plain import exceptions, validators
13
17
  from plain.models.constants import LOOKUP_SEP
@@ -30,6 +34,11 @@ from plain.utils.itercompat import is_iterable
30
34
 
31
35
  from ..registry import models_registry
32
36
 
37
+ if TYPE_CHECKING:
38
+ from plain.models.backends.base.base import BaseDatabaseWrapper
39
+ from plain.models.fields.reverse_related import ForeignObjectRel
40
+ from plain.models.sql.compiler import SQLCompiler
41
+
33
42
  __all__ = [
34
43
  "BLANK_CHOICE_DASH",
35
44
  "PrimaryKeyField",
@@ -72,8 +81,8 @@ class NOT_PROVIDED:
72
81
  BLANK_CHOICE_DASH = [("", "---------")]
73
82
 
74
83
 
75
- def _load_field(package_label, model_name, field_name):
76
- return models_registry.get_model(package_label, model_name)._meta.get_field(
84
+ def _load_field(package_label: str, model_name: str, field_name: str) -> Field:
85
+ return models_registry.get_model(package_label, model_name)._model_meta.get_field(
77
86
  field_name
78
87
  )
79
88
 
@@ -92,13 +101,13 @@ def _load_field(package_label, model_name, field_name):
92
101
  # attname.
93
102
 
94
103
 
95
- def _empty(of_cls):
104
+ def _empty(of_cls: type) -> Empty:
96
105
  new = Empty()
97
106
  new.__class__ = of_cls
98
107
  return new
99
108
 
100
109
 
101
- def return_None():
110
+ def return_None() -> None:
102
111
  return None
103
112
 
104
113
 
@@ -150,7 +159,7 @@ class Field(RegisterLookupMixin):
150
159
  descriptor_class = DeferredAttribute
151
160
 
152
161
  # Generic field type description, usually overridden by subclasses
153
- def _description(self):
162
+ def _description(self) -> str:
154
163
  return f"Field of type: {self.__class__.__name__}"
155
164
 
156
165
  description = property(_description)
@@ -158,16 +167,16 @@ class Field(RegisterLookupMixin):
158
167
  def __init__(
159
168
  self,
160
169
  *,
161
- max_length=None,
162
- required=True,
163
- allow_null=False,
164
- rel=None,
165
- default=NOT_PROVIDED,
166
- choices=None,
167
- db_column=None,
168
- validators=(),
169
- error_messages=None,
170
- db_comment=None,
170
+ max_length: int | None = None,
171
+ required: bool = True,
172
+ allow_null: bool = False,
173
+ rel: ForeignObjectRel | None = None,
174
+ default: Any = NOT_PROVIDED,
175
+ choices: Any = None,
176
+ db_column: str | None = None,
177
+ validators: Sequence[Callable[..., Any]] = (),
178
+ error_messages: dict[str, str] | None = None,
179
+ db_comment: str | None = None,
171
180
  ):
172
181
  self.name = None # Set by set_attributes_from_name
173
182
  self.max_length = max_length
@@ -196,7 +205,7 @@ class Field(RegisterLookupMixin):
196
205
 
197
206
  self._error_messages = error_messages # Store for deconstruction later
198
207
 
199
- def __str__(self):
208
+ def __str__(self) -> str:
200
209
  """
201
210
  Return "package_label.model_label.field_name" for fields attached to
202
211
  models.
@@ -204,9 +213,9 @@ class Field(RegisterLookupMixin):
204
213
  if not hasattr(self, "model"):
205
214
  return super().__str__()
206
215
  model = self.model
207
- return f"{model._meta.label}.{self.name}"
216
+ return f"{model.model_options.label}.{self.name}"
208
217
 
209
- def __repr__(self):
218
+ def __repr__(self) -> str:
210
219
  """Display the module, class, and name of the field."""
211
220
  path = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
212
221
  name = getattr(self, "name", None)
@@ -214,7 +223,7 @@ class Field(RegisterLookupMixin):
214
223
  return f"<{path}: {name}>"
215
224
  return f"<{path}>"
216
225
 
217
- def preflight(self, **kwargs):
226
+ def preflight(self, **kwargs: Any) -> list[PreflightResult]:
218
227
  return [
219
228
  *self._check_field_name(),
220
229
  *self._check_choices(),
@@ -224,7 +233,7 @@ class Field(RegisterLookupMixin):
224
233
  *self._check_validators(),
225
234
  ]
226
235
 
227
- def _check_field_name(self):
236
+ def _check_field_name(self) -> list[PreflightResult]:
228
237
  """
229
238
  Check if field name is valid, i.e. 1) does not end with an
230
239
  underscore, 2) does not contain "__" and 3) is not "id".
@@ -257,10 +266,10 @@ class Field(RegisterLookupMixin):
257
266
  return []
258
267
 
259
268
  @classmethod
260
- def _choices_is_value(cls, value):
269
+ def _choices_is_value(cls, value: Any) -> bool:
261
270
  return isinstance(value, str | Promise) or not is_iterable(value)
262
271
 
263
- def _check_choices(self):
272
+ def _check_choices(self) -> list[PreflightResult]:
264
273
  if not self.choices:
265
274
  return []
266
275
 
@@ -332,13 +341,13 @@ class Field(RegisterLookupMixin):
332
341
  )
333
342
  ]
334
343
 
335
- def _check_db_comment(self):
344
+ def _check_db_comment(self) -> list[PreflightResult]:
336
345
  if not self.db_comment:
337
346
  return []
338
347
  errors = []
339
348
  if not (
340
349
  db_connection.features.supports_comments
341
- or "supports_comments" in self.model._meta.required_db_features
350
+ or "supports_comments" in self.model.model_options.required_db_features
342
351
  ):
343
352
  errors.append(
344
353
  PreflightResult(
@@ -351,7 +360,7 @@ class Field(RegisterLookupMixin):
351
360
  )
352
361
  return errors
353
362
 
354
- def _check_null_allowed_for_primary_keys(self):
363
+ def _check_null_allowed_for_primary_keys(self) -> list[PreflightResult]:
355
364
  if self.primary_key and self.allow_null:
356
365
  # We cannot reliably check this for backends like Oracle which
357
366
  # consider NULL and '' to be equal (and thus set up
@@ -368,12 +377,12 @@ class Field(RegisterLookupMixin):
368
377
  else:
369
378
  return []
370
379
 
371
- def _check_backend_specific_checks(self):
380
+ def _check_backend_specific_checks(self) -> list[PreflightResult]:
372
381
  errors = []
373
382
  errors.extend(db_connection.validation.check_field(self))
374
383
  return errors
375
384
 
376
- def _check_validators(self):
385
+ def _check_validators(self) -> list[PreflightResult]:
377
386
  errors = []
378
387
  for i, validator in enumerate(self.validators):
379
388
  if not callable(validator):
@@ -390,8 +399,8 @@ class Field(RegisterLookupMixin):
390
399
  )
391
400
  return errors
392
401
 
393
- def get_col(self, alias, output_field=None):
394
- if alias == self.model._meta.db_table and (
402
+ def get_col(self, alias: str, output_field: Field | None = None) -> Any:
403
+ if alias == self.model.model_options.db_table and (
395
404
  output_field is None or output_field == self
396
405
  ):
397
406
  return self.cached_col
@@ -400,12 +409,14 @@ class Field(RegisterLookupMixin):
400
409
  return Col(alias, self, output_field)
401
410
 
402
411
  @cached_property
403
- def cached_col(self):
412
+ def cached_col(self) -> Any:
404
413
  from plain.models.expressions import Col
405
414
 
406
- return Col(self.model._meta.db_table, self)
415
+ return Col(self.model.model_options.db_table, self)
407
416
 
408
- def select_format(self, compiler, sql, params):
417
+ def select_format(
418
+ self, compiler: SQLCompiler, sql: str, params: Any
419
+ ) -> tuple[str, Any]:
409
420
  """
410
421
  Custom format for select clauses. For example, GIS columns need to be
411
422
  selected as AsText(table.col) on MySQL as the table.col data can't be
@@ -413,7 +424,7 @@ class Field(RegisterLookupMixin):
413
424
  """
414
425
  return sql, params
415
426
 
416
- def deconstruct(self):
427
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
417
428
  """
418
429
  Return enough information to recreate the field as a 4-tuple:
419
430
 
@@ -488,7 +499,7 @@ class Field(RegisterLookupMixin):
488
499
  # Return basic info - other fields should override this.
489
500
  return (self.name, path, [], keywords)
490
501
 
491
- def clone(self):
502
+ def clone(self) -> Field:
492
503
  """
493
504
  Uses deconstruct() to clone a new copy of this Field.
494
505
  Will not preserve any class attachments/attribute names.
@@ -496,7 +507,7 @@ class Field(RegisterLookupMixin):
496
507
  name, path, args, kwargs = self.deconstruct()
497
508
  return self.__class__(*args, **kwargs)
498
509
 
499
- def __eq__(self, other):
510
+ def __eq__(self, other: object) -> bool:
500
511
  # Needed for @total_ordering
501
512
  if isinstance(other, Field):
502
513
  return self.creation_counter == other.creation_counter and getattr(
@@ -504,7 +515,7 @@ class Field(RegisterLookupMixin):
504
515
  ) == getattr(other, "model", None)
505
516
  return NotImplemented
506
517
 
507
- def __lt__(self, other):
518
+ def __lt__(self, other: object) -> bool:
508
519
  # This is needed because bisect does not take a comparison function.
509
520
  # Order by creation_counter first for backward compatibility.
510
521
  if isinstance(other, Field):
@@ -518,16 +529,19 @@ class Field(RegisterLookupMixin):
518
529
  return not hasattr(self, "model") # Order no-model fields first
519
530
  else:
520
531
  # creation_counter's are equal, compare only models.
521
- return (self.model._meta.package_label, self.model._meta.model_name) < (
522
- other.model._meta.package_label,
523
- other.model._meta.model_name,
532
+ return (
533
+ self.model.model_options.package_label,
534
+ self.model.model_options.model_name,
535
+ ) < (
536
+ other.model.model_options.package_label,
537
+ other.model.model_options.model_name,
524
538
  )
525
539
  return NotImplemented
526
540
 
527
- def __hash__(self):
541
+ def __hash__(self) -> int:
528
542
  return hash(self.creation_counter)
529
543
 
530
- def __deepcopy__(self, memodict):
544
+ def __deepcopy__(self, memodict: dict[int, Any]) -> Field:
531
545
  # We don't have to deepcopy very much here, since most things are not
532
546
  # intended to be altered after initial creation.
533
547
  obj = copy.copy(self)
@@ -538,17 +552,22 @@ class Field(RegisterLookupMixin):
538
552
  memodict[id(self)] = obj
539
553
  return obj
540
554
 
541
- def __copy__(self):
555
+ def __copy__(self) -> Field:
542
556
  # We need to avoid hitting __reduce__, so define this
543
557
  # slightly weird copy construct.
544
558
  obj = Empty()
545
559
  obj.__class__ = self.__class__
546
560
  obj.__dict__ = self.__dict__.copy()
547
- return obj
561
+ return obj # type: ignore[return-value]
548
562
 
549
- def __reduce__(self):
563
+ def __reduce__(
564
+ self,
565
+ ) -> (
566
+ tuple[Callable[..., Any], tuple[Any, ...], dict[str, Any]]
567
+ | tuple[Callable[..., Field], tuple[str, str, str]]
568
+ ):
550
569
  """
551
- Pickling should return the model._meta.fields instance of the field,
570
+ Pickling should return the model._model_meta.fields instance of the field,
552
571
  not a new copy of that field. So, use the app registry to load the
553
572
  model and then the field back.
554
573
  """
@@ -564,12 +583,12 @@ class Field(RegisterLookupMixin):
564
583
  state.pop("_get_default", None)
565
584
  return _empty, (self.__class__,), state
566
585
  return _load_field, (
567
- self.model._meta.package_label,
568
- self.model._meta.object_name,
586
+ self.model.model_options.package_label,
587
+ self.model.model_options.object_name,
569
588
  self.name,
570
589
  )
571
590
 
572
- def get_id_value_on_save(self, instance):
591
+ def get_id_value_on_save(self, instance: Any) -> Any:
573
592
  """
574
593
  Hook to generate new primary key values on save. This method is called when
575
594
  saving instances with no primary key value set. If this method returns
@@ -580,7 +599,7 @@ class Field(RegisterLookupMixin):
580
599
  return self.get_default()
581
600
  return None
582
601
 
583
- def to_python(self, value):
602
+ def to_python(self, value: Any) -> Any:
584
603
  """
585
604
  Convert the input value into the expected Python data type, raising
586
605
  plain.exceptions.ValidationError if the data can't be converted.
@@ -589,7 +608,7 @@ class Field(RegisterLookupMixin):
589
608
  return value
590
609
 
591
610
  @cached_property
592
- def error_messages(self):
611
+ def error_messages(self) -> dict[str, str]:
593
612
  messages = {}
594
613
  for c in reversed(self.__class__.__mro__):
595
614
  messages.update(getattr(c, "default_error_messages", {}))
@@ -597,14 +616,14 @@ class Field(RegisterLookupMixin):
597
616
  return messages
598
617
 
599
618
  @cached_property
600
- def validators(self):
619
+ def validators(self) -> list[Callable[..., Any]]:
601
620
  """
602
621
  Some validators can't be created at field initialization time.
603
622
  This method provides a way to delay their creation until required.
604
623
  """
605
624
  return [*self.default_validators, *self._validators]
606
625
 
607
- def run_validators(self, value):
626
+ def run_validators(self, value: Any) -> None:
608
627
  if value in self.empty_values:
609
628
  return
610
629
 
@@ -620,7 +639,7 @@ class Field(RegisterLookupMixin):
620
639
  if errors:
621
640
  raise exceptions.ValidationError(errors)
622
641
 
623
- def validate(self, value, model_instance):
642
+ def validate(self, value: Any, model_instance: Any) -> None:
624
643
  """
625
644
  Validate value and raise ValidationError if necessary. Subclasses
626
645
  should override this to provide validation logic.
@@ -652,7 +671,7 @@ class Field(RegisterLookupMixin):
652
671
  self.error_messages["required"], code="required"
653
672
  )
654
673
 
655
- def clean(self, value, model_instance):
674
+ def clean(self, value: Any, model_instance: Any) -> Any:
656
675
  """
657
676
  Convert the value's type and run validation. Validation errors
658
677
  from to_python() and validate() are propagated. Return the correct
@@ -663,10 +682,10 @@ class Field(RegisterLookupMixin):
663
682
  self.run_validators(value)
664
683
  return value
665
684
 
666
- def db_type_parameters(self, connection):
685
+ def db_type_parameters(self, connection: BaseDatabaseWrapper) -> DictWrapper:
667
686
  return DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
668
687
 
669
- def db_check(self, connection):
688
+ def db_check(self, connection: BaseDatabaseWrapper) -> str | None:
670
689
  """
671
690
  Return the database column check constraint for this field, for the
672
691
  provided connection. Works the same way as db_type() for the case that
@@ -680,7 +699,7 @@ class Field(RegisterLookupMixin):
680
699
  except KeyError:
681
700
  return None
682
701
 
683
- def db_type(self, connection):
702
+ def db_type(self, connection: BaseDatabaseWrapper) -> str | None:
684
703
  """
685
704
  Return the database column data type for this field, for the provided
686
705
  connection.
@@ -711,21 +730,21 @@ class Field(RegisterLookupMixin):
711
730
  return column_type(data)
712
731
  return column_type % data
713
732
 
714
- def rel_db_type(self, connection):
733
+ def rel_db_type(self, connection: BaseDatabaseWrapper) -> str | None:
715
734
  """
716
735
  Return the data type that a related field pointing to this field should
717
736
  use. For example, this method is called by ForeignKey to determine its data type.
718
737
  """
719
738
  return self.db_type(connection)
720
739
 
721
- def cast_db_type(self, connection):
740
+ def cast_db_type(self, connection: BaseDatabaseWrapper) -> str | None:
722
741
  """Return the data type to use in the Cast() function."""
723
742
  db_type = connection.ops.cast_data_types.get(self.get_internal_type())
724
743
  if db_type:
725
744
  return db_type % self.db_type_parameters(connection)
726
745
  return self.db_type(connection)
727
746
 
728
- def db_parameters(self, connection):
747
+ def db_parameters(self, connection: BaseDatabaseWrapper) -> dict[str, Any]:
729
748
  """
730
749
  Extension of db_type(), providing a range of different return values
731
750
  (type, checks). This will look at db_type(), allowing custom model
@@ -738,59 +757,63 @@ class Field(RegisterLookupMixin):
738
757
  "check": check_string,
739
758
  }
740
759
 
741
- def db_type_suffix(self, connection):
760
+ def db_type_suffix(self, connection: BaseDatabaseWrapper) -> str | None:
742
761
  return connection.data_types_suffix.get(self.get_internal_type())
743
762
 
744
- def get_db_converters(self, connection):
763
+ def get_db_converters(
764
+ self, connection: BaseDatabaseWrapper
765
+ ) -> list[Callable[..., Any]]:
745
766
  if hasattr(self, "from_db_value"):
746
767
  return [self.from_db_value]
747
768
  return []
748
769
 
749
770
  @property
750
- def db_returning(self):
771
+ def db_returning(self) -> bool:
751
772
  """
752
773
  Private API intended only to be used by Plain itself. Currently only
753
774
  the PostgreSQL backend supports returning multiple fields on a model.
754
775
  """
755
776
  return False
756
777
 
757
- def set_attributes_from_name(self, name):
778
+ def set_attributes_from_name(self, name: str) -> None:
758
779
  self.name = self.name or name
759
780
  self.attname, self.column = self.get_attname_column()
760
781
  self.concrete = self.column is not None
761
782
 
762
- def contribute_to_class(self, cls, name):
783
+ def contribute_to_class(self, cls: Any, name: str) -> None:
763
784
  """
764
785
  Register the field with the model class it belongs to.
765
786
  """
766
787
  self.set_attributes_from_name(name)
767
788
  self.model = cls
768
- cls._meta.add_field(self)
789
+ cls._model_meta.add_field(self)
769
790
  if self.column:
770
791
  setattr(cls, self.attname, self.descriptor_class(self))
771
792
 
772
- def get_attname(self):
793
+ def get_attname(self) -> str:
773
794
  return self.name
774
795
 
775
- def get_attname_column(self):
796
+ def get_attname_column(self) -> tuple[str, str]:
776
797
  attname = self.get_attname()
777
798
  column = self.db_column or attname
778
799
  return attname, column
779
800
 
780
- def get_internal_type(self):
801
+ def get_internal_type(self) -> str:
781
802
  return self.__class__.__name__
782
803
 
783
- def pre_save(self, model_instance, add):
804
+ def pre_save(self, model_instance: Any, add: bool) -> Any:
784
805
  """Return field's value just before saving."""
785
806
  return getattr(model_instance, self.attname)
786
807
 
787
- def get_prep_value(self, value):
808
+ def get_prep_value(self, value: Any) -> Any:
788
809
  """Perform preliminary non-db specific value checks and conversions."""
789
810
  if isinstance(value, Promise):
790
811
  value = value._proxy____cast()
791
812
  return value
792
813
 
793
- def get_db_prep_value(self, value, connection, prepared=False):
814
+ def get_db_prep_value(
815
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
816
+ ) -> Any:
794
817
  """
795
818
  Return field's value prepared for interacting with the database backend.
796
819
 
@@ -800,22 +823,22 @@ class Field(RegisterLookupMixin):
800
823
  value = self.get_prep_value(value)
801
824
  return value
802
825
 
803
- def get_db_prep_save(self, value, connection):
826
+ def get_db_prep_save(self, value: Any, connection: BaseDatabaseWrapper) -> Any:
804
827
  """Return field's value prepared for saving into a database."""
805
828
  if hasattr(value, "as_sql"):
806
829
  return value
807
830
  return self.get_db_prep_value(value, connection=connection, prepared=False)
808
831
 
809
- def has_default(self):
832
+ def has_default(self) -> bool:
810
833
  """Return a boolean of whether this field has a default value."""
811
834
  return self.default is not NOT_PROVIDED
812
835
 
813
- def get_default(self):
836
+ def get_default(self) -> Any:
814
837
  """Return the default value for this field."""
815
838
  return self._get_default()
816
839
 
817
840
  @cached_property
818
- def _get_default(self):
841
+ def _get_default(self) -> Callable[[], Any]:
819
842
  if self.has_default():
820
843
  if callable(self.default):
821
844
  return self.default
@@ -827,11 +850,11 @@ class Field(RegisterLookupMixin):
827
850
 
828
851
  def get_choices(
829
852
  self,
830
- include_blank=True,
831
- blank_choice=BLANK_CHOICE_DASH,
832
- limit_choices_to=None,
833
- ordering=(),
834
- ):
853
+ include_blank: bool = True,
854
+ blank_choice: list[tuple[str, str]] = BLANK_CHOICE_DASH,
855
+ limit_choices_to: Any = None,
856
+ ordering: tuple[str, ...] = (),
857
+ ) -> list[tuple[Any, str]]:
835
858
  """
836
859
  Return choices with a default blank choices included, for use
837
860
  as <select> choices for this field.
@@ -859,14 +882,14 @@ class Field(RegisterLookupMixin):
859
882
  (choice_func(x), str(x)) for x in qs
860
883
  ]
861
884
 
862
- def value_to_string(self, obj):
885
+ def value_to_string(self, obj: Any) -> str:
863
886
  """
864
887
  Return a string value of this field from the passed obj.
865
888
  This is used by the serialization framework.
866
889
  """
867
890
  return str(self.value_from_object(obj))
868
891
 
869
- def _get_flatchoices(self):
892
+ def _get_flatchoices(self) -> list[tuple[Any, Any]]:
870
893
  """Flattened version of choices tuple."""
871
894
  if self.choices is None:
872
895
  return []
@@ -880,10 +903,10 @@ class Field(RegisterLookupMixin):
880
903
 
881
904
  flatchoices = property(_get_flatchoices)
882
905
 
883
- def save_form_data(self, instance, data):
906
+ def save_form_data(self, instance: Any, data: Any) -> None:
884
907
  setattr(instance, self.name, data)
885
908
 
886
- def value_from_object(self, obj):
909
+ def value_from_object(self, obj: Any) -> Any:
887
910
  """Return the value of this field in the given model instance."""
888
911
  return getattr(obj, self.attname)
889
912
 
@@ -896,10 +919,10 @@ class BooleanField(Field):
896
919
  }
897
920
  description = "Boolean (Either True or False)"
898
921
 
899
- def get_internal_type(self):
922
+ def get_internal_type(self) -> str:
900
923
  return "BooleanField"
901
924
 
902
- def to_python(self, value):
925
+ def to_python(self, value: Any) -> Any:
903
926
  if self.allow_null and value in self.empty_values:
904
927
  return None
905
928
  if value in (True, False):
@@ -915,7 +938,7 @@ class BooleanField(Field):
915
938
  params={"value": value},
916
939
  )
917
940
 
918
- def get_prep_value(self, value):
941
+ def get_prep_value(self, value: Any) -> Any:
919
942
  value = super().get_prep_value(value)
920
943
  if value is None:
921
944
  return None
@@ -923,32 +946,32 @@ class BooleanField(Field):
923
946
 
924
947
 
925
948
  class CharField(Field):
926
- def __init__(self, *, db_collation=None, **kwargs):
949
+ def __init__(self, *, db_collation: str | None = None, **kwargs: Any):
927
950
  super().__init__(**kwargs)
928
951
  self.db_collation = db_collation
929
952
  if self.max_length is not None:
930
953
  self.validators.append(validators.MaxLengthValidator(self.max_length))
931
954
 
932
955
  @property
933
- def description(self):
956
+ def description(self) -> str:
934
957
  if self.max_length is not None:
935
958
  return "String (up to %(max_length)s)"
936
959
  else:
937
960
  return "String (unlimited)"
938
961
 
939
- def preflight(self, **kwargs):
962
+ def preflight(self, **kwargs: Any) -> list[PreflightResult]:
940
963
  return [
941
964
  *super().preflight(**kwargs),
942
965
  *self._check_db_collation(),
943
966
  *self._check_max_length_attribute(),
944
967
  ]
945
968
 
946
- def _check_max_length_attribute(self, **kwargs):
969
+ def _check_max_length_attribute(self, **kwargs: Any) -> list[PreflightResult]:
947
970
  if self.max_length is None:
948
971
  if (
949
972
  db_connection.features.supports_unlimited_charfield
950
973
  or "supports_unlimited_charfield"
951
- in self.model._meta.required_db_features
974
+ in self.model.model_options.required_db_features
952
975
  ):
953
976
  return []
954
977
  return [
@@ -973,12 +996,12 @@ class CharField(Field):
973
996
  else:
974
997
  return []
975
998
 
976
- def _check_db_collation(self):
999
+ def _check_db_collation(self) -> list[PreflightResult]:
977
1000
  errors = []
978
1001
  if not (
979
1002
  self.db_collation is None
980
1003
  or "supports_collation_on_charfield"
981
- in self.model._meta.required_db_features
1004
+ in self.model.model_options.required_db_features
982
1005
  or db_connection.features.supports_collation_on_charfield
983
1006
  ):
984
1007
  errors.append(
@@ -991,61 +1014,61 @@ class CharField(Field):
991
1014
  )
992
1015
  return errors
993
1016
 
994
- def cast_db_type(self, connection):
1017
+ def cast_db_type(self, connection: BaseDatabaseWrapper) -> str | None:
995
1018
  if self.max_length is None:
996
1019
  return connection.ops.cast_char_field_without_max_length
997
1020
  return super().cast_db_type(connection)
998
1021
 
999
- def db_parameters(self, connection):
1022
+ def db_parameters(self, connection: BaseDatabaseWrapper) -> dict[str, Any]:
1000
1023
  db_params = super().db_parameters(connection)
1001
1024
  db_params["collation"] = self.db_collation
1002
1025
  return db_params
1003
1026
 
1004
- def get_internal_type(self):
1027
+ def get_internal_type(self) -> str:
1005
1028
  return "CharField"
1006
1029
 
1007
- def to_python(self, value):
1030
+ def to_python(self, value: Any) -> Any:
1008
1031
  if isinstance(value, str) or value is None:
1009
1032
  return value
1010
1033
  return str(value)
1011
1034
 
1012
- def get_prep_value(self, value):
1035
+ def get_prep_value(self, value: Any) -> Any:
1013
1036
  value = super().get_prep_value(value)
1014
1037
  return self.to_python(value)
1015
1038
 
1016
- def deconstruct(self):
1039
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
1017
1040
  name, path, args, kwargs = super().deconstruct()
1018
1041
  if self.db_collation:
1019
1042
  kwargs["db_collation"] = self.db_collation
1020
1043
  return name, path, args, kwargs
1021
1044
 
1022
1045
 
1023
- def _to_naive(value):
1046
+ def _to_naive(value: datetime.datetime) -> datetime.datetime:
1024
1047
  if timezone.is_aware(value):
1025
1048
  value = timezone.make_naive(value, datetime.UTC)
1026
1049
  return value
1027
1050
 
1028
1051
 
1029
- def _get_naive_now():
1052
+ def _get_naive_now() -> datetime.datetime:
1030
1053
  return _to_naive(timezone.now())
1031
1054
 
1032
1055
 
1033
1056
  class DateTimeCheckMixin:
1034
- def preflight(self, **kwargs):
1057
+ def preflight(self, **kwargs: Any) -> list[PreflightResult]: # type: ignore[misc]
1035
1058
  return [
1036
- *super().preflight(**kwargs),
1059
+ *super().preflight(**kwargs), # type: ignore[misc]
1037
1060
  *self._check_mutually_exclusive_options(),
1038
1061
  *self._check_fix_default_value(),
1039
1062
  ]
1040
1063
 
1041
- def _check_mutually_exclusive_options(self):
1064
+ def _check_mutually_exclusive_options(self) -> list[PreflightResult]:
1042
1065
  # auto_now, auto_now_add, and default are mutually exclusive
1043
1066
  # options. The use of more than one of these options together
1044
1067
  # will trigger an Error
1045
1068
  mutually_exclusive_options = [
1046
- self.auto_now_add,
1047
- self.auto_now,
1048
- self.has_default(),
1069
+ self.auto_now_add, # type: ignore[attr-defined]
1070
+ self.auto_now, # type: ignore[attr-defined]
1071
+ self.has_default(), # type: ignore[attr-defined]
1049
1072
  ]
1050
1073
  enabled_options = [
1051
1074
  option not in (None, False) for option in mutually_exclusive_options
@@ -1063,12 +1086,16 @@ class DateTimeCheckMixin:
1063
1086
  else:
1064
1087
  return []
1065
1088
 
1066
- def _check_fix_default_value(self):
1089
+ def _check_fix_default_value(self) -> list[PreflightResult]:
1067
1090
  return []
1068
1091
 
1069
1092
  # Concrete subclasses use this in their implementations of
1070
1093
  # _check_fix_default_value().
1071
- def _check_if_value_fixed(self, value, now=None):
1094
+ def _check_if_value_fixed(
1095
+ self,
1096
+ value: datetime.date | datetime.datetime,
1097
+ now: datetime.datetime | None = None,
1098
+ ) -> list[PreflightResult]:
1072
1099
  """
1073
1100
  Check if the given value appears to have been provided as a "fixed"
1074
1101
  time value, and include a warning in the returned list if it does. The
@@ -1110,13 +1137,15 @@ class DateField(DateTimeCheckMixin, Field):
1110
1137
  }
1111
1138
  description = "Date (without time)"
1112
1139
 
1113
- def __init__(self, *, auto_now=False, auto_now_add=False, **kwargs):
1140
+ def __init__(
1141
+ self, *, auto_now: bool = False, auto_now_add: bool = False, **kwargs: Any
1142
+ ):
1114
1143
  self.auto_now, self.auto_now_add = auto_now, auto_now_add
1115
1144
  if auto_now or auto_now_add:
1116
1145
  kwargs["required"] = False
1117
1146
  super().__init__(**kwargs)
1118
1147
 
1119
- def _check_fix_default_value(self):
1148
+ def _check_fix_default_value(self) -> list[PreflightResult]:
1120
1149
  """
1121
1150
  Warn that using an actual date or datetime value is probably wrong;
1122
1151
  it's only evaluated on server startup.
@@ -1135,7 +1164,7 @@ class DateField(DateTimeCheckMixin, Field):
1135
1164
  # At this point, value is a date object.
1136
1165
  return self._check_if_value_fixed(value)
1137
1166
 
1138
- def deconstruct(self):
1167
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
1139
1168
  name, path, args, kwargs = super().deconstruct()
1140
1169
  if self.auto_now:
1141
1170
  kwargs["auto_now"] = True
@@ -1145,10 +1174,10 @@ class DateField(DateTimeCheckMixin, Field):
1145
1174
  del kwargs["required"]
1146
1175
  return name, path, args, kwargs
1147
1176
 
1148
- def get_internal_type(self):
1177
+ def get_internal_type(self) -> str:
1149
1178
  return "DateField"
1150
1179
 
1151
- def to_python(self, value):
1180
+ def to_python(self, value: Any) -> Any:
1152
1181
  if value is None:
1153
1182
  return value
1154
1183
  if isinstance(value, datetime.datetime):
@@ -1178,7 +1207,7 @@ class DateField(DateTimeCheckMixin, Field):
1178
1207
  params={"value": value},
1179
1208
  )
1180
1209
 
1181
- def pre_save(self, model_instance, add):
1210
+ def pre_save(self, model_instance: Any, add: bool) -> Any:
1182
1211
  if self.auto_now or (self.auto_now_add and add):
1183
1212
  value = datetime.date.today()
1184
1213
  setattr(model_instance, self.attname, value)
@@ -1186,17 +1215,19 @@ class DateField(DateTimeCheckMixin, Field):
1186
1215
  else:
1187
1216
  return super().pre_save(model_instance, add)
1188
1217
 
1189
- def get_prep_value(self, value):
1218
+ def get_prep_value(self, value: Any) -> Any:
1190
1219
  value = super().get_prep_value(value)
1191
1220
  return self.to_python(value)
1192
1221
 
1193
- def get_db_prep_value(self, value, connection, prepared=False):
1222
+ def get_db_prep_value(
1223
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
1224
+ ) -> Any:
1194
1225
  # Casts dates into the format expected by the backend
1195
1226
  if not prepared:
1196
1227
  value = self.get_prep_value(value)
1197
1228
  return connection.ops.adapt_datefield_value(value)
1198
1229
 
1199
- def value_to_string(self, obj):
1230
+ def value_to_string(self, obj: Any) -> str:
1200
1231
  val = self.value_from_object(obj)
1201
1232
  return "" if val is None else val.isoformat()
1202
1233
 
@@ -1212,7 +1243,7 @@ class DateTimeField(DateField):
1212
1243
 
1213
1244
  # __init__ is inherited from DateField
1214
1245
 
1215
- def _check_fix_default_value(self):
1246
+ def _check_fix_default_value(self) -> list[PreflightResult]:
1216
1247
  """
1217
1248
  Warn that using an actual date or datetime value is probably wrong;
1218
1249
  it's only evaluated on server startup.
@@ -1226,10 +1257,10 @@ class DateTimeField(DateField):
1226
1257
  # No explicit date / datetime value -- no checks necessary.
1227
1258
  return []
1228
1259
 
1229
- def get_internal_type(self):
1260
+ def get_internal_type(self) -> str:
1230
1261
  return "DateTimeField"
1231
1262
 
1232
- def to_python(self, value):
1263
+ def to_python(self, value: Any) -> Any:
1233
1264
  if value is None:
1234
1265
  return value
1235
1266
  if isinstance(value, datetime.datetime):
@@ -1279,7 +1310,7 @@ class DateTimeField(DateField):
1279
1310
  params={"value": value},
1280
1311
  )
1281
1312
 
1282
- def pre_save(self, model_instance, add):
1313
+ def pre_save(self, model_instance: Any, add: bool) -> Any:
1283
1314
  if self.auto_now or (self.auto_now_add and add):
1284
1315
  value = timezone.now()
1285
1316
  setattr(model_instance, self.attname, value)
@@ -1287,7 +1318,7 @@ class DateTimeField(DateField):
1287
1318
  else:
1288
1319
  return super().pre_save(model_instance, add)
1289
1320
 
1290
- def get_prep_value(self, value):
1321
+ def get_prep_value(self, value: Any) -> Any:
1291
1322
  value = super().get_prep_value(value)
1292
1323
  value = self.to_python(value)
1293
1324
  if value is not None and timezone.is_naive(value):
@@ -1307,13 +1338,15 @@ class DateTimeField(DateField):
1307
1338
  value = timezone.make_aware(value, default_timezone)
1308
1339
  return value
1309
1340
 
1310
- def get_db_prep_value(self, value, connection, prepared=False):
1341
+ def get_db_prep_value(
1342
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
1343
+ ) -> Any:
1311
1344
  # Casts datetimes into the format expected by the backend
1312
1345
  if not prepared:
1313
1346
  value = self.get_prep_value(value)
1314
1347
  return connection.ops.adapt_datetimefield_value(value)
1315
1348
 
1316
- def value_to_string(self, obj):
1349
+ def value_to_string(self, obj: Any) -> str:
1317
1350
  val = self.value_from_object(obj)
1318
1351
  return "" if val is None else val.isoformat()
1319
1352
 
@@ -1328,14 +1361,14 @@ class DecimalField(Field):
1328
1361
  def __init__(
1329
1362
  self,
1330
1363
  *,
1331
- max_digits=None,
1332
- decimal_places=None,
1333
- **kwargs,
1364
+ max_digits: int | None = None,
1365
+ decimal_places: int | None = None,
1366
+ **kwargs: Any,
1334
1367
  ):
1335
1368
  self.max_digits, self.decimal_places = max_digits, decimal_places
1336
1369
  super().__init__(**kwargs)
1337
1370
 
1338
- def preflight(self, **kwargs):
1371
+ def preflight(self, **kwargs: Any) -> list[PreflightResult]:
1339
1372
  errors = super().preflight(**kwargs)
1340
1373
 
1341
1374
  digits_errors = [
@@ -1348,7 +1381,7 @@ class DecimalField(Field):
1348
1381
  errors.extend(digits_errors)
1349
1382
  return errors
1350
1383
 
1351
- def _check_decimal_places(self):
1384
+ def _check_decimal_places(self) -> list[PreflightResult]:
1352
1385
  try:
1353
1386
  decimal_places = int(self.decimal_places)
1354
1387
  if decimal_places < 0:
@@ -1372,7 +1405,7 @@ class DecimalField(Field):
1372
1405
  else:
1373
1406
  return []
1374
1407
 
1375
- def _check_max_digits(self):
1408
+ def _check_max_digits(self) -> list[PreflightResult]:
1376
1409
  try:
1377
1410
  max_digits = int(self.max_digits)
1378
1411
  if max_digits <= 0:
@@ -1396,7 +1429,7 @@ class DecimalField(Field):
1396
1429
  else:
1397
1430
  return []
1398
1431
 
1399
- def _check_decimal_places_and_max_digits(self):
1432
+ def _check_decimal_places_and_max_digits(self) -> list[PreflightResult]:
1400
1433
  if int(self.decimal_places) > int(self.max_digits):
1401
1434
  return [
1402
1435
  PreflightResult(
@@ -1408,16 +1441,16 @@ class DecimalField(Field):
1408
1441
  return []
1409
1442
 
1410
1443
  @cached_property
1411
- def validators(self):
1444
+ def validators(self) -> list[Callable[..., Any]]:
1412
1445
  return super().validators + [
1413
1446
  validators.DecimalValidator(self.max_digits, self.decimal_places)
1414
1447
  ]
1415
1448
 
1416
1449
  @cached_property
1417
- def context(self):
1450
+ def context(self) -> decimal.Context:
1418
1451
  return decimal.Context(prec=self.max_digits)
1419
1452
 
1420
- def deconstruct(self):
1453
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
1421
1454
  name, path, args, kwargs = super().deconstruct()
1422
1455
  if self.max_digits is not None:
1423
1456
  kwargs["max_digits"] = self.max_digits
@@ -1425,10 +1458,10 @@ class DecimalField(Field):
1425
1458
  kwargs["decimal_places"] = self.decimal_places
1426
1459
  return name, path, args, kwargs
1427
1460
 
1428
- def get_internal_type(self):
1461
+ def get_internal_type(self) -> str:
1429
1462
  return "DecimalField"
1430
1463
 
1431
- def to_python(self, value):
1464
+ def to_python(self, value: Any) -> Any:
1432
1465
  if value is None:
1433
1466
  return value
1434
1467
  try:
@@ -1450,7 +1483,9 @@ class DecimalField(Field):
1450
1483
  )
1451
1484
  return decimal_value
1452
1485
 
1453
- def get_db_prep_value(self, value, connection, prepared=False):
1486
+ def get_db_prep_value(
1487
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
1488
+ ) -> Any:
1454
1489
  if not prepared:
1455
1490
  value = self.get_prep_value(value)
1456
1491
  if hasattr(value, "as_sql"):
@@ -1459,7 +1494,7 @@ class DecimalField(Field):
1459
1494
  value, self.max_digits, self.decimal_places
1460
1495
  )
1461
1496
 
1462
- def get_prep_value(self, value):
1497
+ def get_prep_value(self, value: Any) -> Any:
1463
1498
  value = super().get_prep_value(value)
1464
1499
  return self.to_python(value)
1465
1500
 
@@ -1478,10 +1513,10 @@ class DurationField(Field):
1478
1513
  }
1479
1514
  description = "Duration"
1480
1515
 
1481
- def get_internal_type(self):
1516
+ def get_internal_type(self) -> str:
1482
1517
  return "DurationField"
1483
1518
 
1484
- def to_python(self, value):
1519
+ def to_python(self, value: Any) -> Any:
1485
1520
  if value is None:
1486
1521
  return value
1487
1522
  if isinstance(value, datetime.timedelta):
@@ -1500,20 +1535,24 @@ class DurationField(Field):
1500
1535
  params={"value": value},
1501
1536
  )
1502
1537
 
1503
- def get_db_prep_value(self, value, connection, prepared=False):
1538
+ def get_db_prep_value(
1539
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
1540
+ ) -> Any:
1504
1541
  if connection.features.has_native_duration_field:
1505
1542
  return value
1506
1543
  if value is None:
1507
1544
  return None
1508
1545
  return duration_microseconds(value)
1509
1546
 
1510
- def get_db_converters(self, connection):
1547
+ def get_db_converters(
1548
+ self, connection: BaseDatabaseWrapper
1549
+ ) -> list[Callable[..., Any]]:
1511
1550
  converters = []
1512
1551
  if not connection.features.has_native_duration_field:
1513
1552
  converters.append(connection.ops.convert_durationfield_value)
1514
1553
  return converters + super().get_db_converters(connection)
1515
1554
 
1516
- def value_to_string(self, obj):
1555
+ def value_to_string(self, obj: Any) -> str:
1517
1556
  val = self.value_from_object(obj)
1518
1557
  return "" if val is None else duration_string(val)
1519
1558
 
@@ -1522,12 +1561,12 @@ class EmailField(CharField):
1522
1561
  default_validators = [validators.validate_email]
1523
1562
  description = "Email address"
1524
1563
 
1525
- def __init__(self, **kwargs):
1564
+ def __init__(self, **kwargs: Any):
1526
1565
  # max_length=254 to be compliant with RFCs 3696 and 5321
1527
1566
  kwargs.setdefault("max_length", 254)
1528
1567
  super().__init__(**kwargs)
1529
1568
 
1530
- def deconstruct(self):
1569
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
1531
1570
  name, path, args, kwargs = super().deconstruct()
1532
1571
  # We do not exclude max_length if it matches default as we want to change
1533
1572
  # the default in future.
@@ -1541,7 +1580,7 @@ class FloatField(Field):
1541
1580
  }
1542
1581
  description = "Floating point number"
1543
1582
 
1544
- def get_prep_value(self, value):
1583
+ def get_prep_value(self, value: Any) -> Any:
1545
1584
  value = super().get_prep_value(value)
1546
1585
  if value is None:
1547
1586
  return None
@@ -1552,10 +1591,10 @@ class FloatField(Field):
1552
1591
  f"Field '{self.name}' expected a number but got {value!r}.",
1553
1592
  ) from e
1554
1593
 
1555
- def get_internal_type(self):
1594
+ def get_internal_type(self) -> str:
1556
1595
  return "FloatField"
1557
1596
 
1558
- def to_python(self, value):
1597
+ def to_python(self, value: Any) -> Any:
1559
1598
  if value is None:
1560
1599
  return value
1561
1600
  try:
@@ -1575,13 +1614,13 @@ class IntegerField(Field):
1575
1614
  }
1576
1615
  description = "Integer"
1577
1616
 
1578
- def preflight(self, **kwargs):
1617
+ def preflight(self, **kwargs: Any) -> list[PreflightResult]:
1579
1618
  return [
1580
1619
  *super().preflight(**kwargs),
1581
1620
  *self._check_max_length_warning(),
1582
1621
  ]
1583
1622
 
1584
- def _check_max_length_warning(self):
1623
+ def _check_max_length_warning(self) -> list[PreflightResult]:
1585
1624
  if self.max_length is not None:
1586
1625
  return [
1587
1626
  PreflightResult(
@@ -1594,7 +1633,7 @@ class IntegerField(Field):
1594
1633
  return []
1595
1634
 
1596
1635
  @cached_property
1597
- def validators(self):
1636
+ def validators(self) -> list[Callable[..., Any]]:
1598
1637
  # These validators can't be added at field initialization time since
1599
1638
  # they're based on values retrieved from the database connection.
1600
1639
  validators_ = super().validators
@@ -1628,7 +1667,7 @@ class IntegerField(Field):
1628
1667
  validators_.append(validators.MaxValueValidator(max_value))
1629
1668
  return validators_
1630
1669
 
1631
- def get_prep_value(self, value):
1670
+ def get_prep_value(self, value: Any) -> Any:
1632
1671
  value = super().get_prep_value(value)
1633
1672
  if value is None:
1634
1673
  return None
@@ -1639,14 +1678,16 @@ class IntegerField(Field):
1639
1678
  f"Field '{self.name}' expected a number but got {value!r}.",
1640
1679
  ) from e
1641
1680
 
1642
- def get_db_prep_value(self, value, connection, prepared=False):
1681
+ def get_db_prep_value(
1682
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
1683
+ ) -> Any:
1643
1684
  value = super().get_db_prep_value(value, connection, prepared)
1644
1685
  return connection.ops.adapt_integerfield_value(value, self.get_internal_type())
1645
1686
 
1646
- def get_internal_type(self):
1687
+ def get_internal_type(self) -> str:
1647
1688
  return "IntegerField"
1648
1689
 
1649
- def to_python(self, value):
1690
+ def to_python(self, value: Any) -> Any:
1650
1691
  if value is None:
1651
1692
  return value
1652
1693
  try:
@@ -1662,14 +1703,14 @@ class IntegerField(Field):
1662
1703
  class BigIntegerField(IntegerField):
1663
1704
  description = "Big (8 byte) integer"
1664
1705
 
1665
- def get_internal_type(self):
1706
+ def get_internal_type(self) -> str:
1666
1707
  return "BigIntegerField"
1667
1708
 
1668
1709
 
1669
1710
  class SmallIntegerField(IntegerField):
1670
1711
  description = "Small integer"
1671
1712
 
1672
- def get_internal_type(self):
1713
+ def get_internal_type(self) -> str:
1673
1714
  return "SmallIntegerField"
1674
1715
 
1675
1716
 
@@ -1681,9 +1722,9 @@ class GenericIPAddressField(Field):
1681
1722
  def __init__(
1682
1723
  self,
1683
1724
  *,
1684
- protocol="both",
1685
- unpack_ipv4=False,
1686
- **kwargs,
1725
+ protocol: str = "both",
1726
+ unpack_ipv4: bool = False,
1727
+ **kwargs: Any,
1687
1728
  ):
1688
1729
  self.unpack_ipv4 = unpack_ipv4
1689
1730
  self.protocol = protocol
@@ -1695,13 +1736,13 @@ class GenericIPAddressField(Field):
1695
1736
  kwargs["max_length"] = 39
1696
1737
  super().__init__(**kwargs)
1697
1738
 
1698
- def preflight(self, **kwargs):
1739
+ def preflight(self, **kwargs: Any) -> list[PreflightResult]:
1699
1740
  return [
1700
1741
  *super().preflight(**kwargs),
1701
1742
  *self._check_required_and_null_values(),
1702
1743
  ]
1703
1744
 
1704
- def _check_required_and_null_values(self):
1745
+ def _check_required_and_null_values(self) -> list[PreflightResult]:
1705
1746
  if not getattr(self, "allow_null", False) and not getattr(
1706
1747
  self, "required", True
1707
1748
  ):
@@ -1715,7 +1756,7 @@ class GenericIPAddressField(Field):
1715
1756
  ]
1716
1757
  return []
1717
1758
 
1718
- def deconstruct(self):
1759
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
1719
1760
  name, path, args, kwargs = super().deconstruct()
1720
1761
  if self.unpack_ipv4 is not False:
1721
1762
  kwargs["unpack_ipv4"] = self.unpack_ipv4
@@ -1725,10 +1766,10 @@ class GenericIPAddressField(Field):
1725
1766
  del kwargs["max_length"]
1726
1767
  return name, path, args, kwargs
1727
1768
 
1728
- def get_internal_type(self):
1769
+ def get_internal_type(self) -> str:
1729
1770
  return "GenericIPAddressField"
1730
1771
 
1731
- def to_python(self, value):
1772
+ def to_python(self, value: Any) -> Any:
1732
1773
  if value is None:
1733
1774
  return None
1734
1775
  if not isinstance(value, str):
@@ -1740,12 +1781,14 @@ class GenericIPAddressField(Field):
1740
1781
  )
1741
1782
  return value
1742
1783
 
1743
- def get_db_prep_value(self, value, connection, prepared=False):
1784
+ def get_db_prep_value(
1785
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
1786
+ ) -> Any:
1744
1787
  if not prepared:
1745
1788
  value = self.get_prep_value(value)
1746
1789
  return connection.ops.adapt_ipaddressfield_value(value)
1747
1790
 
1748
- def get_prep_value(self, value):
1791
+ def get_prep_value(self, value: Any) -> Any:
1749
1792
  value = super().get_prep_value(value)
1750
1793
  if value is None:
1751
1794
  return None
@@ -1758,7 +1801,7 @@ class GenericIPAddressField(Field):
1758
1801
 
1759
1802
 
1760
1803
  class PositiveIntegerRelDbTypeMixin:
1761
- def __init_subclass__(cls, **kwargs):
1804
+ def __init_subclass__(cls, **kwargs: Any) -> None:
1762
1805
  super().__init_subclass__(**kwargs)
1763
1806
  if not hasattr(cls, "integer_field_class"):
1764
1807
  cls.integer_field_class = next(
@@ -1770,7 +1813,7 @@ class PositiveIntegerRelDbTypeMixin:
1770
1813
  None,
1771
1814
  )
1772
1815
 
1773
- def rel_db_type(self, connection):
1816
+ def rel_db_type(self, connection: BaseDatabaseWrapper) -> str | None:
1774
1817
  """
1775
1818
  Return the data type that a related field pointing to this field should
1776
1819
  use. In most cases, a foreign key pointing to a positive integer
@@ -1788,43 +1831,43 @@ class PositiveIntegerRelDbTypeMixin:
1788
1831
  class PositiveBigIntegerField(PositiveIntegerRelDbTypeMixin, BigIntegerField):
1789
1832
  description = "Positive big integer"
1790
1833
 
1791
- def get_internal_type(self):
1834
+ def get_internal_type(self) -> str:
1792
1835
  return "PositiveBigIntegerField"
1793
1836
 
1794
1837
 
1795
1838
  class PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField):
1796
1839
  description = "Positive integer"
1797
1840
 
1798
- def get_internal_type(self):
1841
+ def get_internal_type(self) -> str:
1799
1842
  return "PositiveIntegerField"
1800
1843
 
1801
1844
 
1802
1845
  class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, SmallIntegerField):
1803
1846
  description = "Positive small integer"
1804
1847
 
1805
- def get_internal_type(self):
1848
+ def get_internal_type(self) -> str:
1806
1849
  return "PositiveSmallIntegerField"
1807
1850
 
1808
1851
 
1809
1852
  class TextField(Field):
1810
1853
  description = "Text"
1811
1854
 
1812
- def __init__(self, *, db_collation=None, **kwargs):
1855
+ def __init__(self, *, db_collation: str | None = None, **kwargs: Any):
1813
1856
  super().__init__(**kwargs)
1814
1857
  self.db_collation = db_collation
1815
1858
 
1816
- def preflight(self, **kwargs):
1859
+ def preflight(self, **kwargs: Any) -> list[PreflightResult]:
1817
1860
  return [
1818
1861
  *super().preflight(**kwargs),
1819
1862
  *self._check_db_collation(),
1820
1863
  ]
1821
1864
 
1822
- def _check_db_collation(self):
1865
+ def _check_db_collation(self) -> list[PreflightResult]:
1823
1866
  errors = []
1824
1867
  if not (
1825
1868
  self.db_collation is None
1826
1869
  or "supports_collation_on_textfield"
1827
- in self.model._meta.required_db_features
1870
+ in self.model.model_options.required_db_features
1828
1871
  or db_connection.features.supports_collation_on_textfield
1829
1872
  ):
1830
1873
  errors.append(
@@ -1837,24 +1880,24 @@ class TextField(Field):
1837
1880
  )
1838
1881
  return errors
1839
1882
 
1840
- def db_parameters(self, connection):
1883
+ def db_parameters(self, connection: BaseDatabaseWrapper) -> dict[str, Any]:
1841
1884
  db_params = super().db_parameters(connection)
1842
1885
  db_params["collation"] = self.db_collation
1843
1886
  return db_params
1844
1887
 
1845
- def get_internal_type(self):
1888
+ def get_internal_type(self) -> str:
1846
1889
  return "TextField"
1847
1890
 
1848
- def to_python(self, value):
1891
+ def to_python(self, value: Any) -> Any:
1849
1892
  if isinstance(value, str) or value is None:
1850
1893
  return value
1851
1894
  return str(value)
1852
1895
 
1853
- def get_prep_value(self, value):
1896
+ def get_prep_value(self, value: Any) -> Any:
1854
1897
  value = super().get_prep_value(value)
1855
1898
  return self.to_python(value)
1856
1899
 
1857
- def deconstruct(self):
1900
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
1858
1901
  name, path, args, kwargs = super().deconstruct()
1859
1902
  if self.db_collation:
1860
1903
  kwargs["db_collation"] = self.db_collation
@@ -1869,13 +1912,15 @@ class TimeField(DateTimeCheckMixin, Field):
1869
1912
  }
1870
1913
  description = "Time"
1871
1914
 
1872
- def __init__(self, *, auto_now=False, auto_now_add=False, **kwargs):
1915
+ def __init__(
1916
+ self, *, auto_now: bool = False, auto_now_add: bool = False, **kwargs: Any
1917
+ ):
1873
1918
  self.auto_now, self.auto_now_add = auto_now, auto_now_add
1874
1919
  if auto_now or auto_now_add:
1875
1920
  kwargs["required"] = False
1876
1921
  super().__init__(**kwargs)
1877
1922
 
1878
- def _check_fix_default_value(self):
1923
+ def _check_fix_default_value(self) -> list[PreflightResult]:
1879
1924
  """
1880
1925
  Warn that using an actual date or datetime value is probably wrong;
1881
1926
  it's only evaluated on server startup.
@@ -1897,7 +1942,7 @@ class TimeField(DateTimeCheckMixin, Field):
1897
1942
  # At this point, value is a datetime object.
1898
1943
  return self._check_if_value_fixed(value, now=now)
1899
1944
 
1900
- def deconstruct(self):
1945
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
1901
1946
  name, path, args, kwargs = super().deconstruct()
1902
1947
  if self.auto_now is not False:
1903
1948
  kwargs["auto_now"] = self.auto_now
@@ -1907,10 +1952,10 @@ class TimeField(DateTimeCheckMixin, Field):
1907
1952
  del kwargs["required"]
1908
1953
  return name, path, args, kwargs
1909
1954
 
1910
- def get_internal_type(self):
1955
+ def get_internal_type(self) -> str:
1911
1956
  return "TimeField"
1912
1957
 
1913
- def to_python(self, value):
1958
+ def to_python(self, value: Any) -> Any:
1914
1959
  if value is None:
1915
1960
  return None
1916
1961
  if isinstance(value, datetime.time):
@@ -1938,7 +1983,7 @@ class TimeField(DateTimeCheckMixin, Field):
1938
1983
  params={"value": value},
1939
1984
  )
1940
1985
 
1941
- def pre_save(self, model_instance, add):
1986
+ def pre_save(self, model_instance: Any, add: bool) -> Any:
1942
1987
  if self.auto_now or (self.auto_now_add and add):
1943
1988
  value = datetime.datetime.now().time()
1944
1989
  setattr(model_instance, self.attname, value)
@@ -1946,17 +1991,19 @@ class TimeField(DateTimeCheckMixin, Field):
1946
1991
  else:
1947
1992
  return super().pre_save(model_instance, add)
1948
1993
 
1949
- def get_prep_value(self, value):
1994
+ def get_prep_value(self, value: Any) -> Any:
1950
1995
  value = super().get_prep_value(value)
1951
1996
  return self.to_python(value)
1952
1997
 
1953
- def get_db_prep_value(self, value, connection, prepared=False):
1998
+ def get_db_prep_value(
1999
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
2000
+ ) -> Any:
1954
2001
  # Casts times into the format expected by the backend
1955
2002
  if not prepared:
1956
2003
  value = self.get_prep_value(value)
1957
2004
  return connection.ops.adapt_timefield_value(value)
1958
2005
 
1959
- def value_to_string(self, obj):
2006
+ def value_to_string(self, obj: Any) -> str:
1960
2007
  val = self.value_from_object(obj)
1961
2008
  return "" if val is None else val.isoformat()
1962
2009
 
@@ -1965,11 +2012,11 @@ class URLField(CharField):
1965
2012
  default_validators = [validators.URLValidator()]
1966
2013
  description = "URL"
1967
2014
 
1968
- def __init__(self, **kwargs):
2015
+ def __init__(self, **kwargs: Any):
1969
2016
  kwargs.setdefault("max_length", 200)
1970
2017
  super().__init__(**kwargs)
1971
2018
 
1972
- def deconstruct(self):
2019
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
1973
2020
  name, path, args, kwargs = super().deconstruct()
1974
2021
  if kwargs.get("max_length") == 200:
1975
2022
  del kwargs["max_length"]
@@ -1980,15 +2027,15 @@ class BinaryField(Field):
1980
2027
  description = "Raw binary data"
1981
2028
  empty_values = [None, b""]
1982
2029
 
1983
- def __init__(self, **kwargs):
2030
+ def __init__(self, **kwargs: Any):
1984
2031
  super().__init__(**kwargs)
1985
2032
  if self.max_length is not None:
1986
2033
  self.validators.append(validators.MaxLengthValidator(self.max_length))
1987
2034
 
1988
- def preflight(self, **kwargs):
2035
+ def preflight(self, **kwargs: Any) -> list[PreflightResult]:
1989
2036
  return [*super().preflight(**kwargs), *self._check_str_default_value()]
1990
2037
 
1991
- def _check_str_default_value(self):
2038
+ def _check_str_default_value(self) -> list[PreflightResult]:
1992
2039
  if self.has_default() and isinstance(self.default, str):
1993
2040
  return [
1994
2041
  PreflightResult(
@@ -2000,13 +2047,15 @@ class BinaryField(Field):
2000
2047
  ]
2001
2048
  return []
2002
2049
 
2003
- def get_internal_type(self):
2050
+ def get_internal_type(self) -> str:
2004
2051
  return "BinaryField"
2005
2052
 
2006
- def get_placeholder(self, value, compiler, connection):
2053
+ def get_placeholder(
2054
+ self, value: Any, compiler: SQLCompiler, connection: BaseDatabaseWrapper
2055
+ ) -> Any:
2007
2056
  return connection.ops.binary_placeholder_sql(value)
2008
2057
 
2009
- def get_default(self):
2058
+ def get_default(self) -> Any:
2010
2059
  if self.has_default() and not callable(self.default):
2011
2060
  return self.default
2012
2061
  default = super().get_default()
@@ -2014,17 +2063,19 @@ class BinaryField(Field):
2014
2063
  return b""
2015
2064
  return default
2016
2065
 
2017
- def get_db_prep_value(self, value, connection, prepared=False):
2066
+ def get_db_prep_value(
2067
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
2068
+ ) -> Any:
2018
2069
  value = super().get_db_prep_value(value, connection, prepared)
2019
2070
  if value is not None:
2020
- return connection.Database.Binary(value)
2071
+ return connection.Database.Binary(value) # type: ignore[attr-defined]
2021
2072
  return value
2022
2073
 
2023
- def value_to_string(self, obj):
2074
+ def value_to_string(self, obj: Any) -> str:
2024
2075
  """Binary data is serialized as base64"""
2025
2076
  return b64encode(self.value_from_object(obj)).decode("ascii")
2026
2077
 
2027
- def to_python(self, value):
2078
+ def to_python(self, value: Any) -> Any:
2028
2079
  # If it's a string, it should be base64-encoded data
2029
2080
  if isinstance(value, str):
2030
2081
  return memoryview(b64decode(value.encode("ascii")))
@@ -2038,23 +2089,25 @@ class UUIDField(Field):
2038
2089
  description = "Universally unique identifier"
2039
2090
  empty_strings_allowed = False
2040
2091
 
2041
- def __init__(self, **kwargs):
2092
+ def __init__(self, **kwargs: Any):
2042
2093
  kwargs["max_length"] = 32
2043
2094
  super().__init__(**kwargs)
2044
2095
 
2045
- def deconstruct(self):
2096
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
2046
2097
  name, path, args, kwargs = super().deconstruct()
2047
2098
  del kwargs["max_length"]
2048
2099
  return name, path, args, kwargs
2049
2100
 
2050
- def get_internal_type(self):
2101
+ def get_internal_type(self) -> str:
2051
2102
  return "UUIDField"
2052
2103
 
2053
- def get_prep_value(self, value):
2104
+ def get_prep_value(self, value: Any) -> Any:
2054
2105
  value = super().get_prep_value(value)
2055
2106
  return self.to_python(value)
2056
2107
 
2057
- def get_db_prep_value(self, value, connection, prepared=False):
2108
+ def get_db_prep_value(
2109
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
2110
+ ) -> Any:
2058
2111
  if value is None:
2059
2112
  return None
2060
2113
  if not isinstance(value, uuid.UUID):
@@ -2064,7 +2117,7 @@ class UUIDField(Field):
2064
2117
  return value
2065
2118
  return value.hex
2066
2119
 
2067
- def to_python(self, value):
2120
+ def to_python(self, value: Any) -> Any:
2068
2121
  if value is not None and not isinstance(value, uuid.UUID):
2069
2122
  input_form = "int" if isinstance(value, int) else "hex"
2070
2123
  try:
@@ -2091,27 +2144,29 @@ class PrimaryKeyField(BigIntegerField):
2091
2144
  self.creation_counter = Field.auto_creation_counter
2092
2145
  Field.auto_creation_counter -= 1
2093
2146
 
2094
- def preflight(self, **kwargs):
2147
+ def preflight(self, **kwargs: Any) -> list[PreflightResult]:
2095
2148
  errors = super().preflight(**kwargs)
2096
2149
  # Remove the reserved_field_name_id error for 'id' field name since PrimaryKeyField is allowed to use it
2097
2150
  errors = [e for e in errors if e.id != "fields.reserved_field_name_id"]
2098
2151
  return errors
2099
2152
 
2100
- def deconstruct(self):
2153
+ def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
2101
2154
  # PrimaryKeyField takes no parameters, so we return an empty kwargs dict
2102
2155
  return (self.name, "plain.models.PrimaryKeyField", [], {})
2103
2156
 
2104
- def validate(self, value, model_instance):
2157
+ def validate(self, value: Any, model_instance: Any) -> None:
2105
2158
  pass
2106
2159
 
2107
- def get_db_prep_value(self, value, connection, prepared=False):
2160
+ def get_db_prep_value(
2161
+ self, value: Any, connection: BaseDatabaseWrapper, prepared: bool = False
2162
+ ) -> Any:
2108
2163
  if not prepared:
2109
2164
  value = self.get_prep_value(value)
2110
2165
  value = connection.ops.validate_autopk_value(value)
2111
2166
  return value
2112
2167
 
2113
- def get_internal_type(self):
2168
+ def get_internal_type(self) -> str:
2114
2169
  return "PrimaryKeyField"
2115
2170
 
2116
- def rel_db_type(self, connection):
2171
+ def rel_db_type(self, connection: BaseDatabaseWrapper) -> str | None:
2117
2172
  return BigIntegerField().db_type(connection=connection)