plain.models 0.49.1__py3-none-any.whl → 0.50.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 (105) hide show
  1. plain/models/CHANGELOG.md +23 -0
  2. plain/models/aggregates.py +42 -19
  3. plain/models/backends/base/base.py +125 -105
  4. plain/models/backends/base/client.py +11 -3
  5. plain/models/backends/base/creation.py +22 -12
  6. plain/models/backends/base/features.py +10 -4
  7. plain/models/backends/base/introspection.py +29 -16
  8. plain/models/backends/base/operations.py +187 -91
  9. plain/models/backends/base/schema.py +267 -165
  10. plain/models/backends/base/validation.py +12 -3
  11. plain/models/backends/ddl_references.py +85 -43
  12. plain/models/backends/mysql/base.py +29 -26
  13. plain/models/backends/mysql/client.py +7 -2
  14. plain/models/backends/mysql/compiler.py +12 -3
  15. plain/models/backends/mysql/creation.py +5 -2
  16. plain/models/backends/mysql/features.py +24 -22
  17. plain/models/backends/mysql/introspection.py +22 -13
  18. plain/models/backends/mysql/operations.py +106 -39
  19. plain/models/backends/mysql/schema.py +48 -24
  20. plain/models/backends/mysql/validation.py +13 -6
  21. plain/models/backends/postgresql/base.py +41 -34
  22. plain/models/backends/postgresql/client.py +7 -2
  23. plain/models/backends/postgresql/creation.py +10 -5
  24. plain/models/backends/postgresql/introspection.py +15 -8
  25. plain/models/backends/postgresql/operations.py +109 -42
  26. plain/models/backends/postgresql/schema.py +85 -46
  27. plain/models/backends/sqlite3/_functions.py +151 -115
  28. plain/models/backends/sqlite3/base.py +37 -23
  29. plain/models/backends/sqlite3/client.py +7 -1
  30. plain/models/backends/sqlite3/creation.py +9 -5
  31. plain/models/backends/sqlite3/features.py +5 -3
  32. plain/models/backends/sqlite3/introspection.py +32 -16
  33. plain/models/backends/sqlite3/operations.py +125 -42
  34. plain/models/backends/sqlite3/schema.py +82 -58
  35. plain/models/backends/utils.py +52 -29
  36. plain/models/backups/cli.py +8 -6
  37. plain/models/backups/clients.py +16 -7
  38. plain/models/backups/core.py +24 -13
  39. plain/models/base.py +113 -74
  40. plain/models/cli.py +94 -63
  41. plain/models/config.py +1 -1
  42. plain/models/connections.py +23 -7
  43. plain/models/constraints.py +65 -47
  44. plain/models/database_url.py +1 -1
  45. plain/models/db.py +6 -2
  46. plain/models/deletion.py +66 -43
  47. plain/models/entrypoints.py +1 -1
  48. plain/models/enums.py +22 -11
  49. plain/models/exceptions.py +23 -8
  50. plain/models/expressions.py +440 -257
  51. plain/models/fields/__init__.py +253 -202
  52. plain/models/fields/json.py +120 -54
  53. plain/models/fields/mixins.py +12 -8
  54. plain/models/fields/related.py +284 -252
  55. plain/models/fields/related_descriptors.py +34 -25
  56. plain/models/fields/related_lookups.py +23 -11
  57. plain/models/fields/related_managers.py +81 -47
  58. plain/models/fields/reverse_related.py +58 -55
  59. plain/models/forms.py +89 -63
  60. plain/models/functions/comparison.py +71 -18
  61. plain/models/functions/datetime.py +79 -29
  62. plain/models/functions/math.py +43 -10
  63. plain/models/functions/mixins.py +24 -7
  64. plain/models/functions/text.py +104 -25
  65. plain/models/functions/window.py +12 -6
  66. plain/models/indexes.py +52 -28
  67. plain/models/lookups.py +228 -153
  68. plain/models/migrations/autodetector.py +86 -43
  69. plain/models/migrations/exceptions.py +7 -3
  70. plain/models/migrations/executor.py +33 -7
  71. plain/models/migrations/graph.py +79 -50
  72. plain/models/migrations/loader.py +45 -22
  73. plain/models/migrations/migration.py +23 -18
  74. plain/models/migrations/operations/base.py +37 -19
  75. plain/models/migrations/operations/fields.py +89 -42
  76. plain/models/migrations/operations/models.py +245 -143
  77. plain/models/migrations/operations/special.py +82 -25
  78. plain/models/migrations/optimizer.py +7 -2
  79. plain/models/migrations/questioner.py +58 -31
  80. plain/models/migrations/recorder.py +18 -11
  81. plain/models/migrations/serializer.py +50 -39
  82. plain/models/migrations/state.py +220 -133
  83. plain/models/migrations/utils.py +29 -13
  84. plain/models/migrations/writer.py +17 -14
  85. plain/models/options.py +63 -56
  86. plain/models/otel.py +16 -6
  87. plain/models/preflight.py +35 -12
  88. plain/models/query.py +323 -228
  89. plain/models/query_utils.py +93 -58
  90. plain/models/registry.py +34 -16
  91. plain/models/sql/compiler.py +146 -97
  92. plain/models/sql/datastructures.py +38 -25
  93. plain/models/sql/query.py +255 -169
  94. plain/models/sql/subqueries.py +32 -21
  95. plain/models/sql/where.py +54 -29
  96. plain/models/test/pytest.py +15 -11
  97. plain/models/test/utils.py +4 -2
  98. plain/models/transaction.py +20 -7
  99. plain/models/utils.py +13 -5
  100. {plain_models-0.49.1.dist-info → plain_models-0.50.0.dist-info}/METADATA +1 -1
  101. plain_models-0.50.0.dist-info/RECORD +122 -0
  102. plain_models-0.49.1.dist-info/RECORD +0 -122
  103. {plain_models-0.49.1.dist-info → plain_models-0.50.0.dist-info}/WHEEL +0 -0
  104. {plain_models-0.49.1.dist-info → plain_models-0.50.0.dist-info}/entry_points.txt +0 -0
  105. {plain_models-0.49.1.dist-info → plain_models-0.50.0.dist-info}/licenses/LICENSE +0 -0
