plain.models 0.49.2__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 +13 -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 +31 -22
  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.2.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.2.dist-info/RECORD +0 -122
  103. {plain_models-0.49.2.dist-info → plain_models-0.50.0.dist-info}/WHEEL +0 -0
  104. {plain_models-0.49.2.dist-info → plain_models-0.50.0.dist-info}/entry_points.txt +0 -0
  105. {plain_models-0.49.2.dist-info → plain_models-0.50.0.dist-info}/licenses/LICENSE +0 -0
plain/models/sql/query.py CHANGED
@@ -7,15 +7,19 @@ databases). The abstraction barrier only works one way: this module has to know
7
7
  all about the internals of models in order to get the information it needs.
8
8
  """
9
9
 
10
+ from __future__ import annotations
11
+
10
12
  import copy
11
13
  import difflib
12
14
  import functools
13
15
  import sys
14
16
  from collections import Counter, namedtuple
15
17
  from collections.abc import Iterator, Mapping
18
+ from collections.abc import Iterator as TypingIterator
16
19
  from functools import cached_property
17
20
  from itertools import chain, count, product
18
21
  from string import ascii_uppercase
22
+ from typing import TYPE_CHECKING, Any
19
23
 
20
24
  from plain.models.aggregates import Count
21
25
  from plain.models.constants import LOOKUP_SEP
@@ -45,6 +49,13 @@ from plain.models.sql.where import AND, OR, ExtraWhere, NothingNode, WhereNode
45
49
  from plain.utils.regex_helper import _lazy_re_compile
46
50
  from plain.utils.tree import Node
47
51
 
52
+ if TYPE_CHECKING:
53
+ from plain.models import Model
54
+ from plain.models.backends.base.base import BaseDatabaseWrapper
55
+ from plain.models.options import Options
56
+ from plain.models.sql.compiler import SQLCompiler
57
+
58
+
48
59
  __all__ = ["Query", "RawQuery"]
49
60
 
50
61
  # Quotation marks ('"`[]), whitespace characters, semicolons, or inline
@@ -56,7 +67,7 @@ FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|--|/\*|\*/")
56
67
  EXPLAIN_OPTIONS_PATTERN = _lazy_re_compile(r"[\w\-]+")
57
68
 
58
69
 
59
- def get_field_names_from_opts(opts):
70
+ def get_field_names_from_opts(opts: Options | None) -> set[str]:
60
71
  if opts is None:
61
72
  return set()
62
73
  return set(
@@ -66,7 +77,7 @@ def get_field_names_from_opts(opts):
66
77
  )
67
78
 
68
79
 
69
- def get_children_from_q(q):
80
+ def get_children_from_q(q: Q) -> TypingIterator[tuple[str, Any]]:
70
81
  for child in q.children:
71
82
  if isinstance(child, Node):
72
83
  yield from get_children_from_q(child)
@@ -83,7 +94,7 @@ JoinInfo = namedtuple(
83
94
  class RawQuery:
84
95
  """A single raw SQL query."""
85
96
 
86
- def __init__(self, sql, params=()):
97
+ def __init__(self, sql: str, params: tuple[Any, ...] | dict[str, Any] = ()):
87
98
  self.params = params
88
99
  self.sql = sql
89
100
  self.cursor = None
@@ -94,19 +105,19 @@ class RawQuery:
94
105
  self.extra_select = {}
95
106
  self.annotation_select = {}
96
107
 
97
- def chain(self):
108
+ def chain(self) -> RawQuery:
98
109
  return self.clone()
99
110
 
100
- def clone(self):
111
+ def clone(self) -> RawQuery:
101
112
  return RawQuery(self.sql, params=self.params)
102
113
 
103
- def get_columns(self):
114
+ def get_columns(self) -> list[str]:
104
115
  if self.cursor is None:
105
116
  self._execute_query()
106
117
  converter = db_connection.introspection.identifier_converter
107
118
  return [converter(column_meta[0]) for column_meta in self.cursor.description]
108
119
 
109
- def __iter__(self):
120
+ def __iter__(self) -> TypingIterator[Any]:
110
121
  # Always execute a new query for a new iterator.
111
122
  # This could be optimized with a cache at the expense of RAM.
112
123
  self._execute_query()
@@ -118,21 +129,21 @@ class RawQuery:
118
129
  result = self.cursor
119
130
  return iter(result)
120
131
 
121
- def __repr__(self):
132
+ def __repr__(self) -> str:
122
133
  return f"<{self.__class__.__name__}: {self}>"
123
134
 
124
135
  @property
125
- def params_type(self):
136
+ def params_type(self) -> type[dict] | type[tuple] | None:
126
137
  if self.params is None:
127
138
  return None
128
139
  return dict if isinstance(self.params, Mapping) else tuple
129
140
 
130
- def __str__(self):
141
+ def __str__(self) -> str:
131
142
  if self.params_type is None:
132
143
  return self.sql
133
144
  return self.sql % self.params_type(self.params)
134
145
 
135
- def _execute_query(self):
146
+ def _execute_query(self) -> None:
136
147
  # Adapt parameters to the database, as much as possible considering
137
148
  # that the target type isn't known. See #17755.
138
149
  params_type = self.params_type
@@ -226,7 +237,7 @@ class Query(BaseExpression):
226
237
 
227
238
  explain_info = None
228
239
 
229
- def __init__(self, model, alias_cols=True):
240
+ def __init__(self, model: type[Model], alias_cols: bool = True):
230
241
  self.model = model
231
242
  self.alias_refcount = {}
232
243
  # alias_map is the most important data structure regarding joins.
@@ -255,7 +266,7 @@ class Query(BaseExpression):
255
266
  self._filtered_relations = {}
256
267
 
257
268
  @property
258
- def output_field(self):
269
+ def output_field(self) -> Field | None: # type: ignore[return]
259
270
  if len(self.select) == 1:
260
271
  select = self.select[0]
261
272
  return getattr(select, "target", None) or select.field
@@ -263,11 +274,11 @@ class Query(BaseExpression):
263
274
  return next(iter(self.annotation_select.values())).output_field
264
275
 
265
276
  @cached_property
266
- def base_table(self):
277
+ def base_table(self) -> str | None:
267
278
  for alias in self.alias_map:
268
279
  return alias
269
280
 
270
- def __str__(self):
281
+ def __str__(self) -> str:
271
282
  """
272
283
  Return the query as a string of SQL with the parameter values
273
284
  substituted in (use sql_with_params() to see the unsubstituted string).
@@ -278,53 +289,53 @@ class Query(BaseExpression):
278
289
  sql, params = self.sql_with_params()
279
290
  return sql % params
280
291
 
281
- def sql_with_params(self):
292
+ def sql_with_params(self) -> tuple[str, tuple[Any, ...]]:
282
293
  """
283
294
  Return the query as an SQL string and the parameters that will be
284
295
  substituted into the query.
285
296
  """
286
297
  return self.get_compiler().as_sql()
287
298
 