plain/models/base.py CHANGED
@@ -1,7 +1,11 @@
1
+ from __future__ import annotations
2
+
1
3
  import copy
2
4
  import inspect
3
5
  import warnings
6
+ from collections.abc import Iterable, Iterator, Sequence
4
7
  from itertools import chain
8
+ from typing import Any
5
9
 
6
10
  import plain.runtime
7
11
  from plain.exceptions import NON_FIELD_ERRORS, ValidationError
@@ -31,10 +35,10 @@ from plain.utils.hashable import make_hashable
31
35
 
32
36
 
33
37
  class Deferred:
34
- def __repr__(self):
38
+ def __repr__(self) -> str:
35
39
  return "<Deferred field>"
36
40
 
37
- def __str__(self):
41
+ def __str__(self) -> str:
38
42
  return "<Deferred field>"
39
43
 
40
44
 
@@ -44,7 +48,9 @@ DEFERRED = Deferred()
44
48
  class ModelBase(type):
45
49
  """Metaclass for all models."""
46
50
 
47
- def __new__(cls, name, bases, attrs, **kwargs):
51
+ def __new__(
52
+ cls, name: str, bases: tuple[type, ...], attrs: dict[str, Any], **kwargs: Any
53
+ ) -> type:
48
54
  # Don't do any of this for the root models.Model class.
49
55
  if not bases:
50
56
  return super().__new__(cls, name, bases, attrs)
@@ -93,7 +99,7 @@ class ModelBase(type):
93
99
 
94
100
  return new_class
95
101
 
96
- def _setup_meta(cls):
102
+ def _setup_meta(cls) -> None:
97
103
  name = cls.__name__
98
104
  module = cls.__module__
99
105
 
@@ -123,7 +129,9 @@ class ModelBase(type):
123
129
 
124
130
 
125
131
  class ModelStateFieldsCacheDescriptor:
126
- def __get__(self, instance, cls=None):
132
+ def __get__(
133
+ self, instance: ModelState | None, cls: type | None = None
134
+ ) -> ModelStateFieldsCacheDescriptor | dict[str, Any]:
127
135
  if instance is None:
128
136
  return self
129
137
  res = instance.fields_cache = {}
@@ -151,7 +159,7 @@ class Model(metaclass=ModelBase):
151
159
  # Every model gets an automatic id field
152
160
  id = PrimaryKeyField()
153
161
 
154
- def __init__(self, *args, **kwargs):
162
+ def __init__(self, *args: Any, **kwargs: Any):
155
163
  # Alias some things as locals to avoid repeat global lookups
156
164
  cls = self.__class__
157
165
  opts = self._meta
@@ -261,7 +269,7 @@ class Model(metaclass=ModelBase):
261
269
  super().__init__()
262
270
 
263
271
  @classmethod
264
- def from_db(cls, field_names, values):
272
+ def from_db(cls, field_names: Iterable[str], values: Sequence[Any]) -> Model:
265
273
  if len(values) != len(cls._meta.concrete_fields):
266
274
  values_iter = iter(values)
267
275
  values = [
@@ -272,13 +280,13 @@ class Model(metaclass=ModelBase):
272
280
  new._state.adding = False
273
281
  return new
274
282
 
275
- def __repr__(self):
283
+ def __repr__(self) -> str:
276
284
  return f"<{self.__class__.__name__}: {self}>"
277
285
 
278
- def __str__(self):
286
+ def __str__(self) -> str:
279
287
  return f"{self.__class__.__name__} object ({self.id})"
280
288
 
281
- def __eq__(self, other):
289
+ def __eq__(self, other: object) -> bool:
282
290
  if not isinstance(other, Model):
283
291
  return NotImplemented
284
292
  if self.__class__ != other.__class__:
@@ -288,18 +296,18 @@ class Model(metaclass=ModelBase):
288
296
  return self is other
289
297
  return my_id == other.id
290
298
 
291
- def __hash__(self):
299
+ def __hash__(self) -> int:
292
300
  if self.id is None:
293
301
  raise TypeError("Model instances without primary key value are unhashable")
294
302
  return hash(self.id)
295
303
 
296
- def __reduce__(self):
304
+ def __reduce__(self) -> tuple[Any, tuple[Any, ...], dict[str, Any]]:
297
305
  data = self.__getstate__()
298
306
  data[PLAIN_VERSION_PICKLE_KEY] = plain.runtime.__version__
299
307
  class_id = self._meta.package_label, self._meta.object_name
300
308
  return model_unpickle, (class_id,), data
301
309
 
302
- def __getstate__(self):
310
+ def __getstate__(self) -> dict[str, Any]:
303
311
  """Hook to allow choosing the attributes to pickle."""
304
312
  state = self.__dict__.copy()
305
313
  state["_state"] = copy.copy(state["_state"])
@@ -316,7 +324,7 @@ class Model(metaclass=ModelBase):
316
324
  state.pop(attr)
317
325
  return state
318
326
 
319
- def __setstate__(self, state):
327
+ def __setstate__(self, state: dict[str, Any]) -> None:
320
328
  pickled_version = state.get(PLAIN_VERSION_PICKLE_KEY)
321
329
  if pickled_version:
322
330
  if pickled_version != plain.runtime.__version__:
@@ -337,7 +345,7 @@ class Model(metaclass=ModelBase):
337
345
  state[attr] = memoryview(value)
338
346
  self.__dict__.update(state)
339
347
 
340
- def get_deferred_fields(self):
348
+ def get_deferred_fields(self) -> set[str]:
341
349
  """
342
350
  Return a set containing names of deferred fields for this instance.
343
351
  """
@@ -347,7 +355,7 @@ class Model(metaclass=ModelBase):
347
355
  if f.attname not in self.__dict__
348
356
  }
349
357
 
350
- def refresh_from_db(self, fields=None):
358
+ def refresh_from_db(self, fields: list[str] | None = None) -> None:
351
359
  """
352
360
  Reload field values from the database.
353
361
 
@@ -368,7 +376,7 @@ class Model(metaclass=ModelBase):
368
376
  prefetched_objects_cache = getattr(self, "_prefetched_objects_cache", ())
369
377
  for field in fields:
370
378
  if field in prefetched_objects_cache:
371
- del prefetched_objects_cache[field]
379
+ del prefetched_objects_cache[field] # type: ignore[misc]
372
380
  fields.remove(field)
373
381
  if not fields:
374
382
  return
@@ -409,7 +417,7 @@ class Model(metaclass=ModelBase):
409
417
  if field.is_cached(self):
410
418
  field.delete_cached_value(self)
411
419
 
412
- def serializable_value(self, field_name):
420
+ def serializable_value(self, field_name: str) -> Any:
413
421
  """
414
422
  Return the value of the field name for this instance. If the field is
415
423
  a foreign key, return the id value instead of the object. If there's