288
- def __deepcopy__(self, memo):
299
+ def __deepcopy__(self, memo: dict[int, Any]) -> Query:
289
300
  """Limit the amount of work when a Query is deepcopied."""
290
301
  result = self.clone()
291
302
  memo[id(self)] = result
292
303
  return result
293
304
 
294
- def get_compiler(self, *, elide_empty=True):
305
+ def get_compiler(self, *, elide_empty: bool = True) -> Any:
295
306
  return db_connection.ops.compiler(self.compiler)(
296
307
  self, db_connection, elide_empty
297
308
  )
298
309
 
299
- def get_meta(self):
310
+ def get_meta(self) -> Options | None:
300
311
  """
301
312
  Return the Options instance (the model._meta) from which to start
302
313
  processing. Normally, this is self.model._meta, but it can be changed
303
314
  by subclasses.
304
315
  """
305
316
  if self.model:
306
- return self.model._meta
317
+ return self.model._meta # type: ignore[attr-defined,return-value]
307
318
 
308
- def clone(self):
319
+ def clone(self) -> Query:
309
320
  """
310
321
  Return a copy of the current Query. A lightweight alternative to
311
322
  deepcopy().
312
323
  """
313
- obj = Empty()
314
- obj.__class__ = self.__class__
324
+ obj = Empty() # type: ignore[misc]
325
+ obj.__class__ = self.__class__ # type: ignore[misc]
315
326
  # Copy references to everything.
316
- obj.__dict__ = self.__dict__.copy()
327
+ obj.__dict__ = self.__dict__.copy() # type: ignore[attr-defined]
317
328
  # Clone attributes that can't use shallow copy.
318
- obj.alias_refcount = self.alias_refcount.copy()
319
- obj.alias_map = self.alias_map.copy()
320
- obj.external_aliases = self.external_aliases.copy()
321
- obj.table_map = self.table_map.copy()
322
- obj.where = self.where.clone()
323
- obj.annotations = self.annotations.copy()
329
+ obj.alias_refcount = self.alias_refcount.copy() # type: ignore[attr-defined]
330
+ obj.alias_map = self.alias_map.copy() # type: ignore[attr-defined]
331
+ obj.external_aliases = self.external_aliases.copy() # type: ignore[attr-defined]
332
+ obj.table_map = self.table_map.copy() # type: ignore[attr-defined]
333
+ obj.where = self.where.clone() # type: ignore[attr-defined]
334
+ obj.annotations = self.annotations.copy() # type: ignore[attr-defined]
324
335
  if self.annotation_select_mask is not None:
325
- obj.annotation_select_mask = self.annotation_select_mask.copy()
336
+ obj.annotation_select_mask = self.annotation_select_mask.copy() # type: ignore[attr-defined]
326
337
  if self.combined_queries:
327
- obj.combined_queries = tuple(
338
+ obj.combined_queries = tuple( # type: ignore[attr-defined]
328
339
  [query.clone() for query in self.combined_queries]
329
340
  )
330
341
  # _annotation_select_cache cannot be copied, as doing so breaks the
@@ -332,50 +343,50 @@ class Query(BaseExpression):
332
343
  # _annotation_select_cache point to the same underlying objects.
333
344
  # It will get re-populated in the cloned queryset the next time it's
334
345
  # used.
335
- obj._annotation_select_cache = None
336
- obj.extra = self.extra.copy()
346
+ obj._annotation_select_cache = None # type: ignore[attr-defined]
347
+ obj.extra = self.extra.copy() # type: ignore[attr-defined]
337
348
  if self.extra_select_mask is not None:
338
- obj.extra_select_mask = self.extra_select_mask.copy()
349
+ obj.extra_select_mask = self.extra_select_mask.copy() # type: ignore[attr-defined]
339
350
  if self._extra_select_cache is not None:
340
- obj._extra_select_cache = self._extra_select_cache.copy()
351
+ obj._extra_select_cache = self._extra_select_cache.copy() # type: ignore[attr-defined]
341
352
  if self.select_related is not False:
342
353
  # Use deepcopy because select_related stores fields in nested
343
354
  # dicts.
344
- obj.select_related = copy.deepcopy(obj.select_related)
355
+ obj.select_related = copy.deepcopy(obj.select_related) # type: ignore[attr-defined]
345
356
  if "subq_aliases" in self.__dict__:
346
- obj.subq_aliases = self.subq_aliases.copy()
347
- obj.used_aliases = self.used_aliases.copy()
348
- obj._filtered_relations = self._filtered_relations.copy()
357
+ obj.subq_aliases = self.subq_aliases.copy() # type: ignore[attr-defined]
358
+ obj.used_aliases = self.used_aliases.copy() # type: ignore[attr-defined]
359
+ obj._filtered_relations = self._filtered_relations.copy() # type: ignore[attr-defined]
349
360
  # Clear the cached_property, if it exists.
350
361
  obj.__dict__.pop("base_table", None)
351
- return obj
362
+ return obj # type: ignore[return-value]
352
363
 
353
- def chain(self, klass=None):
364
+ def chain(self, klass: type[Query] | None = None) -> Query:
354
365
  """
355
366
  Return a copy of the current Query that's ready for another operation.
356
367
  The klass argument changes the type of the Query, e.g. UpdateQuery.
357
368
  """
358
369
  obj = self.clone()
359
370
  if klass and obj.__class__ != klass:
360
- obj.__class__ = klass
371
+ obj.__class__ = klass # type: ignore[misc]
361
372
  if not obj.filter_is_sticky:
362
- obj.used_aliases = set()
373
+ obj.used_aliases = set() # type: ignore[attr-defined]
363
374
  obj.filter_is_sticky = False
364
375
  if hasattr(obj, "_setup_query"):
365
- obj._setup_query()
366
- return obj
376
+ obj._setup_query() # type: ignore[attr-defined]
377
+ return obj # type: ignore[return-value]
367
378
 
368
- def relabeled_clone(self, change_map):
379
+ def relabeled_clone(self, change_map: dict[str, str]) -> Query:
369
380
  clone = self.clone()
370
381
  clone.change_aliases(change_map)
371
382
  return clone
372
383
 
373
- def _get_col(self, target, field, alias):
384
+ def _get_col(self, target: Any, field: Field, alias: str | None) -> Col:
374
385
  if not self.alias_cols:
375
386
  alias = None
376
387
  return target.get_col(alias, field)
377
388
 
378
- def get_aggregation(self, aggregate_exprs):
389
+ def get_aggregation(self, aggregate_exprs: dict[str, Any]) -> dict[str, Any]:
379
390
  """
380
391
  Return the dictionary with the values of the existing aggregations.
381
392
  """
@@ -526,17 +537,17 @@ class Query(BaseExpression):
526
537
 
527
538
  return dict(zip(outer_query.annotation_select, result))
528
539
 
529
- def get_count(self):
540
+ def get_count(self) -> int:
530
541
  """
531
542
  Perform a COUNT() query using the current filter constraints.
532
543
  """
533
544
  obj = self.clone()
534
545
  return obj.get_aggregation({"__count": Count("*")})["__count"]
535
546
 
536
- def has_filters(self):
547
+ def has_filters(self) -> bool:
537
548
  return self.where
538
549
 
539
- def exists(self, limit=True):
550
+ def exists(self, limit: bool = True) -> Query:
540
551
  q = self.clone()
541
552
  if not (q.distinct and q.is_sliced):
542
553
  if q.group_by is True:
@@ -558,12 +569,12 @@ class Query(BaseExpression):
558
569
  q.add_annotation(Value(1), "a")
559
570
  return q
560
571
 
561
- def has_results(self):
572
+ def has_results(self) -> bool:
562
573
  q = self.exists()
563
574
  compiler = q.get_compiler()
564
575
  return compiler.has_results()
565
576
 
566
- def explain(self, format=None, **options):
577
+ def explain(self, format: str | None = None, **options: Any) -> str:
567
578
  q = self.clone()
568
579
  for option_name in options:
569
580
  if (
@@ -575,7 +586,7 @@ class Query(BaseExpression):
575
586
  compiler = q.get_compiler()
576
587
  return "\n".join(compiler.explain_query())
577
588
 
578
- def combine(self, rhs, connector):
589
+ def combine(self, rhs: Query, connector: str) -> None:
579
590
  """
580
591
  Merge the 'rhs' query into the current one (with any 'rhs' effects
581
592
  being applied *after* (that is, "to the right of") anything in the
@@ -690,7 +701,12 @@ class Query(BaseExpression):
690
701
  self.order_by = rhs.order_by or self.order_by
691
702
  self.extra_order_by = rhs.extra_order_by or self.extra_order_by
692
703
 
693
- def _get_defer_select_mask(self, opts, mask, select_mask=None):
704
+ def _get_defer_select_mask(
705
+ self,
706
+ opts: Options,
707
+ mask: dict[str, Any],
708
+ select_mask: dict[Any, Any] | None = None,
709
+ ) -> dict[Any, Any]:
694
710
  if select_mask is None:
695
711
  select_mask = {}
696
712
  select_mask[opts.get_field("id")] = {}
@@ -727,7 +743,12 @@ class Query(BaseExpression):
727
743
  )
728
744
  return select_mask
729
745
 
730
- def _get_only_select_mask(self, opts, mask, select_mask=None):
746
+ def _get_only_select_mask(
747
+ self,
748
+ opts: Options,
749
+ mask: dict[str, Any],
750
+ select_mask: dict[Any, Any] | None = None,
751
+ ) -> dict[Any, Any]:
731
752
  if select_mask is None:
732
753
  select_mask = {}
733
754
  select_mask[opts.get_field("id")] = {}
@@ -744,7 +765,7 @@ class Query(BaseExpression):
744
765
  )
745
766
  return select_mask
746
767
 
747
- def get_select_mask(self):
768
+ def get_select_mask(self) -> dict[Any, Any]:
748
769
  """
749
770
  Convert the self.deferred_loading data structure to an alternate data
750
771
  structure, describing the field that *will* be loaded. This is used to
@@ -766,7 +787,9 @@ class Query(BaseExpression):
766
787
  return self._get_defer_select_mask(opts, mask)
767
788
  return self._get_only_select_mask(opts, mask)
768
789
 
769
- def table_alias(self, table_name, create=False, filtered_relation=None):
790
+ def table_alias(
791
+ self, table_name: str, create: bool = False, filtered_relation: Any = None
792
+ ) -> tuple[str, bool]:
770
793
  """
771
794
  Return a table alias for the given table_name and whether this is a
772
795
  new alias or not.
@@ -793,15 +816,15 @@ class Query(BaseExpression):
793
816
  self.alias_refcount[alias] = 1
794
817
  return alias, True
795
818
 
796
- def ref_alias(self, alias):
819
+ def ref_alias(self, alias: str) -> None:
797
820
  """Increases the reference count for this alias."""
798
821
  self.alias_refcount[alias] += 1
799
822
 
800
- def unref_alias(self, alias, amount=1):
823
+ def unref_alias(self, alias: str, amount: int = 1) -> None:
801
824
  """Decreases the reference count for this alias."""
802
825
  self.alias_refcount[alias] -= amount
803
826
 
804
- def promote_joins(self, aliases):
827
+ def promote_joins(self, aliases: set[str] | list[str]) -> None:
805
828
  """
806
829
  Promote recursively the join type of given aliases and its children to
807
830
  an outer join. If 'unconditional' is False, only promote the join if
@@ -838,7 +861,7 @@ class Query(BaseExpression):
838
861
  and join not in aliases
839
862
  )
840
863
 
841
- def demote_joins(self, aliases):
864
+ def demote_joins(self, aliases: set[str] | list[str]) -> None:
842
865
  """
843
866
  Change join type from LOUTER to INNER for all joins in aliases.
844
867
 
@@ -857,7 +880,7 @@ class Query(BaseExpression):
857
880
  if self.alias_map[parent_alias].join_type == INNER:
858
881
  aliases.append(parent_alias)
859
882
 
860
- def reset_refcounts(self, to_counts):
883
+ def reset_refcounts(self, to_counts: dict[str, int]) -> None:
861
884
  """
862
885
  Reset reference counts for aliases so that they match the value passed
863
886
  in `to_counts`.
@@ -866,7 +889,7 @@ class Query(BaseExpression):
866
889
  unref_amount = cur_refcount - to_counts.get(alias, 0)
867
890
  self.unref_alias(alias, unref_amount)
868
891
 
869
- def change_aliases(self, change_map):
892
+ def change_aliases(self, change_map: dict[str, str]) -> None:
870
893
  """
871
894
  Change the aliases in change_map (which maps old-alias -> new-alias),
872
895
  relabelling any references to them in select columns and the where
@@ -911,7 +934,9 @@ class Query(BaseExpression):
911
934
  for alias, aliased in self.external_aliases.items()
912
935
  }
913
936
 
914
- def bump_prefix(self, other_query, exclude=None):
937
+ def bump_prefix(
938
+ self, other_query: Query, exclude: set[str] | dict[str, str] | None = None
939
+ ) -> None:
915
940
  """
916
941
  Change the alias prefix to the next letter in the alphabet in a way
917
942
  that the other query's aliases and this query's aliases will not
@@ -919,7 +944,7 @@ class Query(BaseExpression):
919
944
  after this call. To prevent changing aliases use the exclude parameter.
920
945
  """
921
946
 
922
- def prefix_gen():
947
+ def prefix_gen() -> TypingIterator[str]:
923
948
  """
924
949
  Generate a sequence of characters in alphabetical order:
925
950
  -> 'A', 'B', 'C', ...
@@ -966,7 +991,7 @@ class Query(BaseExpression):
966
991
  }
967
992
  )
968
993
 