@@ -429,11 +437,11 @@ class Model(metaclass=ModelBase):
429
437
  def save(
430
438
  self,
431
439
  *,
432
- clean_and_validate=True,
433
- force_insert=False,
434
- force_update=False,
435
- update_fields=None,
436
- ):
440
+ clean_and_validate: bool = True,
441
+ force_insert: bool = False,
442
+ force_update: bool = False,
443
+ update_fields: Iterable[str] | None = None,
444
+ ) -> None:
437
445
  """
438
446
  Save the current instance. Override this in a subclass if you want to
439
447
  control the saving process.
@@ -490,11 +498,11 @@ class Model(metaclass=ModelBase):
490
498
  def save_base(
491
499
  self,
492
500
  *,
493
- raw=False,
494
- force_insert=False,
495
- force_update=False,
496
- update_fields=None,
497
- ):
501
+ raw: bool = False,
502
+ force_insert: bool = False,
503
+ force_update: bool = False,
504
+ update_fields: Iterable[str] | None = None,
505
+ ) -> None:
498
506
  """
499
507
  Handle the parts of saving which should be done only once per save,
500
508
  yet need to be done in raw saves, too. This includes some sanity
@@ -521,17 +529,17 @@ class Model(metaclass=ModelBase):
521
529
 
522
530
  def _save_table(
523
531
  self,
524
- raw=False,
525
- cls=None,
526
- force_insert=False,
527
- force_update=False,
528
- update_fields=None,
529
- ):
532
+ raw: bool = False,
533
+ cls: type[Model] | None = None,
534
+ force_insert: bool = False,
535
+ force_update: bool = False,
536
+ update_fields: Iterable[str] | None = None,
537
+ ) -> bool:
530
538
  """
531
539
  Do the heavy-lifting involved in saving. Update or insert the data
532
540
  for a single table.
533
541
  """
534
- meta = cls._meta
542
+ meta = cls._meta # type: ignore[union-attr]
535
543
  non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
536
544
 
537
545
  if update_fields:
@@ -591,7 +599,14 @@ class Model(metaclass=ModelBase):
591
599
  setattr(self, field.attname, value)
592
600
  return updated
593
601
 
594
- def _do_update(self, base_qs, id_val, values, update_fields, forced_update):
602
+ def _do_update(
603
+ self,
604
+ base_qs: QuerySet,
605
+ id_val: Any,
606
+ values: list[tuple[Any, Any, Any]],
607
+ update_fields: Iterable[str] | None,
608
+ forced_update: bool,
609
+ ) -> bool:
595
610
  """
596
611
  Try to update the model. Return True if the model was updated (if an
597
612
  update query was done and a matching row was found in the DB).
@@ -606,19 +621,27 @@ class Model(metaclass=ModelBase):
606
621
  return update_fields is not None or filtered.exists()
607
622
  return filtered._update(values) > 0
608
623
 
609
- def _do_insert(self, manager, fields, returning_fields, raw):
624
+ def _do_insert(
625
+ self,
626
+ manager: QuerySet,
627
+ fields: Sequence[Any],
628
+ returning_fields: Sequence[Any],
629
+ raw: bool,
630
+ ) -> list[Any]:
610
631
  """
611
632
  Do an INSERT. If returning_fields is defined then this method should
612
633
  return the newly created data for the model.
613
634
  """
614
- return manager._insert(
635
+ return manager._insert( # type: ignore[return-value, arg-type]
615
636
  [self],
616
- fields=fields,
617
- returning_fields=returning_fields,
637
+ fields=fields, # type: ignore[arg-type]
638
+ returning_fields=returning_fields, # type: ignore[arg-type]
618
639
  raw=raw,
619
640
  )
620
641
 
621
- def _prepare_related_fields_for_save(self, operation_name, fields=None):
642
+ def _prepare_related_fields_for_save(
643
+ self, operation_name: str, fields: Sequence[Any] | None = None
644
+ ) -> None:
622
645
  # Ensure that a model instance without a PK hasn't been assigned to
623
646
  # a ForeignKey on this model. If the field is nullable, allowing the save would result in silent data loss.
624
647
  for field in self._meta.concrete_fields:
@@ -655,7 +678,7 @@ class Model(metaclass=ModelBase):
655
678
  ):
656
679
  field.delete_cached_value(self)
657
680
 
658
- def delete(self):
681
+ def delete(self) -> tuple[int, dict[str, int]]:
659
682
  if self.id is None:
660
683
  raise ValueError(
661
684
  f"{self._meta.object_name} object can't be deleted because its id attribute is set "
@@ -681,7 +704,9 @@ class Model(metaclass=ModelBase):
681
704
  choices_dict.get(make_hashable(value), value), strings_only=True
682
705
  )
683
706
 
684
- def _get_field_value_map(self, meta, exclude=None):
707
+ def _get_field_value_map(
708
+ self, meta: Options | None, exclude: set[str] | None = None
709
+ ) -> dict[str, Value]:
685
710
  if exclude is None:
686
711
  exclude = set()
687
712
  meta = meta or self._meta
@@ -691,14 +716,14 @@ class Model(metaclass=ModelBase):
691
716
  if field.name not in exclude
692
717
  }
693
718
 
694
- def prepare_database_save(self, field):
719
+ def prepare_database_save(self, field: Any) -> Any:
695
720
  if self.id is None:
696
721
  raise ValueError(
697
722
  f"Unsaved model instance {self!r} cannot be used in an ORM query."
698
723
  )
699
724
  return getattr(self, field.remote_field.get_related_field().attname)
700
725
 
701
- def clean(self):
726
+ def clean(self) -> None:
702
727
  """
703
728
  Hook for doing any extra model-wide validation after clean() has been
704
729
  called on every field by self.clean_fields. Any ValidationError raised
@@ -707,7 +732,7 @@ class Model(metaclass=ModelBase):
707
732
  """
708
733
  pass
709
734
 
710
- def validate_unique(self, exclude=None):
735
+ def validate_unique(self, exclude: set[str] | None = None) -> None:
711
736
  """
712
737
  Check unique constraints on the model and raise ValidationError if any
713
738
  failed.
@@ -717,7 +742,9 @@ class Model(metaclass=ModelBase):
717
742
  if errors := self._perform_unique_checks(unique_checks):
718
743
  raise ValidationError(errors)
719
744
 
720
- def _get_unique_checks(self, exclude=None):
745
+ def _get_unique_checks(
746
+ self, exclude: set[str] | None = None
747
+ ) -> list[tuple[type, tuple[str, ...]]]:
721
748
  """
722
749
  Return a list of checks to perform. Since validate_unique() could be
723
750
  called from a ModelForm, some fields may have been excluded; we can't
@@ -744,7 +771,9 @@ class Model(metaclass=ModelBase):
744
771
 
745
772
  return unique_checks
746
773
 
747
- def _perform_unique_checks(self, unique_checks):
774
+ def _perform_unique_checks(
775
+ self, unique_checks: list[tuple[type, tuple[str, ...]]]
776
+ ) -> dict[str, list[ValidationError]]:
748
777
  errors = {}
749
778
 
750
779
  for model_class, unique_check in unique_checks:
@@ -768,7 +797,7 @@ class Model(metaclass=ModelBase):
768
797
  if len(unique_check) != len(lookup_kwargs):
769
798
  continue
770
799
 
771
- qs = model_class.query.filter(**lookup_kwargs)
800
+ qs = model_class.query.filter(**lookup_kwargs) # type: ignore[attr-defined]
772
801
 
773
802
  # Exclude the current object from the query if we are editing an
774
803
  # instance (as opposed to creating a new one)
@@ -788,8 +817,10 @@ class Model(metaclass=ModelBase):
788
817
 
789
818
  return errors
790
819
 
791
- def unique_error_message(self, model_class, unique_check):
792
- opts = model_class._meta
820
+ def unique_error_message(
821
+ self, model_class: type, unique_check: tuple[str, ...]
822
+ ) -> ValidationError:
823
+ opts = model_class._meta # type: ignore[attr-defined]
793
824
 
794
825
  params = {
795
826
  "model": self,
@@ -828,11 +859,11 @@ class Model(metaclass=ModelBase):
828
859
  params=params,
829
860
  )
830
861
 
831
- def get_constraints(self):
862
+ def get_constraints(self) -> list[tuple[type, list[Any]]]:
832
863
  constraints = [(self.__class__, self._meta.constraints)]
833
864
  return constraints
834
865
 
835
- def validate_constraints(self, exclude=None):
866
+ def validate_constraints(self, exclude: set[str] | None = None) -> None:
836
867
  constraints = self.get_constraints()
837
868
 
838
869
  errors = {}
@@ -852,8 +883,12 @@ class Model(metaclass=ModelBase):
852
883
  raise ValidationError(errors)
853
884
 
854
885
  def full_clean(
855
- self, *, exclude=None, validate_unique=True, validate_constraints=True
856
- ):
886
+ self,
887
+ *,
888
+ exclude: set[str] | Iterable[str] | None = None,
889
+ validate_unique: bool = True,
890
+ validate_constraints: bool = True,
891
+ ) -> None:
857
892
  """