969
- def get_initial_alias(self):
994
+ def get_initial_alias(self) -> str | None:
970
995
  """
971
996
  Return the first alias for this query, after increasing its reference
972
997
  count.
@@ -975,12 +1000,12 @@ class Query(BaseExpression):
975
1000
  alias = self.base_table
976
1001
  self.ref_alias(alias)
977
1002
  elif self.model:
978
- alias = self.join(self.base_table_class(self.get_meta().db_table, None))
1003
+ alias = self.join(self.base_table_class(self.get_meta().db_table, None)) # type: ignore[arg-type]
979
1004
  else:
980
1005
  alias = None
981
1006
  return alias
982
1007
 
983
- def count_active_tables(self):
1008
+ def count_active_tables(self) -> int:
984
1009
  """
985
1010
  Return the number of tables in this query with a non-zero reference
986
1011
  count. After execution, the reference counts are zeroed, so tables
@@ -988,7 +1013,12 @@ class Query(BaseExpression):
988
1013
  """
989
1014
  return len([1 for count in self.alias_refcount.values() if count])
990
1015
 
991
- def join(self, join, reuse=None, reuse_with_filtered_relation=False):
1016
+ def join(
1017
+ self,
1018
+ join: BaseTable | Join,
1019
+ reuse: set[str] | None = None,
1020
+ reuse_with_filtered_relation: bool = False,
1021
+ ) -> str:
992
1022
  """
993
1023
  Return an alias for the 'join', either reusing an existing alias for
994
1024
  that join or creating a new one. 'join' is either a base_table_class or
@@ -1029,7 +1059,7 @@ class Query(BaseExpression):
1029
1059
  join.table_name, create=True, filtered_relation=join.filtered_relation
1030
1060
  )
1031
1061
  if join.join_type:
1032
- if self.alias_map[join.parent_alias].join_type == LOUTER or join.nullable:
1062
+ if self.alias_map[join.parent_alias].join_type == LOUTER or join.nullable: # type: ignore[attr-defined]
1033
1063
  join_type = LOUTER
1034
1064
  else:
1035
1065
  join_type = INNER
@@ -1038,14 +1068,16 @@ class Query(BaseExpression):
1038
1068
  self.alias_map[alias] = join
1039
1069
  return alias
1040
1070
 
1041
- def check_alias(self, alias):
1071
+ def check_alias(self, alias: str) -> None:
1042
1072
  if FORBIDDEN_ALIAS_PATTERN.search(alias):
1043
1073
  raise ValueError(
1044
1074
  "Column aliases cannot contain whitespace characters, quotation marks, "
1045
1075
  "semicolons, or SQL comments."
1046
1076
  )
1047
1077
 
1048
- def add_annotation(self, annotation, alias, select=True):
1078
+ def add_annotation(
1079
+ self, annotation: BaseExpression, alias: str, select: bool = True
1080
+ ) -> None:
1049
1081
  """Add a single annotation expression to the Query."""
1050
1082
  self.check_alias(alias)
1051
1083
  annotation = annotation.resolve_expression(self, allow_joins=True, reuse=None)
@@ -1055,7 +1087,7 @@ class Query(BaseExpression):
1055
1087
  self.set_annotation_mask(set(self.annotation_select).difference({alias}))
1056
1088
  self.annotations[alias] = annotation
1057
1089
 
1058
- def resolve_expression(self, query, *args, **kwargs):
1090
+ def resolve_expression(self, query: Query, *args: Any, **kwargs: Any) -> Query:
1059
1091
  clone = self.clone()
1060
1092
  # Subqueries need to use a different set of aliases than the outer query.
1061
1093
  clone.bump_prefix(query)
@@ -1084,7 +1116,7 @@ class Query(BaseExpression):
1084
1116
  )
1085
1117
  return clone
1086
1118
 
1087
- def get_external_cols(self):
1119
+ def get_external_cols(self) -> list[Col]:
1088
1120
  exprs = chain(self.annotations.values(), self.where.children)
1089
1121
  return [
1090
1122
  col
@@ -1092,7 +1124,9 @@ class Query(BaseExpression):
1092
1124
  if col.alias in self.external_aliases
1093
1125
  ]
1094
1126
 
1095
- def get_group_by_cols(self, wrapper=None):
1127
+ def get_group_by_cols(
1128
+ self, wrapper: BaseExpression | None = None
1129
+ ) -> list[Col] | list[BaseExpression]:
1096
1130
  # If wrapper is referenced by an alias for an explicit GROUP BY through
1097
1131
  # values() a reference to this expression and not the self must be
1098
1132
  # returned to ensure external column references are not grouped against
@@ -1102,7 +1136,9 @@ class Query(BaseExpression):
1102
1136
  return [wrapper or self]
1103
1137
  return external_cols
1104
1138
 
1105
- def as_sql(self, compiler, connection):
1139
+ def as_sql(
1140
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1141
+ ) -> tuple[str, tuple[Any, ...]]:
1106
1142
  # Some backends (e.g. Oracle) raise an error when a subquery contains
1107
1143
  # unnecessary ORDER BY clause.