858
893
  Call clean_fields(), clean(), validate_unique(), and
859
894
  validate_constraints() on the model. Raise a ValidationError for any
@@ -900,7 +935,7 @@ class Model(metaclass=ModelBase):
900
935
  if errors:
901
936
  raise ValidationError(errors)
902
937
 
903
- def clean_fields(self, exclude=None):
938
+ def clean_fields(self, exclude: set[str] | None = None) -> None:
904
939
  """
905
940
  Clean all fields and raise a ValidationError containing a dict
906
941
  of all validation errors if any occur.
@@ -926,7 +961,7 @@ class Model(metaclass=ModelBase):
926
961
  raise ValidationError(errors)
927
962
 
928
963
  @classmethod
929
- def preflight(cls):
964
+ def preflight(cls) -> list[PreflightResult]:
930
965
  errors = []
931
966
 
932
967
  errors += [
@@ -956,7 +991,7 @@ class Model(metaclass=ModelBase):
956
991
  return errors
957
992
 
958
993
  @classmethod
959
- def _check_db_table_comment(cls):
994
+ def _check_db_table_comment(cls) -> list[PreflightResult]:
960
995
  if not cls._meta.db_table_comment:
961
996
  return []
962
997
  errors = []
@@ -976,7 +1011,7 @@ class Model(metaclass=ModelBase):
976
1011
  return errors
977
1012
 
978
1013
  @classmethod
979
- def _check_fields(cls):
1014
+ def _check_fields(cls) -> list[PreflightResult]:
980
1015
  """Perform all field checks."""
981
1016
  errors = []
982
1017
  for field in cls._meta.local_fields:
@@ -986,7 +1021,7 @@ class Model(metaclass=ModelBase):
986
1021
  return errors
987
1022
 
988
1023
  @classmethod
989
- def _check_m2m_through_same_relationship(cls):
1024
+ def _check_m2m_through_same_relationship(cls) -> list[PreflightResult]:
990
1025
  """Check if no relationship model is used by more than one m2m field."""
991
1026
 
992
1027
  errors = []
@@ -1021,7 +1056,7 @@ class Model(metaclass=ModelBase):
1021
1056
  return errors
1022
1057
 
1023
1058
  @classmethod
1024
- def _check_id_field(cls):
1059
+ def _check_id_field(cls) -> list[PreflightResult]:
1025
1060
  """Disallow user-defined fields named ``id``."""
1026
1061
  if any(
1027
1062
  f for f in cls._meta.local_fields if f.name == "id" and not f.auto_created
@@ -1036,7 +1071,7 @@ class Model(metaclass=ModelBase):
1036
1071
  return []
1037
1072
 
1038
1073
  @classmethod
1039
- def _check_field_name_clashes(cls):
1074
+ def _check_field_name_clashes(cls) -> list[PreflightResult]:
1040
1075
  """Forbid field shadowing in multi-table inheritance."""
1041
1076
  errors = []
1042
1077
  used_fields = {} # name or attname -> field
@@ -1065,7 +1100,7 @@ class Model(metaclass=ModelBase):
1065
1100
  return errors
1066
1101
 
1067
1102
  @classmethod
1068
- def _check_column_name_clashes(cls):
1103
+ def _check_column_name_clashes(cls) -> list[PreflightResult]:
1069
1104
  # Store a list of column names which have already been used by other fields.
1070
1105
  used_column_names = []
1071
1106
  errors = []
@@ -1089,7 +1124,7 @@ class Model(metaclass=ModelBase):
1089
1124
  return errors
1090
1125
 
1091
1126
  @classmethod
1092
- def _check_model_name_db_lookup_clashes(cls):
1127
+ def _check_model_name_db_lookup_clashes(cls) -> list[PreflightResult]:
1093
1128
  errors = []
1094
1129
  model_name = cls.__name__
1095
1130
  if model_name.startswith("_") or model_name.endswith("_"):
@@ -1113,7 +1148,9 @@ class Model(metaclass=ModelBase):
1113
1148
  return errors
1114
1149
 
1115
1150
  @classmethod
1116
- def _check_property_name_related_field_accessor_clashes(cls):
1151
+ def _check_property_name_related_field_accessor_clashes(
1152
+ cls,
1153
+ ) -> list[PreflightResult]:
1117
1154
  errors = []
1118
1155
  property_names = cls._meta._property_names
1119
1156
  related_field_accessors = (
@@ -1134,7 +1171,7 @@ class Model(metaclass=ModelBase):
1134
1171
  return errors
1135
1172
 
1136
1173
  @classmethod
1137
- def _check_single_primary_key(cls):
1174
+ def _check_single_primary_key(cls) -> list[PreflightResult]:
1138
1175
  errors = []
1139
1176
  if sum(1 for f in cls._meta.local_fields if f.primary_key) > 1:
1140
1177
  errors.append(
@@ -1148,7 +1185,7 @@ class Model(metaclass=ModelBase):
1148
1185
  return errors
1149
1186
 
1150
1187
  @classmethod
1151
- def _check_indexes(cls):
1188
+ def _check_indexes(cls) -> list[PreflightResult]:
1152
1189
  """Check fields, names, and conditions of indexes."""
1153
1190
  errors = []
1154
1191
  references = set()
@@ -1229,7 +1266,9 @@ class Model(metaclass=ModelBase):
1229
1266
  return errors
1230
1267
 
1231
1268
  @classmethod
1232
- def _check_local_fields(cls, fields, option):
1269
+ def _check_local_fields(
1270
+ cls, fields: Iterable[str], option: str
1271
+ ) -> list[PreflightResult]:
1233
1272
  from plain import models
1234
1273
 
1235
1274
  # In order to avoid hitting the relation tree prematurely, we use our
@@ -1274,7 +1313,7 @@ class Model(metaclass=ModelBase):
1274
1313
  return errors
1275
1314
 
1276
1315
  @classmethod
1277
- def _check_ordering(cls):
1316
+ def _check_ordering(cls) -> list[PreflightResult]:
1278
1317
  """
1279
1318
  Check "ordering" option -- is it a list of strings and do all fields
1280
1319
  exist?
@@ -1365,7 +1404,7 @@ class Model(metaclass=ModelBase):
1365
1404
  return errors
1366
1405
 
1367
1406
  @classmethod
1368
- def _check_long_column_names(cls):
1407
+ def _check_long_column_names(cls) -> list[PreflightResult]:
1369
1408
  """
1370
1409
  Check that any auto-generated column names are shorter than the limits
1371
1410
  for each database in which the model will be created.
@@ -1428,7 +1467,7 @@ class Model(metaclass=ModelBase):
1428
1467
  return errors
1429
1468
 
1430
1469
  @classmethod
1431
- def _get_expr_references(cls, expr):
1470
+ def _get_expr_references(cls, expr: Any) -> Iterator[tuple[str, ...]]:
1432
1471
  if isinstance(expr, Q):
1433
1472
  for child in expr.children:
1434
1473
  if isinstance(child, tuple):
@@ -1444,7 +1483,7 @@ class Model(metaclass=ModelBase):
1444
1483
  yield from cls._get_expr_references(src_expr)
1445
1484
 
1446
1485
  @classmethod
1447
- def _check_constraints(cls):
1486
+ def _check_constraints(cls) -> list[PreflightResult]:
1448
1487
  errors = []
1449
1488
  if not (
1450
1489
  db_connection.features.supports_table_check_constraints
@@ -1617,7 +1656,7 @@ class Model(metaclass=ModelBase):
1617
1656
  ########
1618
1657
 
1619
1658
 
1620
- def model_unpickle(model_id):
1659
+ def model_unpickle(model_id: tuple[str, str] | type[Model]) -> Model:
1621
1660
  """Used to unpickle Model subclasses with deferred fields."""
1622
1661
  if isinstance(model_id, tuple):
1623
1662
  model = models_registry.get_model(*model_id)
@@ -1627,4 +1666,4 @@ def model_unpickle(model_id):
1627
1666
  return model.__new__(model)
1628
1667
 
1629
1668
 
1630
- model_unpickle.__safe_for_unpickle__ = True
1669
+ model_unpickle.__safe_for_unpickle__ = True # type: ignore[attr-defined]