1108
1144
  if (
@@ -1117,7 +1153,9 @@ class Query(BaseExpression):
1117
1153
  sql = f"({sql})"
1118
1154
  return sql, params
1119
1155
 
1120
- def resolve_lookup_value(self, value, can_reuse, allow_joins):
1156
+ def resolve_lookup_value(
1157
+ self, value: Any, can_reuse: set[str] | None, allow_joins: bool
1158
+ ) -> Any:
1121
1159
  if hasattr(value, "resolve_expression"):
1122
1160
  value = value.resolve_expression(
1123
1161
  self,
@@ -1137,7 +1175,9 @@ class Query(BaseExpression):
1137
1175
  return type_(values)
1138
1176
  return value
1139
1177
 
1140
- def solve_lookup_type(self, lookup, summarize=False):
1178
+ def solve_lookup_type(
1179
+ self, lookup: str, summarize: bool = False
1180
+ ) -> tuple[list[str] | tuple[str, ...], tuple[str, ...], BaseExpression | bool]:
1141
1181
  """
1142
1182
  Solve the lookup type from the lookup (e.g.: 'foobar__id__icontains').
1143
1183
  """
@@ -1157,9 +1197,9 @@ class Query(BaseExpression):
1157
1197
  raise FieldError(
1158
1198
  f'Invalid lookup "{lookup}" for model {self.get_meta().model.__name__}".'
1159
1199
  )
1160
- return lookup_parts, field_parts, False
1200
+ return lookup_parts, field_parts, False # type: ignore[return-value]
1161
1201
 
1162
- def check_query_object_type(self, value, opts, field):
1202
+ def check_query_object_type(self, value: Any, opts: Options, field: Field) -> None:
1163
1203
  """
1164
1204
  Check whether the object passed while querying is of the correct type.
1165
1205
  If not, raise a ValueError specifying the wrong object.
@@ -1170,7 +1210,7 @@ class Query(BaseExpression):
1170
1210
  f'Cannot query "{value}": Must be "{opts.object_name}" instance.'
1171
1211
  )
1172
1212
 
1173
- def check_related_objects(self, field, value, opts):
1213
+ def check_related_objects(self, field: Field, value: Any, opts: Options) -> None:
1174
1214
  """Check the type of object passed to query relations."""
1175
1215
  if field.is_relation:
1176
1216
  # Check that the field and the queryset use the same model in a
@@ -1192,7 +1232,7 @@ class Query(BaseExpression):
1192
1232
  for v in value:
1193
1233
  self.check_query_object_type(v, opts, field)
1194
1234
 
1195
- def check_filterable(self, expression):
1235
+ def check_filterable(self, expression: Any) -> None:
1196
1236
  """Raise an error if expression cannot be used in a WHERE clause."""
1197
1237
  if hasattr(expression, "resolve_expression") and not getattr(
1198
1238
  expression, "filterable", True
@@ -1204,7 +1244,9 @@ class Query(BaseExpression):
1204
1244
  for expr in expression.get_source_expressions():
1205
1245
  self.check_filterable(expr)
1206
1246
 
1207
- def build_lookup(self, lookups, lhs, rhs):
1247
+ def build_lookup(
1248
+ self, lookups: list[str], lhs: BaseExpression, rhs: Any
1249
+ ) -> Lookup | None:
1208
1250
  """
1209
1251
  Try to extract transforms and lookup from given lhs.
1210
1252
 
@@ -1235,11 +1277,11 @@ class Query(BaseExpression):
1235
1277
  if lookup.rhs is None and not lookup.can_use_none_as_rhs:
1236
1278
  if lookup_name not in ("exact", "iexact"):
1237
1279
  raise ValueError("Cannot use None as a query value")
1238
- return lhs.get_lookup("isnull")(lhs, True)
1280
+ return lhs.get_lookup("isnull")(lhs, True) # type: ignore[return-value]
1239
1281
 
1240
1282
  return lookup
1241
1283
 
1242
- def try_transform(self, lhs, name):
1284
+ def try_transform(self, lhs: BaseExpression, name: str) -> BaseExpression:
1243
1285
  """
1244
1286
  Helper method for build_lookup(). Try to fetch and initialize
1245
1287
  a transform for name parameter from lhs.
@@ -1265,16 +1307,16 @@ class Query(BaseExpression):
1265
1307
 
1266
1308
  def build_filter(
1267
1309
  self,
1268
- filter_expr,
1269
- branch_negated=False,
1270
- current_negated=False,
1271
- can_reuse=None,
1272
- allow_joins=True,
1273
- split_subq=True,
1274
- reuse_with_filtered_relation=False,
1275
- check_filterable=True,
1276
- summarize=False,
1277
- ):
1310
+ filter_expr: tuple[str, Any] | Q | BaseExpression,
1311
+ branch_negated: bool = False,
1312
+ current_negated: bool = False,
1313
+ can_reuse: set[str] | None = None,
1314
+ allow_joins: bool = True,
1315
+ split_subq: bool = True,
1316
+ reuse_with_filtered_relation: bool = False,
1317
+ check_filterable: bool = True,
1318
+ summarize: bool = False,
1319
+ ) -> tuple[WhereNode, set[str] | tuple[()]]:
1278
1320
  """
1279
1321
  Build a WhereNode for a single filter clause but don't add it
1280
1322
  to this Query. Query.add_q() will then add this filter to the where
@@ -1321,10 +1363,10 @@ class Query(BaseExpression):
1321
1363
  raise TypeError("Cannot filter against a non-conditional expression.")
1322
1364
  condition = filter_expr.resolve_expression(
1323
1365
  self, allow_joins=allow_joins, summarize=summarize
1324
- )
1366
+ ) # type: ignore[attr-defined]
1325
1367
  if not isinstance(condition, Lookup):
1326
1368
  condition = self.build_lookup(["exact"], condition, True)
1327
- return WhereNode([condition], connector=AND), []
1369
+ return WhereNode([condition], connector=AND), [] # type: ignore[return-value]
1328
1370
  arg, value = filter_expr
1329
1371
  if not arg:
1330
1372
  raise FieldError(f"Cannot parse keyword query {arg!r}")
@@ -1347,7 +1389,7 @@ class Query(BaseExpression):
1347
1389
 
1348
1390
  if reffed_expression:
1349
1391
  condition = self.build_lookup(lookups, reffed_expression, value)
1350
- return WhereNode([condition], connector=AND), []
1392
+ return WhereNode([condition], connector=AND), [] # type: ignore[return-value]
1351
1393
 
1352
1394
  opts = self.get_meta()
1353
1395
  alias = self.get_initial_alias()
@@ -1430,10 +1472,10 @@ class Query(BaseExpression):
1430
1472
  clause.add(lookup_class(value, False), AND)
1431
1473
  return clause, used_joins if not require_outer else ()
1432
1474
 
1433
- def add_filter(self, filter_lhs, filter_rhs):
1475
+ def add_filter(self, filter_lhs: str, filter_rhs: Any) -> None:
1434
1476
  self.add_q(Q((filter_lhs, filter_rhs)))
1435
1477
 
1436
- def add_q(self, q_object):
1478
+ def add_q(self, q_object: Q) -> None: # type: ignore[unsupported-operator]
1437
1479
  """
1438
1480
  A preprocessor for the internal _add_q(). Responsible for doing final
1439
1481
  join promotion.
@@ -1452,23 +1494,23 @@ class Query(BaseExpression):
1452
1494
  self.where.add(clause, AND)
1453
1495
  self.demote_joins(existing_inner)
1454
1496
 
1455
- def build_where(self, filter_expr):
1497
+ def build_where(self, filter_expr: tuple[str, Any]) -> WhereNode:
1456
1498
  return self.build_filter(filter_expr, allow_joins=False)[0]
1457
1499
 
1458
- def clear_where(self):
1500
+ def clear_where(self) -> None:
1459
1501
  self.where = WhereNode()
1460
1502
 
1461
1503
  def _add_q(
1462
1504
  self,
1463
- q_object,
1464
- used_aliases,
1465
- branch_negated=False,
1466
- current_negated=False,
1467
- allow_joins=True,
1468
- split_subq=True,
1469
- check_filterable=True,
1470
- summarize=False,
1471
- ):
1505
+ q_object: Q,
1506
+ used_aliases: set[str] | None,
1507
+ branch_negated: bool = False,
1508
+ current_negated: bool = False,
1509
+ allow_joins: bool = True,
1510
+ split_subq: bool = True,
1511
+ check_filterable: bool = True,
1512
+ summarize: bool = False,
1513
+ ) -> tuple[WhereNode, set[str] | tuple[()]]: # type: ignore[unsupported-operator]
1472
1514
  """Add a Q-object to the current filter."""
1473
1515
  connector = q_object.connector
1474
1516
  current_negated ^= q_object.negated
@@ -1495,8 +1537,12 @@ class Query(BaseExpression):
1495
1537
  return target_clause, needed_inner
1496
1538
 
1497
1539
  def build_filtered_relation_q(
1498
- self, q_object, reuse, branch_negated=False, current_negated=False
1499
- ):
1540
+ self,
1541
+ q_object: Q,
1542
+ reuse: set[str],
1543
+ branch_negated: bool = False,
1544
+ current_negated: bool = False,
1545
+ ) -> WhereNode: # type: ignore[unsupported-operator]
1500
1546
  """Add a FilteredRelation object to the current filter."""
1501
1547
  connector = q_object.connector
1502
1548
  current_negated ^= q_object.negated
@@ -1523,7 +1569,7 @@ class Query(BaseExpression):
1523
1569
  target_clause.add(child_clause, connector)
1524
1570
  return target_clause
1525
1571
 
1526
- def add_filtered_relation(self, filtered_relation, alias):
1572
+ def add_filtered_relation(self, filtered_relation: Any, alias: str) -> None:
1527
1573
  filtered_relation.alias = alias
1528
1574
  lookups = dict(get_children_from_q(filtered_relation.condition))
1529
1575
  relation_lookup_parts, relation_field_parts, _ = self.solve_lookup_type(
@@ -1553,7 +1599,13 @@ class Query(BaseExpression):
1553
1599
  )
1554
1600
  self._filtered_relations[filtered_relation.alias] = filtered_relation
1555
1601
 
1556
- def names_to_path(self, names, opts, allow_many=True, fail_on_missing=False):
1602
+ def names_to_path(
1603
+ self,
1604
+ names: list[str],
1605
+ opts: Options | None,
1606
+ allow_many: bool = True,
1607
+ fail_on_missing: bool = False,
1608
+ ) -> tuple[list[Any], Field, tuple[Field, ...], list[str]]:
1557
1609
  """
1558
1610
  Walk the list of names and turns them into PathInfo tuples. A single
1559
1611
  name in 'names' can generate multiple PathInfos (m2m, for example).
@@ -1593,7 +1645,7 @@ class Query(BaseExpression):
1593
1645
  )
1594
1646
  path.extend(filtered_relation_path[:-1])
1595
1647
  else:
1596
- field = opts.get_field(filtered_relation.relation_name)
1648
+ field = opts.get_field(filtered_relation.relation_name) # type: ignore[attr-defined]
1597
1649
  if field is not None:
1598
1650
  # Fields that contain one-to-many relations with a generic
1599
1651
  # model (like a GenericForeignKey) cannot generate reverse
@@ -1655,13 +1707,13 @@ class Query(BaseExpression):
1655
1707
 
1656
1708
  def setup_joins(
1657
1709
  self,
1658
- names,
1659
- opts,
1660
- alias,
1661
- can_reuse=None,
1662
- allow_many=True,
1663
- reuse_with_filtered_relation=False,
1664
- ):
1710
+ names: list[str],
1711
+ opts: Options,
1712
+ alias: str,
1713
+ can_reuse: set[str] | None = None,
1714
+ allow_many: bool = True,
1715
+ reuse_with_filtered_relation: bool = False,
1716
+ ) -> JoinInfo:
1665
1717
  """
1666
1718
  Compute the necessary table joins for the passage through the fields
1667
1719
  given in 'names'. 'opts' is the Options class for the current model
@@ -1698,10 +1750,10 @@ class Query(BaseExpression):
1698
1750
  # directly, compute transforms here and create a partial that converts
1699
1751
  # fields to the appropriate wrapped version.
1700
1752
 
1701
- def final_transformer(field, alias):
1753
+ def final_transformer(field: Field, alias: str | None) -> Col:
1702
1754
  if not self.alias_cols:
1703
1755
  alias = None
1704
- return field.get_col(alias)
1756
+ return field.get_col(alias) # type: ignore[arg-type]
1705
1757
 
1706
1758
  # Try resolving all the names as fields first. If there's an error,
1707
1759
  # treat trailing names as lookups until a field can be resolved.
@@ -1728,7 +1780,9 @@ class Query(BaseExpression):
1728
1780
  break
1729
1781
  for name in transforms:
1730
1782
 
1731
- def transform(field, alias, *, name, previous):
1783
+ def transform(
1784
+ field: Field, alias: str | None, *, name: str, previous: Any
1785
+ ) -> BaseExpression:
1732
1786
  try:
1733
1787
  wrapped = previous(field, alias)
1734
1788
  return self.try_transform(wrapped, name)
@@ -1739,10 +1793,10 @@ class Query(BaseExpression):
1739
1793
  else:
1740
1794
  raise
1741
1795
 
1742
- final_transformer = functools.partial(
1796
+ final_transformer = functools.partial( # type: ignore[misc]
1743
1797
  transform, name=name, previous=final_transformer
1744
1798
  )
1745
- final_transformer.has_transforms = True
1799
+ final_transformer.has_transforms = True # type: ignore[attr-defined]
1746
1800
  # Then, add the path to the query's joins. Note that we can't trim
1747
1801
  # joins at this stage - we will need the information about join type
1748
1802
  # of the trimmed joins.
@@ -1778,7 +1832,9 @@ class Query(BaseExpression):
1778
1832
  filtered_relation.path = joins[:]
1779
1833
  return JoinInfo(final_field, targets, opts, joins, path, final_transformer)
1780
1834
 
1781
- def trim_joins(self, targets, joins, path):
1835
+ def trim_joins(
1836
+ self, targets: tuple[Field, ...], joins: list[str], path: list[Any]
1837
+ ) -> tuple[tuple[Field, ...], str, list[str]]:
1782
1838
  """
1783
1839
  The 'target' parameter is the final field being joined to, 'joins'
1784
1840
  is the full list of join aliases. The 'path' contain the PathInfos
@@ -1811,7 +1867,12 @@ class Query(BaseExpression):
1811
1867
  return targets, joins[-1], joins
1812
1868
 
1813
1869
  @classmethod
1814
- def _gen_cols(cls, exprs, include_external=False, resolve_refs=True):
1870
+ def _gen_cols(
1871
+ cls,
1872
+ exprs: TypingIterator[Any],
1873
+ include_external: bool = False,
1874
+ resolve_refs: bool = True,
1875
+ ) -> TypingIterator[Col]:
1815
1876
  for expr in exprs:
1816
1877
  if isinstance(expr, Col):
1817
1878
  yield expr
@@ -1829,10 +1890,16 @@ class Query(BaseExpression):
1829
1890
  )
1830
1891
 
1831
1892
  @classmethod
1832
- def _gen_col_aliases(cls, exprs):
1893
+ def _gen_col_aliases(cls, exprs: TypingIterator[Any]) -> TypingIterator[str]:
1833
1894
  yield from (expr.alias for expr in cls._gen_cols(exprs))
1834
1895
 
1835
- def resolve_ref(self, name, allow_joins=True, reuse=None, summarize=False):
1896
+ def resolve_ref(
1897
+ self,
1898
+ name: str,
1899
+ allow_joins: bool = True,
1900
+ reuse: set[str] | None = None,
1901
+ summarize: bool = False,
1902
+ ) -> BaseExpression:
1836
1903
  annotation = self.annotations.get(name)
1837
1904
  if annotation is not None:
1838
1905
  if not allow_joins:
@@ -1882,7 +1949,12 @@ class Query(BaseExpression):
1882
1949
  reuse.update(join_list)
1883
1950
  return transform
1884
1951
 
1885
- def split_exclude(self, filter_expr, can_reuse, names_with_path):
1952
+ def split_exclude(
1953
+ self,
1954
+ filter_expr: tuple[str, Any],
1955
+ can_reuse: set[str],
1956
+ names_with_path: list[tuple[str, list[Any]]],
1957
+ ) -> tuple[WhereNode, set[str] | tuple[()]]:
1886
1958
  """
1887
1959
  When doing an exclude against any kind of N-to-many relation, we need
1888
1960
  to use a subquery. This method constructs the nested query, given the
@@ -1953,15 +2025,15 @@ class Query(BaseExpression):
1953
2025
  # outercol IS NULL we will not match the row.
1954
2026
  return condition, needed_inner
1955
2027
 
1956
- def set_empty(self):
2028
+ def set_empty(self) -> None:
1957
2029
  self.where.add(NothingNode(), AND)
1958
2030
  for query in self.combined_queries:
1959
2031
  query.set_empty()
1960
2032
 
1961
- def is_empty(self):
2033
+ def is_empty(self) -> bool:
1962
2034
  return any(isinstance(c, NothingNode) for c in self.where.children)
1963
2035
 
1964
- def set_limits(self, low=None, high=None):
2036
+ def set_limits(self, low: int | None = None, high: int | None = None) -> None:
1965
2037
  """
1966
2038
  Adjust the limits on the rows retrieved. Use low/high to set these,
1967
2039
  as it makes it more Pythonic to read and write. When the SQL query is
@@ -1984,18 +2056,18 @@ class Query(BaseExpression):
1984
2056
  if self.low_mark == self.high_mark:
1985
2057
  self.set_empty()
1986
2058
 
1987
- def clear_limits(self):
2059
+ def clear_limits(self) -> None:
1988
2060
  """Clear any existing limits."""
1989
2061
  self.low_mark, self.high_mark = 0, None
1990
2062
 
1991
2063
  @property
1992
- def is_sliced(self):
2064
+ def is_sliced(self) -> bool:
1993
2065
  return self.low_mark != 0 or self.high_mark is not None
1994
2066
 
1995
- def has_limit_one(self):
2067
+ def has_limit_one(self) -> bool:
1996
2068
  return self.high_mark is not None and (self.high_mark - self.low_mark) == 1
1997
2069
 
1998
- def can_filter(self):
2070
+ def can_filter(self) -> bool:
1999
2071
  """
2000
2072
  Return True if adding filters to this instance is still possible.
2001
2073
 
@@ -2003,7 +2075,7 @@ class Query(BaseExpression):
2003
2075
  """
2004
2076
  return not self.is_sliced
2005
2077
 
2006
- def clear_select_clause(self):
2078
+ def clear_select_clause(self) -> None:
2007
2079
  """Remove all fields from SELECT clause."""
2008
2080
  self.select = ()
2009
2081
  self.default_cols = False
@@ -2011,7 +2083,7 @@ class Query(BaseExpression):
2011
2083
  self.set_extra_mask(())
2012
2084
  self.set_annotation_mask(())
2013
2085
 
2014
- def clear_select_fields(self):
2086
+ def clear_select_fields(self) -> None:
2015
2087
  """
2016
2088
  Clear the list of fields to select (but not extra_select columns).
2017
2089
  Some queryset types completely replace any existing list of select
@@ -2020,22 +2092,24 @@ class Query(BaseExpression):
2020
2092
  self.select = ()
2021
2093
  self.values_select = ()
2022
2094
 
2023
- def add_select_col(self, col, name):
2095
+ def add_select_col(self, col: Col, name: str) -> None:
2024
2096
  self.select += (col,)
2025
2097
  self.values_select += (name,)
2026
2098
 
2027
- def set_select(self, cols):
2099
+ def set_select(self, cols: list[Col] | tuple[Col, ...]) -> None:
2028
2100
  self.default_cols = False
2029
2101
  self.select = tuple(cols)
2030
2102
 
2031
- def add_distinct_fields(self, *field_names):
2103
+ def add_distinct_fields(self, *field_names: str) -> None:
2032
2104
  """
2033
2105
  Add and resolve the given fields to the query's "distinct on" clause.
2034
2106
  """
2035
2107
  self.distinct_fields = field_names
2036
2108
  self.distinct = True
2037
2109
 
2038
- def add_fields(self, field_names, allow_m2m=True):
2110
+ def add_fields(
2111
+ self, field_names: list[str] | TypingIterator[str], allow_m2m: bool = True
2112
+ ) -> None:
2039
2113
  """
2040
2114
  Add the given (model) fields to the select set. Add the field names in
2041
2115
  the order specified.
@@ -2086,7 +2160,7 @@ class Query(BaseExpression):
2086
2160
  )
2087
2161
  )
2088
2162
 
2089
- def add_ordering(self, *ordering):
2163
+ def add_ordering(self, *ordering: str | BaseExpression) -> None:
2090
2164
  """
2091
2165
  Add items from the 'ordering' sequence to the query's "order by"
2092
2166
  clause. These items are either field names (not column names) --
@@ -2122,7 +2196,7 @@ class Query(BaseExpression):
2122
2196
  else:
2123
2197
  self.default_ordering = False
2124
2198
 
2125
- def clear_ordering(self, force=False, clear_default=True):
2199
+ def clear_ordering(self, force: bool = False, clear_default: bool = True) -> None:
2126
2200
  """
2127
2201
  Remove any ordering settings if the current query allows it without
2128
2202
  side effects, set 'force' to True to clear the ordering regardless.
@@ -2138,7 +2212,7 @@ class Query(BaseExpression):
2138
2212
  if clear_default:
2139
2213
  self.default_ordering = False
2140
2214
 
2141
- def set_group_by(self, allow_aliases=True):
2215
+ def set_group_by(self, allow_aliases: bool = True) -> None:
2142
2216
  """
2143
2217
  Expand the GROUP BY clause required by the query.
2144
2218
 
@@ -2171,7 +2245,7 @@ class Query(BaseExpression):
2171
2245
  group_by.extend(group_by_cols)
2172
2246
  self.group_by = tuple(group_by)
2173
2247
 
2174
- def add_select_related(self, fields):
2248
+ def add_select_related(self, fields: list[str]) -> None:
2175
2249
  """
2176
2250
  Set up the select_related data structure so that we only select
2177
2251
  certain related models (as opposed to all models, when
@@ -2187,7 +2261,15 @@ class Query(BaseExpression):
2187
2261
  d = d.setdefault(part, {})
2188
2262
  self.select_related = field_dict
2189
2263
 
2190
- def add_extra(self, select, select_params, where, params, tables, order_by):
2264
+ def add_extra(
2265
+ self,
2266
+ select: dict[str, str],
2267
+ select_params: list[Any] | None,
2268
+ where: list[str],
2269
+ params: list[Any],
2270
+ tables: list[str],
2271
+ order_by: tuple[str, ...],
2272
+ ) -> None:
2191
2273
  """
2192
2274
  Add data to the various extra_* attributes for user-created additions
2193
2275
  to the query.
@@ -2220,11 +2302,11 @@ class Query(BaseExpression):
2220
2302
  if order_by:
2221
2303
  self.extra_order_by = order_by
2222
2304
 
2223
- def clear_deferred_loading(self):
2305
+ def clear_deferred_loading(self) -> None:
2224
2306
  """Remove any fields from the deferred loading set."""
2225
2307
  self.deferred_loading = (frozenset(), True)
2226
2308
 
2227
- def add_deferred_loading(self, field_names):
2309
+ def add_deferred_loading(self, field_names: frozenset[str]) -> None:
2228
2310
  """
2229
2311
  Add the given list of model field names to the set of fields to
2230
2312
  exclude from loading from the database when automatic column selection
@@ -2249,7 +2331,7 @@ class Query(BaseExpression):
2249
2331
  if new_only := set(field_names).difference(existing):
2250
2332
  self.deferred_loading = new_only, True
2251
2333
 
2252
- def add_immediate_loading(self, field_names):
2334
+ def add_immediate_loading(self, field_names: list[str] | set[str]) -> None:
2253
2335
  """
2254
2336
  Add the given list of model field names to the set of fields to
2255
2337
  retrieve when the SQL is executed ("immediate loading" fields). The
@@ -2270,7 +2352,9 @@ class Query(BaseExpression):
2270
2352
  # Replace any existing "immediate load" field names.
2271
2353
  self.deferred_loading = frozenset(field_names), False
2272
2354
 
2273
- def set_annotation_mask(self, names):
2355
+ def set_annotation_mask(
2356
+ self, names: set[str] | frozenset[str] | list[str] | dict[str, Any] | None
2357
+ ) -> None: # type: ignore[misc]
2274
2358
  """Set the mask of annotations that will be returned by the SELECT."""
2275
2359
  if names is None:
2276
2360
  self.annotation_select_mask = None
@@ -2278,11 +2362,11 @@ class Query(BaseExpression):
2278
2362
  self.annotation_select_mask = set(names)
2279
2363
  self._annotation_select_cache = None
2280
2364
 
2281
- def append_annotation_mask(self, names):
2365
+ def append_annotation_mask(self, names: list[str] | dict[str, Any]) -> None:
2282
2366
  if self.annotation_select_mask is not None:
2283
2367
  self.set_annotation_mask(self.annotation_select_mask.union(names))
2284
2368
 
2285
- def set_extra_mask(self, names):
2369
+ def set_extra_mask(self, names: set[str] | tuple[str, ...] | None) -> None:
2286
2370
  """
2287
2371
  Set the mask of extra select items that will be returned by SELECT.
2288
2372
  Don't remove them from the Query since they might be used later.
@@ -2293,7 +2377,7 @@ class Query(BaseExpression):
2293
2377
  self.extra_select_mask = set(names)
2294
2378
  self._extra_select_cache = None
2295
2379
 
2296
- def set_values(self, fields):
2380
+ def set_values(self, fields: list[str]) -> None:
2297
2381
  self.select_related = False
2298
2382
  self.clear_deferred_loading()
2299
2383
  self.clear_select_fields()
@@ -2346,7 +2430,7 @@ class Query(BaseExpression):
2346
2430
  self.add_fields(field_names, True)
2347
2431
 
2348
2432
  @property
2349
- def annotation_select(self):
2433
+ def annotation_select(self) -> dict[str, BaseExpression]:
2350
2434
  """
2351
2435
  Return the dictionary of aggregate columns that are not masked and
2352
2436
  should be used in the SELECT clause. Cache this result for performance.
@@ -2366,7 +2450,7 @@ class Query(BaseExpression):
2366
2450
  return self.annotations
2367
2451
 
2368
2452
  @property
2369
- def extra_select(self):
2453
+ def extra_select(self) -> dict[str, tuple[str, list[Any]]]:
2370
2454
  if self._extra_select_cache is not None:
2371
2455
  return self._extra_select_cache
2372
2456
  if not self.extra:
@@ -2379,7 +2463,9 @@ class Query(BaseExpression):
2379
2463
  else:
2380
2464
  return self.extra
2381
2465
 
2382
- def trim_start(self, names_with_path):
2466
+ def trim_start(
2467
+ self, names_with_path: list[tuple[str, list[Any]]]
2468
+ ) -> tuple[str, bool]:
2383
2469
  """
2384
2470
  Trim joins from the start of the join path. The candidates for trim
2385
2471
  are the PathInfos in names_with_path structure that are m2m joins.
@@ -2456,7 +2542,7 @@ class Query(BaseExpression):
2456
2542
  self.set_select([f.get_col(select_alias) for f in select_fields])
2457
2543
  return trimmed_prefix, contains_louter
2458
2544
 
2459
- def is_nullable(self, field):
2545
+ def is_nullable(self, field: Field) -> bool:
2460
2546
  """Check if the given field should be treated as nullable."""
2461
2547
  # QuerySet does not have knowledge of which connection is going to be
2462
2548
  # used. For the single-database setup we always reference the default
@@ -2464,7 +2550,7 @@ class Query(BaseExpression):
2464
2550
  return field.allow_null
2465
2551
 
2466
2552
 
2467
- def get_order_dir(field, default="ASC"):
2553
+ def get_order_dir(field: str, default: str = "ASC") -> tuple[str, str]:
2468
2554
  """
2469
2555
  Return the field name and direction for an order specification. For
2470
2556
  example, '-foo' is returned as ('foo', 'DESC').
@@ -2484,7 +2570,7 @@ class JoinPromoter:
2484
2570
  conditions.
2485
2571
  """
2486
2572
 
2487
- def __init__(self, connector, num_children, negated):
2573
+ def __init__(self, connector: str, num_children: int, negated: bool):
2488
2574
  self.connector = connector
2489
2575
  self.negated = negated
2490
2576
  if self.negated:
@@ -2499,20 +2585,20 @@ class JoinPromoter:
2499
2585
  # inner and/or outer joins.
2500
2586
  self.votes = Counter()
2501
2587
 
2502
- def __repr__(self):
2588
+ def __repr__(self) -> str:
2503
2589
  return (
2504
2590
  f"{self.__class__.__qualname__}(connector={self.connector!r}, "
2505
2591
  f"num_children={self.num_children!r}, negated={self.negated!r})"
2506
2592
  )
2507
2593
 
2508
- def add_votes(self, votes):
2594
+ def add_votes(self, votes: Any) -> None:
2509
2595
  """
2510
2596
  Add single vote per item to self.votes. Parameter can be any
2511
2597
  iterable.
2512
2598
  """
2513
2599
  self.votes.update(votes)
2514
2600
 
2515
- def update_join_types(self, query):
2601
+ def update_join_types(self, query: Query) -> set[str]:
2516
2602
  """
2517
2603
  Change join types so that the generated query is as efficient as
2518
2604
  possible, but still correct. So, change as many joins as possible