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 copy
2
4
  import datetime
3
5
  import functools
@@ -6,6 +8,7 @@ from collections import defaultdict
6
8
  from decimal import Decimal
7
9
  from functools import cached_property
8
10
  from types import NoneType
11
+ from typing import TYPE_CHECKING, Any
9
12
  from uuid import UUID
10
13
 
11
14
  from plain.models import fields
@@ -20,6 +23,13 @@ from plain.models.query_utils import Q
20
23
  from plain.utils.deconstruct import deconstructible
21
24
  from plain.utils.hashable import make_hashable
22
25
 
26
+ if TYPE_CHECKING:
27
+ from collections.abc import Callable, Iterable, Sequence
28
+
29
+ from plain.models.backends.base.base import BaseDatabaseWrapper
30
+ from plain.models.fields import Field
31
+ from plain.models.sql.compiler import SQLCompiler
32
+
23
33
 
24
34
  class SQLiteNumericMixin:
25
35
  """
@@ -27,10 +37,15 @@ class SQLiteNumericMixin:
27
37
  numeric to be properly filtered.
28
38
  """
29
39
 
30
- def as_sqlite(self, compiler, connection, **extra_context):
31
- sql, params = self.as_sql(compiler, connection, **extra_context)
40
+ def as_sqlite(
41
+ self,
42
+ compiler: SQLCompiler,
43
+ connection: BaseDatabaseWrapper,
44
+ **extra_context: Any,
45
+ ) -> tuple[str, Sequence[Any]]:
46
+ sql, params = self.as_sql(compiler, connection, **extra_context) # type: ignore[attr-defined]
32
47
  try:
33
- if self.output_field.get_internal_type() == "DecimalField":
48
+ if self.output_field.get_internal_type() == "DecimalField": # type: ignore[attr-defined]
34
49
  sql = f"CAST({sql} AS NUMERIC)"
35
50
  except FieldError:
36
51
  pass
@@ -62,7 +77,9 @@ class Combinable:
62
77
  BITRIGHTSHIFT = ">>"
63
78
  BITXOR = "#"
64
79
 
65
- def _combine(self, other, connector, reversed):
80
+ def _combine(
81
+ self, other: Any, connector: str, reversed: bool
82
+ ) -> CombinedExpression:
66
83
  if not hasattr(other, "resolve_expression"):
67
84
  # everything must be resolvable to an expression
68
85
  other = Value(other)
@@ -75,97 +92,97 @@ class Combinable:
75
92
  # OPERATORS #
76
93
  #############
77
94
 
78
- def __neg__(self):
95
+ def __neg__(self) -> CombinedExpression:
79
96
  return self._combine(-1, self.MUL, False)
80
97
 
81
- def __add__(self, other):
98
+ def __add__(self, other: Any) -> CombinedExpression:
82
99
  return self._combine(other, self.ADD, False)
83
100
 
84
- def __sub__(self, other):
101
+ def __sub__(self, other: Any) -> CombinedExpression:
85
102
  return self._combine(other, self.SUB, False)
86
103
 
87
- def __mul__(self, other):
104
+ def __mul__(self, other: Any) -> CombinedExpression:
88
105
  return self._combine(other, self.MUL, False)
89
106
 
90
- def __truediv__(self, other):
107
+ def __truediv__(self, other: Any) -> CombinedExpression:
91
108
  return self._combine(other, self.DIV, False)
92
109
 
93
- def __mod__(self, other):
110
+ def __mod__(self, other: Any) -> CombinedExpression:
94
111
  return self._combine(other, self.MOD, False)
95
112
 
96
- def __pow__(self, other):
113
+ def __pow__(self, other: Any) -> CombinedExpression:
97
114
  return self._combine(other, self.POW, False)
98
115
 
99
- def __and__(self, other):
116
+ def __and__(self, other: Any) -> Q:
100
117
  if getattr(self, "conditional", False) and getattr(other, "conditional", False):
101
- return Q(self) & Q(other)
118
+ return Q(self) & Q(other) # type: ignore[unsupported-operator]
102
119
  raise NotImplementedError(
103
120
  "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
104
121
  )
105
122
 
106
- def bitand(self, other):
123
+ def bitand(self, other: Any) -> CombinedExpression:
107
124
  return self._combine(other, self.BITAND, False)
108
125
 
109
- def bitleftshift(self, other):
126
+ def bitleftshift(self, other: Any) -> CombinedExpression:
110
127
  return self._combine(other, self.BITLEFTSHIFT, False)
111
128
 
112
- def bitrightshift(self, other):
129
+ def bitrightshift(self, other: Any) -> CombinedExpression:
113
130
  return self._combine(other, self.BITRIGHTSHIFT, False)
114
131
 
115
- def __xor__(self, other):
132
+ def __xor__(self, other: Any) -> Q:
116
133
  if getattr(self, "conditional", False) and getattr(other, "conditional", False):
117
- return Q(self) ^ Q(other)
134
+ return Q(self) ^ Q(other) # type: ignore[unsupported-operator]
118
135
  raise NotImplementedError(
119
136
  "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
120
137
  )
121
138
 
122
- def bitxor(self, other):
139
+ def bitxor(self, other: Any) -> CombinedExpression:
123
140
  return self._combine(other, self.BITXOR, False)
124
141
 
125
- def __or__(self, other):
142
+ def __or__(self, other: Any) -> Q:
126
143
  if getattr(self, "conditional", False) and getattr(other, "conditional", False):
127
- return Q(self) | Q(other)
144
+ return Q(self) | Q(other) # type: ignore[unsupported-operator]
128
145
  raise NotImplementedError(
129
146
  "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
130
147
  )
131
148
 
132
- def bitor(self, other):
149
+ def bitor(self, other: Any) -> CombinedExpression:
133
150
  return self._combine(other, self.BITOR, False)
134
151
 
135
- def __radd__(self, other):
152
+ def __radd__(self, other: Any) -> CombinedExpression:
136
153
  return self._combine(other, self.ADD, True)
137
154
 
138
- def __rsub__(self, other):
155
+ def __rsub__(self, other: Any) -> CombinedExpression:
139
156
  return self._combine(other, self.SUB, True)
140
157
 
141
- def __rmul__(self, other):
158
+ def __rmul__(self, other: Any) -> CombinedExpression:
142
159
  return self._combine(other, self.MUL, True)
143
160
 
144
- def __rtruediv__(self, other):
161
+ def __rtruediv__(self, other: Any) -> CombinedExpression:
145
162
  return self._combine(other, self.DIV, True)
146
163
 
147
- def __rmod__(self, other):
164
+ def __rmod__(self, other: Any) -> CombinedExpression:
148
165
  return self._combine(other, self.MOD, True)
149
166
 
150
- def __rpow__(self, other):
167
+ def __rpow__(self, other: Any) -> CombinedExpression:
151
168
  return self._combine(other, self.POW, True)
152
169
 
153
- def __rand__(self, other):
170
+ def __rand__(self, other: Any) -> None:
154
171
  raise NotImplementedError(
155
172
  "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
156
173
  )
157
174
 
158
- def __ror__(self, other):
175
+ def __ror__(self, other: Any) -> None:
159
176
  raise NotImplementedError(
160
177
  "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
161
178
  )
162
179
 
163
- def __rxor__(self, other):
180
+ def __rxor__(self, other: Any) -> None:
164
181
  raise NotImplementedError(
165
182
  "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
166
183
  )
167
184
 
168
- def __invert__(self):
185
+ def __invert__(self) -> NegatedExpression:
169
186
  return NegatedExpression(self)
170
187
 
171
188
 
@@ -181,29 +198,31 @@ class BaseExpression:
181
198
  # Can the expression can be used as a source expression in Window?
182
199
  window_compatible = False
183
200
 
184
- def __init__(self, output_field=None):
201
+ def __init__(self, output_field: Field | None = None):
185
202
  if output_field is not None:
186
203
  self.output_field = output_field
187
204
 
188
- def __getstate__(self):
205
+ def __getstate__(self) -> dict[str, Any]:
189
206
  state = self.__dict__.copy()
190
207
  state.pop("convert_value", None)
191
208
  return state
192
209
 
193
- def get_db_converters(self, connection):
210
+ def get_db_converters(
211
+ self, connection: BaseDatabaseWrapper
212
+ ) -> list[Callable[..., Any]]:
194
213
  return (
195
214
  []
196
- if self.convert_value is self._convert_value_noop
197
- else [self.convert_value]
198
- ) + self.output_field.get_db_converters(connection)
215
+ if self.convert_value is self._convert_value_noop # type: ignore[attr-defined]
216
+ else [self.convert_value] # type: ignore[attr-defined]
217
+ ) + self.output_field.get_db_converters(connection) # type: ignore[attr-defined]
199
218
 
200
- def get_source_expressions(self):
219
+ def get_source_expressions(self) -> list[Any]:
201
220
  return []
202
221
 
203
- def set_source_expressions(self, exprs):
222
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
204
223
  assert not exprs
205
224
 
206
- def _parse_expressions(self, *expressions):
225
+ def _parse_expressions(self, *expressions: Any) -> list[Any]:
207
226
  return [
208
227
  arg
209
228
  if hasattr(arg, "resolve_expression")
@@ -211,7 +230,9 @@ class BaseExpression:
211
230
  for arg in expressions
212
231
  ]
213
232
 
214
- def as_sql(self, compiler, connection):
233
+ def as_sql(
234
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
235
+ ) -> tuple[str, Sequence[Any]]:
215
236
  """
216
237
  Responsible for returning a (sql, [params]) tuple to be included
217
238
  in the current query.
@@ -240,27 +261,32 @@ class BaseExpression:
240
261
  raise NotImplementedError("Subclasses must implement as_sql()")
241
262
 
242
263
  @cached_property
243
- def contains_aggregate(self):
264
+ def contains_aggregate(self) -> bool:
244
265
  return any(
245
266
  expr and expr.contains_aggregate for expr in self.get_source_expressions()
246
267
  )
247
268
 
248
269
  @cached_property
249
- def contains_over_clause(self):
270
+ def contains_over_clause(self) -> bool:
250
271
  return any(
251
272
  expr and expr.contains_over_clause for expr in self.get_source_expressions()
252
273
  )
253
274
 
254
275
  @cached_property
255
- def contains_column_references(self):
276
+ def contains_column_references(self) -> bool:
256
277
  return any(
257
278
  expr and expr.contains_column_references
258
279
  for expr in self.get_source_expressions()
259
280
  )
260
281
 
261
282
  def resolve_expression(
262
- self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
263
- ):
283
+ self,
284
+ query: Any = None,
285
+ allow_joins: bool = True,
286
+ reuse: Any = None,
287
+ summarize: bool = False,
288
+ for_save: bool = False,
289
+ ) -> BaseExpression:
264
290
  """
265
291
  Provide the chance to do any preprocessing or validation before being
266
292
  added to the query.
@@ -288,15 +314,15 @@ class BaseExpression:
288
314
  return c
289
315
 
290
316
  @property
291
- def conditional(self):
292
- return isinstance(self.output_field, fields.BooleanField)
317
+ def conditional(self) -> bool:
318
+ return isinstance(self.output_field, fields.BooleanField) # type: ignore[attr-defined]
293
319
 
294
320
  @property
295
- def field(self):
296
- return self.output_field
321
+ def field(self) -> Field:
322
+ return self.output_field # type: ignore[attr-defined]
297
323
 
298
324
  @cached_property
299
- def output_field(self):
325
+ def output_field(self) -> Field:
300
326
  """Return the output type of this expressions."""
301
327
  output_field = self._resolve_output_field()
302
328
  if output_field is None:
@@ -305,7 +331,7 @@ class BaseExpression:
305
331
  return output_field
306
332
 
307
333
  @cached_property
308
- def _output_field_or_none(self):
334
+ def _output_field_or_none(self) -> Field | None:
309
335
  """
310
336
  Return the output field of this expression, or None if
311
337
  _resolve_output_field() didn't return an output type.
@@ -315,8 +341,9 @@ class BaseExpression:
315
341
  except FieldError:
316
342
  if not self._output_field_resolved_to_none:
317
343
  raise
344
+ return None
318
345
 
319
- def _resolve_output_field(self):
346
+ def _resolve_output_field(self) -> Field | None:
320
347
  """
321
348
  Attempt to infer the output type of the expression.
322
349
 
@@ -341,13 +368,16 @@ class BaseExpression:
341
368
  "set output_field."
342
369
  )
343
370
  return output_field
371
+ return None
344
372
 
345
373
  @staticmethod
346
- def _convert_value_noop(value, expression, connection):
374
+ def _convert_value_noop(
375
+ value: Any, expression: Any, connection: BaseDatabaseWrapper
376
+ ) -> Any:
347
377
  return value
348
378
 
349
379
  @cached_property
350
- def convert_value(self):
380
+ def convert_value(self) -> Callable[[Any, Any, Any], Any]:
351
381
  """
352
382
  Expressions provide their own converters because users have the option
353
383
  of manually specifying the output_field which may be a different type
@@ -375,13 +405,13 @@ class BaseExpression:
375
405
  )
376
406
  return self._convert_value_noop
377
407
 
378
- def get_lookup(self, lookup):
379
- return self.output_field.get_lookup(lookup)
408
+ def get_lookup(self, lookup: str) -> type | None:
409
+ return self.output_field.get_lookup(lookup) # type: ignore[attr-defined]
380
410
 
381
- def get_transform(self, name):
382
- return self.output_field.get_transform(name)
411
+ def get_transform(self, name: str) -> type | None:
412
+ return self.output_field.get_transform(name) # type: ignore[attr-defined]
383
413
 
384
- def relabeled_clone(self, change_map):
414
+ def relabeled_clone(self, change_map: dict[str, str]) -> BaseExpression:
385
415
  clone = self.copy()
386
416
  clone.set_source_expressions(
387
417
  [
@@ -391,7 +421,9 @@ class BaseExpression:
391
421
  )
392
422
  return clone
393
423
 
394
- def replace_expressions(self, replacements):
424
+ def replace_expressions(
425
+ self, replacements: dict[BaseExpression, Any]
426
+ ) -> BaseExpression:
395
427
  if replacement := replacements.get(self):
396
428
  return replacement
397
429
  clone = self.copy()
@@ -404,16 +436,16 @@ class BaseExpression:
404
436
  )
405
437
  return clone
406
438
 
407
- def get_refs(self):
439
+ def get_refs(self) -> set[str]:
408
440
  refs = set()
409
441
  for expr in self.get_source_expressions():
410
442
  refs |= expr.get_refs()
411
443
  return refs
412
444
 
413
- def copy(self):
445
+ def copy(self) -> BaseExpression:
414
446
  return copy.copy(self)
415
447
 
416
- def prefix_references(self, prefix):
448
+ def prefix_references(self, prefix: str) -> BaseExpression:
417
449
  clone = self.copy()
418
450
  clone.set_source_expressions(
419
451
  [
@@ -425,7 +457,7 @@ class BaseExpression:
425
457
  )
426
458
  return clone
427
459
 
428
- def get_group_by_cols(self):
460
+ def get_group_by_cols(self) -> list[BaseExpression]:
429
461
  if not self.contains_aggregate:
430
462
  return [self]
431
463
  cols = []
@@ -433,20 +465,20 @@ class BaseExpression:
433
465
  cols.extend(source.get_group_by_cols())
434
466
  return cols
435
467
 
436
- def get_source_fields(self):
468
+ def get_source_fields(self) -> list[Field | None]:
437
469
  """Return the underlying field types used by this aggregate."""
438
470
  return [e._output_field_or_none for e in self.get_source_expressions()]
439
471
 
440
- def asc(self, **kwargs):
472
+ def asc(self, **kwargs: Any) -> OrderBy:
441
473
  return OrderBy(self, **kwargs)
442
474
 
443
- def desc(self, **kwargs):
475
+ def desc(self, **kwargs: Any) -> OrderBy:
444
476
  return OrderBy(self, descending=True, **kwargs)
445
477
 
446
- def reverse_ordering(self):
478
+ def reverse_ordering(self) -> BaseExpression:
447
479
  return self
448
480
 
449
- def flatten(self):
481
+ def flatten(self) -> Iterable[Any]:
450
482
  """
451
483
  Recursively yield this expression and all subexpressions, in
452
484
  depth-first order.
@@ -459,13 +491,15 @@ class BaseExpression:
459
491
  else:
460
492
  yield expr
461
493
 
462
- def select_format(self, compiler, sql, params):
494
+ def select_format(
495
+ self, compiler: SQLCompiler, sql: str, params: Sequence[Any]
496
+ ) -> tuple[str, Sequence[Any]]:
463
497
  """
464
498
  Custom format for select clauses. For example, EXISTS expressions need
465
499
  to be wrapped in CASE WHEN on Oracle.
466
500
  """
467
- if hasattr(self.output_field, "select_format"):
468
- return self.output_field.select_format(compiler, sql, params)
501
+ if hasattr(self.output_field, "select_format"): # type: ignore[attr-defined]
502
+ return self.output_field.select_format(compiler, sql, params) # type: ignore[attr-defined]
469
503
  return sql, params
470
504
 
471
505
 
@@ -474,17 +508,17 @@ class Expression(BaseExpression, Combinable):
474
508
  """An expression that can be combined with other expressions."""
475
509
 
476
510
  @cached_property
477
- def identity(self):
511
+ def identity(self) -> tuple[Any, ...]:
478
512
  constructor_signature = inspect.signature(self.__init__)
479
- args, kwargs = self._constructor_args
513
+ args, kwargs = self._constructor_args # type: ignore[attr-defined]
480
514
  signature = constructor_signature.bind_partial(*args, **kwargs)
481
515
  signature.apply_defaults()
482
516
  arguments = signature.arguments.items()
483
- identity = [self.__class__]
517
+ identity: list[Any] = [self.__class__]
484
518
  for arg, value in arguments:
485
519
  if isinstance(value, fields.Field):
486
520
  if value.name and value.model:
487
- value = (value.model._meta.label, value.name)
521
+ value = (value.model.model_options.label, value.name)
488
522
  else:
489
523
  value = type(value)
490
524
  else:
@@ -492,12 +526,12 @@ class Expression(BaseExpression, Combinable):
492
526
  identity.append((arg, value))
493
527
  return tuple(identity)
494
528
 
495
- def __eq__(self, other):
529
+ def __eq__(self, other: object) -> bool:
496
530
  if not isinstance(other, Expression):
497
531
  return NotImplemented
498
532
  return other.identity == self.identity
499
533
 
500
- def __hash__(self):
534
+ def __hash__(self) -> int:
501
535
  return hash(self.identity)
502
536
 
503
537
 
@@ -608,7 +642,9 @@ _connector_combinations = [
608
642
  _connector_combinators = defaultdict(list)
609
643
 
610
644
 
611
- def register_combinable_fields(lhs, connector, rhs, result):
645
+ def register_combinable_fields(
646
+ lhs: type[Field], connector: str, rhs: type[Field], result: type[Field]
647
+ ) -> None:
612
648
  """
613
649
  Register combinable types:
614
650
  lhs <connector> rhs -> result
@@ -627,35 +663,40 @@ for d in _connector_combinations:
627
663
 
628
664
 
629
665
  @functools.lru_cache(maxsize=128)
630
- def _resolve_combined_type(connector, lhs_type, rhs_type):
666
+ def _resolve_combined_type(
667
+ connector: str, lhs_type: type[Field], rhs_type: type[Field]
668
+ ) -> type[Field] | None:
631
669
  combinators = _connector_combinators.get(connector, ())
632
670
  for combinator_lhs_type, combinator_rhs_type, combined_type in combinators:
633
671
  if issubclass(lhs_type, combinator_lhs_type) and issubclass(
634
672
  rhs_type, combinator_rhs_type
635
673
  ):
636
674
  return combined_type
675
+ return None
637
676
 
638
677
 
639
678
  class CombinedExpression(SQLiteNumericMixin, Expression):
640
- def __init__(self, lhs, connector, rhs, output_field=None):
679
+ def __init__(
680
+ self, lhs: Any, connector: str, rhs: Any, output_field: Field | None = None
681
+ ):
641
682
  super().__init__(output_field=output_field)
642
683
  self.connector = connector
643
684
  self.lhs = lhs
644
685
  self.rhs = rhs
645
686
 
646
- def __repr__(self):
687
+ def __repr__(self) -> str:
647
688
  return f"<{self.__class__.__name__}: {self}>"
648
689
 
649
- def __str__(self):
690
+ def __str__(self) -> str:
650
691
  return f"{self.lhs} {self.connector} {self.rhs}"
651
692
 
652
- def get_source_expressions(self):
693
+ def get_source_expressions(self) -> list[Any]:
653
694
  return [self.lhs, self.rhs]
654
695
 
655
- def set_source_expressions(self, exprs):
696
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
656
697
  self.lhs, self.rhs = exprs
657
698
 
658
- def _resolve_output_field(self):
699
+ def _resolve_output_field(self) -> Field | None:
659
700
  # We avoid using super() here for reasons given in
660
701
  # Expression._resolve_output_field()
661
702
  combined_type = _resolve_combined_type(
@@ -672,7 +713,9 @@ class CombinedExpression(SQLiteNumericMixin, Expression):
672
713
  )
673
714
  return combined_type()
674
715
 
675
- def as_sql(self, compiler, connection):
716
+ def as_sql(
717
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
718
+ ) -> tuple[str, list[Any]]:
676
719
  expressions = []
677
720
  expression_params = []
678
721
  sql, params = compiler.compile(self.lhs)
@@ -687,8 +730,13 @@ class CombinedExpression(SQLiteNumericMixin, Expression):
687
730
  return expression_wrapper % sql, expression_params
688
731
 
689
732
  def resolve_expression(
690
- self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
691
- ):
733
+ self,
734
+ query: Any = None,
735
+ allow_joins: bool = True,
736
+ reuse: Any = None,
737
+ summarize: bool = False,
738
+ for_save: bool = False,
739
+ ) -> CombinedExpression | DurationExpression | TemporalSubtraction:
692
740
  lhs = self.lhs.resolve_expression(
693
741
  query, allow_joins, reuse, summarize, for_save
694
742
  )
@@ -735,7 +783,9 @@ class CombinedExpression(SQLiteNumericMixin, Expression):
735
783
 
736
784
 
737
785
  class DurationExpression(CombinedExpression):
738
- def compile(self, side, compiler, connection):
786
+ def compile(
787
+ self, side: Any, compiler: SQLCompiler, connection: BaseDatabaseWrapper
788
+ ) -> tuple[str, Sequence[Any]]:
739
789
  try:
740
790
  output = side.output_field
741
791
  except FieldError:
@@ -746,9 +796,11 @@ class DurationExpression(CombinedExpression):
746
796
  return connection.ops.format_for_duration_arithmetic(sql), params
747
797
  return compiler.compile(side)
748
798
 
749
- def as_sql(self, compiler, connection):
799
+ def as_sql(
800
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
801
+ ) -> tuple[str, list[Any]]:
750
802
  if connection.features.has_native_duration_field:
751
- return super().as_sql(compiler, connection)
803
+ return super().as_sql(compiler, connection) # type: ignore[misc]
752
804
  connection.ops.check_expression_support(self)
753
805
  expressions = []
754
806
  expression_params = []
@@ -763,7 +815,12 @@ class DurationExpression(CombinedExpression):
763
815
  sql = connection.ops.combine_duration_expression(self.connector, expressions)
764
816
  return expression_wrapper % sql, expression_params
765
817
 
766
- def as_sqlite(self, compiler, connection, **extra_context):
818
+ def as_sqlite(
819
+ self,
820
+ compiler: SQLCompiler,
821
+ connection: BaseDatabaseWrapper,
822
+ **extra_context: Any,
823
+ ) -> tuple[str, Sequence[Any]]:
767
824
  sql, params = self.as_sql(compiler, connection, **extra_context)
768
825
  if self.connector in {Combinable.MUL, Combinable.DIV}:
769
826
  try:
@@ -788,10 +845,12 @@ class DurationExpression(CombinedExpression):
788
845
  class TemporalSubtraction(CombinedExpression):
789
846
  output_field = fields.DurationField()
790
847
 
791
- def __init__(self, lhs, rhs):
848
+ def __init__(self, lhs: Any, rhs: Any):
792
849
  super().__init__(lhs, self.SUB, rhs)
793
850
 
794
- def as_sql(self, compiler, connection):
851
+ def as_sql(
852
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
853
+ ) -> tuple[str, Sequence[Any]]:
795
854
  connection.ops.check_expression_support(self)
796
855
  lhs = compiler.compile(self.lhs)
797
856
  rhs = compiler.compile(self.rhs)
@@ -804,37 +863,44 @@ class TemporalSubtraction(CombinedExpression):
804
863
  class F(Combinable):
805
864
  """An object capable of resolving references to existing query objects."""
806
865
 
807
- def __init__(self, name):
866
+ def __init__(self, name: str):
808
867
  """
809
868
  Arguments:
810
869
  * name: the name of the field this expression references
811
870
  """
812
871
  self.name = name
813
872
 
814
- def __repr__(self):
873
+ def __repr__(self) -> str:
815
874
  return f"{self.__class__.__name__}({self.name})"
816
875
 
817
876
  def resolve_expression(
818
- self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
819
- ):
820
- return query.resolve_ref(self.name, allow_joins, reuse, summarize)
821
-
822
- def replace_expressions(self, replacements):
877
+ self,
878
+ query: Any = None,
879
+ allow_joins: bool = True,
880
+ reuse: Any = None,
881
+ summarize: bool = False,
882
+ for_save: bool = False,
883
+ ) -> Any:
884
+ return query.resolve_ref(self.name, allow_joins, reuse, summarize) # type: ignore[union-attr]
885
+
886
+ def replace_expressions(self, replacements: dict[Any, Any]) -> F:
823
887
  return replacements.get(self, self)
824
888
 
825
- def asc(self, **kwargs):
889
+ def asc(self, **kwargs: Any) -> OrderBy:
826
890
  return OrderBy(self, **kwargs)
827
891
 
828
- def desc(self, **kwargs):
892
+ def desc(self, **kwargs: Any) -> OrderBy:
829
893
  return OrderBy(self, descending=True, **kwargs)
830
894
 
831
- def __eq__(self, other):
832
- return self.__class__ == other.__class__ and self.name == other.name
895
+ def __eq__(self, other: object) -> bool:
896
+ return (
897
+ self.__class__ == other.__class__ and self.name == other.name # type: ignore[attr-defined]
898
+ )
833
899
 
834
- def __hash__(self):
900
+ def __hash__(self) -> int:
835
901
  return hash(self.name)
836
902
 
837
- def copy(self):
903
+ def copy(self) -> F:
838
904
  return copy.copy(self)
839
905
 
840
906
 
@@ -849,14 +915,14 @@ class ResolvedOuterRef(F):
849
915
  contains_aggregate = False
850
916
  contains_over_clause = False
851
917
 
852
- def as_sql(self, *args, **kwargs):
918
+ def as_sql(self, *args: Any, **kwargs: Any) -> None:
853
919
  raise ValueError(
854
920
  "This queryset contains a reference to an outer query and may "
855
921
  "only be used in a subquery."
856
922
  )
857
923
 
858
- def resolve_expression(self, *args, **kwargs):
859
- col = super().resolve_expression(*args, **kwargs)
924
+ def resolve_expression(self, *args: Any, **kwargs: Any) -> Any:
925
+ col = super().resolve_expression(*args, **kwargs) # type: ignore[misc]
860
926
  if col.contains_over_clause:
861
927
  raise NotSupportedError(
862
928
  f"Referencing outer query window expression is not supported: "
@@ -868,22 +934,22 @@ class ResolvedOuterRef(F):
868
934
  col.possibly_multivalued = LOOKUP_SEP in self.name
869
935
  return col
870
936
 
871
- def relabeled_clone(self, relabels):
937
+ def relabeled_clone(self, relabels: dict[str, str]) -> ResolvedOuterRef:
872
938
  return self
873
939
 
874
- def get_group_by_cols(self):
940
+ def get_group_by_cols(self) -> list[Any]:
875
941
  return []
876
942
 
877
943
 
878
944
  class OuterRef(F):
879
945
  contains_aggregate = False
880
946
 
881
- def resolve_expression(self, *args, **kwargs):
947
+ def resolve_expression(self, *args: Any, **kwargs: Any) -> ResolvedOuterRef | F:
882
948
  if isinstance(self.name, self.__class__):
883
949
  return self.name
884
950
  return ResolvedOuterRef(self.name)
885
951
 
886
- def relabeled_clone(self, relabels):
952
+ def relabeled_clone(self, relabels: dict[str, str]) -> OuterRef:
887
953
  return self
888
954
 
889
955
 
@@ -896,7 +962,9 @@ class Func(SQLiteNumericMixin, Expression):
896
962
  arg_joiner = ", "
897
963
  arity = None # The number of arguments the function accepts.
898
964
 
899
- def __init__(self, *expressions, output_field=None, **extra):
965
+ def __init__(
966
+ self, *expressions: Any, output_field: Field | None = None, **extra: Any
967
+ ):
900
968
  if self.arity is not None and len(expressions) != self.arity:
901
969
  raise TypeError(
902
970
  "'{}' takes exactly {} {} ({} given)".format(
@@ -910,7 +978,7 @@ class Func(SQLiteNumericMixin, Expression):
910
978
  self.source_expressions = self._parse_expressions(*expressions)
911
979
  self.extra = extra
912
980
 
913
- def __repr__(self):
981
+ def __repr__(self) -> str:
914
982
  args = self.arg_joiner.join(str(arg) for arg in self.source_expressions)
915
983
  extra = {**self.extra, **self._get_repr_options()}
916
984
  if extra:
@@ -920,19 +988,24 @@ class Func(SQLiteNumericMixin, Expression):
920
988
  return f"{self.__class__.__name__}({args}, {extra})"
921
989
  return f"{self.__class__.__name__}({args})"
922
990
 
923
- def _get_repr_options(self):
991
+ def _get_repr_options(self) -> dict[str, Any]:
924
992
  """Return a dict of extra __init__() options to include in the repr."""
925
993
  return {}
926
994
 
927
- def get_source_expressions(self):
995
+ def get_source_expressions(self) -> list[Any]:
928
996
  return self.source_expressions
929
997
 
930
- def set_source_expressions(self, exprs):
998
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
931
999
  self.source_expressions = exprs
932
1000
 
933
1001
  def resolve_expression(
934
- self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
935
- ):
1002
+ self,
1003
+ query: Any = None,
1004
+ allow_joins: bool = True,
1005
+ reuse: Any = None,
1006
+ summarize: bool = False,
1007
+ for_save: bool = False,
1008
+ ) -> Func:
936
1009
  c = self.copy()
937
1010
  c.is_summary = summarize
938
1011
  for pos, arg in enumerate(c.source_expressions):
@@ -943,13 +1016,13 @@ class Func(SQLiteNumericMixin, Expression):
943
1016
 
944
1017
  def as_sql(
945
1018
  self,
946
- compiler,
947
- connection,
948
- function=None,
949
- template=None,
950
- arg_joiner=None,
951
- **extra_context,
952
- ):
1019
+ compiler: SQLCompiler,
1020
+ connection: BaseDatabaseWrapper,
1021
+ function: str | None = None,
1022
+ template: str | None = None,
1023
+ arg_joiner: str | None = None,
1024
+ **extra_context: Any,
1025
+ ) -> tuple[str, list[Any]]:
953
1026
  connection.ops.check_expression_support(self)
954
1027
  sql_parts = []
955
1028
  params = []
@@ -980,8 +1053,8 @@ class Func(SQLiteNumericMixin, Expression):
980
1053
  data["expressions"] = data["field"] = arg_joiner.join(sql_parts)
981
1054
  return template % data, params
982
1055
 
983
- def copy(self):
984
- copy = super().copy()
1056
+ def copy(self) -> Func:
1057
+ copy = super().copy() # type: ignore[misc]
985
1058
  copy.source_expressions = self.source_expressions[:]
986
1059
  copy.extra = self.extra.copy()
987
1060
  return copy
@@ -995,7 +1068,7 @@ class Value(SQLiteNumericMixin, Expression):
995
1068
  # instances to be compiled until a decision is taken in #25425.
996
1069
  for_save = False
997
1070
 
998
- def __init__(self, value, output_field=None):
1071
+ def __init__(self, value: Any, output_field: Field | None = None):
999
1072
  """
1000
1073
  Arguments:
1001
1074
  * value: the value this expression represents. The value will be
@@ -1007,10 +1080,12 @@ class Value(SQLiteNumericMixin, Expression):
1007
1080
  super().__init__(output_field=output_field)
1008
1081
  self.value = value
1009
1082
 
1010
- def __repr__(self):
1083
+ def __repr__(self) -> str:
1011
1084
  return f"{self.__class__.__name__}({self.value!r})"
1012
1085
 
1013
- def as_sql(self, compiler, connection):
1086
+ def as_sql(
1087
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1088
+ ) -> tuple[str, list[Any]]:
1014
1089
  connection.ops.check_expression_support(self)
1015
1090
  val = self.value
1016
1091
  output_field = self._output_field_or_none
@@ -1029,16 +1104,21 @@ class Value(SQLiteNumericMixin, Expression):
1029
1104
  return "%s", [val]
1030
1105
 
1031
1106
  def resolve_expression(
1032
- self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
1033
- ):
1034
- c = super().resolve_expression(query, allow_joins, reuse, summarize, for_save)
1107
+ self,
1108
+ query: Any = None,
1109
+ allow_joins: bool = True,
1110
+ reuse: Any = None,
1111
+ summarize: bool = False,
1112
+ for_save: bool = False,
1113
+ ) -> Value:
1114
+ c = super().resolve_expression(query, allow_joins, reuse, summarize, for_save) # type: ignore[misc]
1035
1115
  c.for_save = for_save
1036
1116
  return c
1037
1117
 
1038
- def get_group_by_cols(self):
1118
+ def get_group_by_cols(self) -> list[Any]:
1039
1119
  return []
1040
1120
 
1041
- def _resolve_output_field(self):
1121
+ def _resolve_output_field(self) -> Field | None:
1042
1122
  if isinstance(self.value, str):
1043
1123
  return fields.CharField()
1044
1124
  if isinstance(self.value, bool):
@@ -1063,32 +1143,38 @@ class Value(SQLiteNumericMixin, Expression):
1063
1143
  return fields.UUIDField()
1064
1144
 
1065
1145
  @property
1066
- def empty_result_set_value(self):
1146
+ def empty_result_set_value(self) -> Any:
1067
1147
  return self.value
1068
1148
 
1069
1149
 
1070
1150
  class RawSQL(Expression):
1071
- def __init__(self, sql, params, output_field=None):
1151
+ def __init__(
1152
+ self, sql: str, params: Sequence[Any], output_field: Field | None = None
1153
+ ):
1072
1154
  if output_field is None:
1073
1155
  output_field = fields.Field()
1074
1156
  self.sql, self.params = sql, params
1075
1157
  super().__init__(output_field=output_field)
1076
1158
 
1077
- def __repr__(self):
1159
+ def __repr__(self) -> str:
1078
1160
  return f"{self.__class__.__name__}({self.sql}, {self.params})"
1079
1161
 
1080
- def as_sql(self, compiler, connection):
1162
+ def as_sql(
1163
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1164
+ ) -> tuple[str, Sequence[Any]]:
1081
1165
  return f"({self.sql})", self.params
1082
1166
 
1083
- def get_group_by_cols(self):
1167
+ def get_group_by_cols(self) -> list[RawSQL]:
1084
1168
  return [self]
1085
1169
 
1086
1170
 
1087
1171
  class Star(Expression):
1088
- def __repr__(self):
1172
+ def __repr__(self) -> str:
1089
1173
  return "'*'"
1090
1174
 
1091
- def as_sql(self, compiler, connection):
1175
+ def as_sql(
1176
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1177
+ ) -> tuple[str, list[Any]]:
1092
1178
  return "*", []
1093
1179
 
1094
1180
 
@@ -1096,34 +1182,40 @@ class Col(Expression):
1096
1182
  contains_column_references = True
1097
1183
  possibly_multivalued = False
1098
1184
 
1099
- def __init__(self, alias, target, output_field=None):
1185
+ def __init__(
1186
+ self, alias: str | None, target: Any, output_field: Field | None = None
1187
+ ):
1100
1188
  if output_field is None:
1101
1189
  output_field = target
1102
1190
  super().__init__(output_field=output_field)
1103
1191
  self.alias, self.target = alias, target
1104
1192
 
1105
- def __repr__(self):
1193
+ def __repr__(self) -> str:
1106
1194
  alias, target = self.alias, self.target
1107
1195
  identifiers = (alias, str(target)) if alias else (str(target),)
1108
1196
  return "{}({})".format(self.__class__.__name__, ", ".join(identifiers))
1109
1197
 
1110
- def as_sql(self, compiler, connection):
1198
+ def as_sql(
1199
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1200
+ ) -> tuple[str, list[Any]]:
1111
1201
  alias, column = self.alias, self.target.column
1112
1202
  identifiers = (alias, column) if alias else (column,)
1113
1203
  sql = ".".join(map(compiler.quote_name_unless_alias, identifiers))
1114
1204
  return sql, []
1115
1205
 
1116
- def relabeled_clone(self, relabels):
1206
+ def relabeled_clone(self, relabels: dict[str, str]) -> Col:
1117
1207
  if self.alias is None:
1118
1208
  return self
1119
1209
  return self.__class__(
1120
1210
  relabels.get(self.alias, self.alias), self.target, self.output_field
1121
1211
  )
1122
1212
 
1123
- def get_group_by_cols(self):
1213
+ def get_group_by_cols(self) -> list[Col]:
1124
1214
  return [self]
1125
1215
 
1126
- def get_db_converters(self, connection):
1216
+ def get_db_converters(
1217
+ self, connection: BaseDatabaseWrapper
1218
+ ) -> list[Callable[..., Any]]:
1127
1219
  if self.target == self.output_field:
1128
1220
  return self.output_field.get_db_converters(connection)
1129
1221
  return self.output_field.get_db_converters(
@@ -1137,36 +1229,43 @@ class Ref(Expression):
1137
1229
  qs.annotate(sum_cost=Sum('cost')) query.
1138
1230
  """
1139
1231
 
1140
- def __init__(self, refs, source):
1232
+ def __init__(self, refs: str, source: Any):
1141
1233
  super().__init__()
1142
1234
  self.refs, self.source = refs, source
1143
1235
 
1144
- def __repr__(self):
1236
+ def __repr__(self) -> str:
1145
1237
  return f"{self.__class__.__name__}({self.refs}, {self.source})"
1146
1238
 
1147
- def get_source_expressions(self):
1239
+ def get_source_expressions(self) -> list[Any]:
1148
1240
  return [self.source]
1149
1241
 
1150
- def set_source_expressions(self, exprs):
1242
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
1151
1243
  (self.source,) = exprs
1152
1244
 
1153
1245
  def resolve_expression(
1154
- self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
1155
- ):
1246
+ self,
1247
+ query: Any = None,
1248
+ allow_joins: bool = True,
1249
+ reuse: Any = None,
1250
+ summarize: bool = False,
1251
+ for_save: bool = False,
1252
+ ) -> Ref:
1156
1253
  # The sub-expression `source` has already been resolved, as this is
1157
1254
  # just a reference to the name of `source`.
1158
1255
  return self
1159
1256
 
1160
- def get_refs(self):
1257
+ def get_refs(self) -> set[str]:
1161
1258
  return {self.refs}
1162
1259
 
1163
- def relabeled_clone(self, relabels):
1260
+ def relabeled_clone(self, relabels: dict[str, str]) -> Ref:
1164
1261
  return self
1165
1262
 
1166
- def as_sql(self, compiler, connection):
1263
+ def as_sql(
1264
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1265
+ ) -> tuple[str, list[Any]]:
1167
1266
  return connection.ops.quote_name(self.refs), []
1168
1267
 
1169
- def get_group_by_cols(self):
1268
+ def get_group_by_cols(self) -> list[Ref]:
1170
1269
  return [self]
1171
1270
 
1172
1271
 
@@ -1179,17 +1278,22 @@ class ExpressionList(Func):
1179
1278
 
1180
1279
  template = "%(expressions)s"
1181
1280
 
1182
- def __init__(self, *expressions, **extra):
1281
+ def __init__(self, *expressions: Any, **extra: Any):
1183
1282
  if not expressions:
1184
1283
  raise ValueError(
1185
1284
  f"{self.__class__.__name__} requires at least one expression."
1186
1285
  )
1187
1286
  super().__init__(*expressions, **extra)
1188
1287
 
1189
- def __str__(self):
1288
+ def __str__(self) -> str:
1190
1289
  return self.arg_joiner.join(str(arg) for arg in self.source_expressions)
1191
1290
 
1192
- def as_sqlite(self, compiler, connection, **extra_context):
1291
+ def as_sqlite(
1292
+ self,
1293
+ compiler: SQLCompiler,
1294
+ connection: BaseDatabaseWrapper,
1295
+ **extra_context: Any,
1296
+ ) -> tuple[str, Sequence[Any]]:
1193
1297
  # Casting to numeric is unnecessary.
1194
1298
  return self.as_sql(compiler, connection, **extra_context)
1195
1299
 
@@ -1197,8 +1301,8 @@ class ExpressionList(Func):
1197
1301
  class OrderByList(Func):
1198
1302
  template = "ORDER BY %(expressions)s"
1199
1303
 
1200
- def __init__(self, *expressions, **extra):
1201
- expressions = (
1304
+ def __init__(self, *expressions: Any, **extra: Any):
1305
+ expressions_tuple = tuple(
1202
1306
  (
1203
1307
  OrderBy(F(expr[1:]), descending=True)
1204
1308
  if isinstance(expr, str) and expr[0] == "-"
@@ -1206,14 +1310,14 @@ class OrderByList(Func):
1206
1310
  )
1207
1311
  for expr in expressions
1208
1312
  )
1209
- super().__init__(*expressions, **extra)
1313
+ super().__init__(*expressions_tuple, **extra)
1210
1314
 
1211
- def as_sql(self, *args, **kwargs):
1315
+ def as_sql(self, *args: Any, **kwargs: Any) -> tuple[str, tuple[Any, ...]]:
1212
1316
  if not self.source_expressions:
1213
1317
  return "", ()
1214
- return super().as_sql(*args, **kwargs)
1318
+ return super().as_sql(*args, **kwargs) # type: ignore[misc]
1215
1319
 
1216
- def get_group_by_cols(self):
1320
+ def get_group_by_cols(self) -> list[Any]:
1217
1321
  group_by_cols = []
1218
1322
  for order_by in self.get_source_expressions():
1219
1323
  group_by_cols.extend(order_by.get_group_by_cols())
@@ -1227,42 +1331,46 @@ class ExpressionWrapper(SQLiteNumericMixin, Expression):
1227
1331
  extra context to the inner expression, such as the output_field.
1228
1332
  """
1229
1333
 
1230
- def __init__(self, expression, output_field):
1334
+ def __init__(self, expression: Any, output_field: Field):
1231
1335
  super().__init__(output_field=output_field)
1232
1336
  self.expression = expression
1233
1337
 
1234
- def set_source_expressions(self, exprs):
1338
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
1235
1339
  self.expression = exprs[0]
1236
1340
 
1237
- def get_source_expressions(self):
1341
+ def get_source_expressions(self) -> list[Any]:
1238
1342
  return [self.expression]
1239
1343
 
1240
- def get_group_by_cols(self):
1344
+ def get_group_by_cols(self) -> list[Any]:
1241
1345
  if isinstance(self.expression, Expression):
1242
1346
  expression = self.expression.copy()
1243
1347
  expression.output_field = self.output_field
1244
1348
  return expression.get_group_by_cols()
1245
1349
  # For non-expressions e.g. an SQL WHERE clause, the entire
1246
1350
  # `expression` must be included in the GROUP BY clause.
1247
- return super().get_group_by_cols()
1351
+ return super().get_group_by_cols() # type: ignore[misc]
1248
1352
 
1249
- def as_sql(self, compiler, connection):
1353
+ def as_sql(
1354
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1355
+ ) -> tuple[str, Sequence[Any]]:
1250
1356
  return compiler.compile(self.expression)
1251
1357
 
1252
- def __repr__(self):
1358
+ def __repr__(self) -> str:
1253
1359
  return f"{self.__class__.__name__}({self.expression})"
1254
1360
 
1255
1361
 
1256
1362
  class NegatedExpression(ExpressionWrapper):
1257
1363
  """The logical negation of a conditional expression."""
1258
1364
 
1259
- def __init__(self, expression):
1365
+ def __init__(self, expression: Any):
1260
1366
  super().__init__(expression, output_field=fields.BooleanField())
1261
1367
 
1262
- def __invert__(self):
1368
+ def __invert__(self) -> Any:
1263
1369
  return self.expression.copy()
1264
1370
 
1265
- def as_sql(self, compiler, connection):
1371
+ def as_sql(
1372
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1373
+ ) -> tuple[str, Sequence[Any]]:
1266
1374
  try:
1267
1375
  sql, params = super().as_sql(compiler, connection)
1268
1376
  except EmptyResultSet:
@@ -1279,8 +1387,13 @@ class NegatedExpression(ExpressionWrapper):
1279
1387
  return f"NOT {sql}", params
1280
1388
 
1281
1389
  def resolve_expression(
1282
- self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
1283
- ):
1390
+ self,
1391
+ query: Any = None,
1392
+ allow_joins: bool = True,
1393
+ reuse: Any = None,
1394
+ summarize: bool = False,
1395
+ for_save: bool = False,
1396
+ ) -> NegatedExpression:
1284
1397
  resolved = super().resolve_expression(
1285
1398
  query, allow_joins, reuse, summarize, for_save
1286
1399
  )
@@ -1288,7 +1401,9 @@ class NegatedExpression(ExpressionWrapper):
1288
1401
  raise TypeError("Cannot negate non-conditional expressions.")
1289
1402
  return resolved
1290
1403
 
1291
- def select_format(self, compiler, sql, params):
1404
+ def select_format(
1405
+ self, compiler: SQLCompiler, sql: str, params: Sequence[Any]
1406
+ ) -> tuple[str, Sequence[Any]]:
1292
1407
  # Wrap boolean expressions with a CASE WHEN expression if a database
1293
1408
  # backend (e.g. Oracle) doesn't support boolean expression in SELECT or
1294
1409
  # GROUP BY list.
@@ -1310,13 +1425,18 @@ class When(Expression):
1310
1425
  # This isn't a complete conditional expression, must be used in Case().
1311
1426
  conditional = False
1312
1427
 
1313
- def __init__(self, condition=None, then=None, **lookups):
1314
- if lookups:
1428
+ def __init__(self, condition: Any = None, then: Any = None, **lookups: Any):
1429
+ lookups_dict: dict[str, Any] | None = lookups or None
1430
+ if lookups_dict:
1315
1431
  if condition is None:
1316
- condition, lookups = Q(**lookups), None
1432
+ condition, lookups_dict = Q(**lookups_dict), None
1317
1433
  elif getattr(condition, "conditional", False):
1318
- condition, lookups = Q(condition, **lookups), None
1319
- if condition is None or not getattr(condition, "conditional", False) or lookups:
1434
+ condition, lookups_dict = Q(condition, **lookups_dict), None
1435
+ if (
1436
+ condition is None
1437
+ or not getattr(condition, "conditional", False)
1438
+ or lookups_dict
1439
+ ):
1320
1440
  raise TypeError(
1321
1441
  "When() supports a Q object, a boolean expression, or lookups "
1322
1442
  "as a condition."
@@ -1327,25 +1447,30 @@ class When(Expression):
1327
1447
  self.condition = condition
1328
1448
  self.result = self._parse_expressions(then)[0]
1329
1449
 
1330
- def __str__(self):
1450
+ def __str__(self) -> str:
1331
1451
  return f"WHEN {self.condition!r} THEN {self.result!r}"
1332
1452
 
1333
- def __repr__(self):
1453
+ def __repr__(self) -> str:
1334
1454
  return f"<{self.__class__.__name__}: {self}>"
1335
1455
 
1336
- def get_source_expressions(self):
1456
+ def get_source_expressions(self) -> list[Any]:
1337
1457
  return [self.condition, self.result]
1338
1458
 
1339
- def set_source_expressions(self, exprs):
1459
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
1340
1460
  self.condition, self.result = exprs
1341
1461
 
1342
- def get_source_fields(self):
1462
+ def get_source_fields(self) -> list[Field | None]:
1343
1463
  # We're only interested in the fields of the result expressions.
1344
1464
  return [self.result._output_field_or_none]
1345
1465
 
1346
1466
  def resolve_expression(
1347
- self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
1348
- ):
1467
+ self,
1468
+ query: Any = None,
1469
+ allow_joins: bool = True,
1470
+ reuse: Any = None,
1471
+ summarize: bool = False,
1472
+ for_save: bool = False,
1473
+ ) -> When:
1349
1474
  c = self.copy()
1350
1475
  c.is_summary = summarize
1351
1476
  if hasattr(c.condition, "resolve_expression"):
@@ -1357,7 +1482,13 @@ class When(Expression):
1357
1482
  )
1358
1483
  return c
1359
1484
 
1360
- def as_sql(self, compiler, connection, template=None, **extra_context):
1485
+ def as_sql(
1486
+ self,
1487
+ compiler: SQLCompiler,
1488
+ connection: BaseDatabaseWrapper,
1489
+ template: str | None = None,
1490
+ **extra_context: Any,
1491
+ ) -> tuple[str, tuple[Any, ...]]:
1361
1492
  connection.ops.check_expression_support(self)
1362
1493
  template_params = extra_context
1363
1494
  sql_params = []
@@ -1372,7 +1503,7 @@ class When(Expression):
1372
1503
  *result_params,
1373
1504
  )
1374
1505
 
1375
- def get_group_by_cols(self):
1506
+ def get_group_by_cols(self) -> list[Any]:
1376
1507
  # This is not a complete expression and cannot be used in GROUP BY.
1377
1508
  cols = []
1378
1509
  for source in self.get_source_expressions():
@@ -1397,7 +1528,13 @@ class Case(SQLiteNumericMixin, Expression):
1397
1528
  template = "CASE %(cases)s ELSE %(default)s END"
1398
1529
  case_joiner = " "
1399
1530
 
1400
- def __init__(self, *cases, default=None, output_field=None, **extra):
1531
+ def __init__(
1532
+ self,
1533
+ *cases: When,
1534
+ default: Any = None,
1535
+ output_field: Field | None = None,
1536
+ **extra: Any,
1537
+ ):
1401
1538
  if not all(isinstance(case, When) for case in cases):
1402
1539
  raise TypeError("Positional arguments must all be When objects.")
1403
1540
  super().__init__(output_field)
@@ -1405,24 +1542,29 @@ class Case(SQLiteNumericMixin, Expression):
1405
1542
  self.default = self._parse_expressions(default)[0]
1406
1543
  self.extra = extra
1407
1544
 
1408
- def __str__(self):
1545
+ def __str__(self) -> str:
1409
1546
  return "CASE {}, ELSE {!r}".format(
1410
1547
  ", ".join(str(c) for c in self.cases),
1411
1548
  self.default,
1412
1549
  )
1413
1550
 
1414
- def __repr__(self):
1551
+ def __repr__(self) -> str:
1415
1552
  return f"<{self.__class__.__name__}: {self}>"
1416
1553
 
1417
- def get_source_expressions(self):
1554
+ def get_source_expressions(self) -> list[Any]:
1418
1555
  return self.cases + [self.default]
1419
1556
 
1420
- def set_source_expressions(self, exprs):
1557
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
1421
1558
  *self.cases, self.default = exprs
1422
1559
 
1423
1560
  def resolve_expression(
1424
- self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
1425
- ):
1561
+ self,
1562
+ query: Any = None,
1563
+ allow_joins: bool = True,
1564
+ reuse: Any = None,
1565
+ summarize: bool = False,
1566
+ for_save: bool = False,
1567
+ ) -> Case:
1426
1568
  c = self.copy()
1427
1569
  c.is_summary = summarize
1428
1570
  for pos, case in enumerate(c.cases):
@@ -1434,17 +1576,23 @@ class Case(SQLiteNumericMixin, Expression):
1434
1576
  )
1435
1577
  return c
1436
1578
 
1437
- def copy(self):
1438
- c = super().copy()
1579
+ def copy(self) -> Case:
1580
+ c = super().copy() # type: ignore[misc]
1439
1581
  c.cases = c.cases[:]
1440
1582
  return c
1441
1583
 
1442
1584
  def as_sql(
1443
- self, compiler, connection, template=None, case_joiner=None, **extra_context
1444
- ):
1585
+ self,
1586
+ compiler: SQLCompiler,
1587
+ connection: BaseDatabaseWrapper,
1588
+ template: str | None = None,
1589
+ case_joiner: str | None = None,
1590
+ **extra_context: Any,
1591
+ ) -> tuple[str, list[Any]]:
1445
1592
  connection.ops.check_expression_support(self)
1446
1593
  if not self.cases:
1447
- return compiler.compile(self.default)
1594
+ sql, params = compiler.compile(self.default)
1595
+ return sql, list(params)
1448
1596
  template_params = {**self.extra, **extra_context}
1449
1597
  case_parts = []
1450
1598
  sql_params = []
@@ -1460,7 +1608,7 @@ class Case(SQLiteNumericMixin, Expression):
1460
1608
  case_parts.append(case_sql)
1461
1609
  sql_params.extend(case_params)
1462
1610
  if not case_parts:
1463
- return default_sql, default_params
1611
+ return default_sql, list(default_params)
1464
1612
  case_joiner = case_joiner or self.case_joiner
1465
1613
  template_params["cases"] = case_joiner.join(case_parts)
1466
1614
  template_params["default"] = default_sql
@@ -1471,10 +1619,10 @@ class Case(SQLiteNumericMixin, Expression):
1471
1619
  sql = connection.ops.unification_cast_sql(self.output_field) % sql
1472
1620
  return sql, sql_params
1473
1621
 
1474
- def get_group_by_cols(self):
1622
+ def get_group_by_cols(self) -> list[Any]:
1475
1623
  if not self.cases:
1476
1624
  return self.default.get_group_by_cols()
1477
- return super().get_group_by_cols()
1625
+ return super().get_group_by_cols() # type: ignore[misc]
1478
1626
 
1479
1627
 
1480
1628
  class Subquery(BaseExpression, Combinable):
@@ -1487,35 +1635,41 @@ class Subquery(BaseExpression, Combinable):
1487
1635
  contains_aggregate = False
1488
1636
  empty_result_set_value = None
1489
1637
 
1490
- def __init__(self, queryset, output_field=None, **extra):
1638
+ def __init__(self, queryset: Any, output_field: Field | None = None, **extra: Any):
1491
1639
  # Allow the usage of both QuerySet and sql.Query objects.
1492
1640
  self.query = getattr(queryset, "query", queryset).clone()
1493
1641
  self.query.subquery = True
1494
1642
  self.extra = extra
1495
1643
  super().__init__(output_field)
1496
1644
 
1497
- def get_source_expressions(self):
1645
+ def get_source_expressions(self) -> list[Any]:
1498
1646
  return [self.query]
1499
1647
 
1500
- def set_source_expressions(self, exprs):
1648
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
1501
1649
  self.query = exprs[0]
1502
1650
 
1503
- def _resolve_output_field(self):
1651
+ def _resolve_output_field(self) -> Field | None:
1504
1652
  return self.query.output_field
1505
1653
 
1506
- def copy(self):
1654
+ def copy(self) -> Subquery:
1507
1655
  clone = super().copy()
1508
1656
  clone.query = clone.query.clone()
1509
1657
  return clone
1510
1658
 
1511
1659
  @property
1512
- def external_aliases(self):
1660
+ def external_aliases(self) -> list[str]:
1513
1661
  return self.query.external_aliases
1514
1662
 
1515
- def get_external_cols(self):
1663
+ def get_external_cols(self) -> list[Any]:
1516
1664
  return self.query.get_external_cols()
1517
1665
 
1518
- def as_sql(self, compiler, connection, template=None, **extra_context):
1666
+ def as_sql(
1667
+ self,
1668
+ compiler: SQLCompiler,
1669
+ connection: BaseDatabaseWrapper,
1670
+ template: str | None = None,
1671
+ **extra_context: Any,
1672
+ ) -> tuple[str, tuple[Any, ...]]:
1519
1673
  connection.ops.check_expression_support(self)
1520
1674
  template_params = {**self.extra, **extra_context}
1521
1675
  subquery_sql, sql_params = self.query.as_sql(compiler, connection)
@@ -1525,7 +1679,7 @@ class Subquery(BaseExpression, Combinable):
1525
1679
  sql = template % template_params
1526
1680
  return sql, sql_params
1527
1681
 
1528
- def get_group_by_cols(self):
1682
+ def get_group_by_cols(self) -> list[Any]:
1529
1683
  return self.query.get_group_by_cols(wrapper=self)
1530
1684
 
1531
1685
 
@@ -1534,11 +1688,13 @@ class Exists(Subquery):
1534
1688
  output_field = fields.BooleanField()
1535
1689
  empty_result_set_value = False
1536
1690
 
1537
- def __init__(self, queryset, **kwargs):
1691
+ def __init__(self, queryset: Any, **kwargs: Any):
1538
1692
  super().__init__(queryset, **kwargs)
1539
1693
  self.query = self.query.exists()
1540
1694
 
1541
- def select_format(self, compiler, sql, params):
1695
+ def select_format(
1696
+ self, compiler: SQLCompiler, sql: str, params: Sequence[Any]
1697
+ ) -> tuple[str, Sequence[Any]]:
1542
1698
  # Wrap EXISTS() with a CASE WHEN expression if a database backend
1543
1699
  # (e.g. Oracle) doesn't support boolean expression in SELECT or GROUP
1544
1700
  # BY list.
@@ -1552,7 +1708,13 @@ class OrderBy(Expression):
1552
1708
  template = "%(expression)s %(ordering)s"
1553
1709
  conditional = False
1554
1710
 
1555
- def __init__(self, expression, descending=False, nulls_first=None, nulls_last=None):
1711
+ def __init__(
1712
+ self,
1713
+ expression: Any,
1714
+ descending: bool = False,
1715
+ nulls_first: bool | None = None,
1716
+ nulls_last: bool | None = None,
1717
+ ):
1556
1718
  if nulls_first and nulls_last:
1557
1719
  raise ValueError("nulls_first and nulls_last are mutually exclusive")
1558
1720
  if nulls_first is False or nulls_last is False:
@@ -1564,16 +1726,22 @@ class OrderBy(Expression):
1564
1726
  raise ValueError("expression must be an expression type")
1565
1727
  self.expression = expression
1566
1728
 
1567
- def __repr__(self):
1729
+ def __repr__(self) -> str:
1568
1730
  return f"{self.__class__.__name__}({self.expression}, descending={self.descending})"
1569
1731
 
1570
- def set_source_expressions(self, exprs):
1732
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
1571
1733
  self.expression = exprs[0]
1572
1734
 
1573
- def get_source_expressions(self):
1735
+ def get_source_expressions(self) -> list[Any]:
1574
1736
  return [self.expression]
1575
1737
 
1576
- def as_sql(self, compiler, connection, template=None, **extra_context):
1738
+ def as_sql(
1739
+ self,
1740
+ compiler: SQLCompiler,
1741
+ connection: BaseDatabaseWrapper,
1742
+ template: str | None = None,
1743
+ **extra_context: Any,
1744
+ ) -> tuple[str, tuple[Any, ...]]:
1577
1745
  template = template or self.template
1578
1746
  if connection.features.supports_order_by_nulls_modifier:
1579
1747
  if self.nulls_last:
@@ -1599,13 +1767,13 @@ class OrderBy(Expression):
1599
1767
  params *= template.count("%(expression)s")
1600
1768
  return (template % placeholders).rstrip(), params
1601
1769
 
1602
- def get_group_by_cols(self):
1770
+ def get_group_by_cols(self) -> list[Any]:
1603
1771
  cols = []
1604
1772
  for source in self.get_source_expressions():
1605
1773
  cols.extend(source.get_group_by_cols())
1606
1774
  return cols
1607
1775
 
1608
- def reverse_ordering(self):
1776
+ def reverse_ordering(self) -> OrderBy:
1609
1777
  self.descending = not self.descending
1610
1778
  if self.nulls_first:
1611
1779
  self.nulls_last = True
@@ -1615,10 +1783,10 @@ class OrderBy(Expression):
1615
1783
  self.nulls_last = None
1616
1784
  return self
1617
1785
 
1618
- def asc(self):
1786
+ def asc(self) -> None:
1619
1787
  self.descending = False
1620
1788
 
1621
- def desc(self):
1789
+ def desc(self) -> None:
1622
1790
  self.descending = True
1623
1791
 
1624
1792
 
@@ -1632,11 +1800,11 @@ class Window(SQLiteNumericMixin, Expression):
1632
1800
 
1633
1801
  def __init__(
1634
1802
  self,
1635
- expression,
1636
- partition_by=None,
1637
- order_by=None,
1638
- frame=None,
1639
- output_field=None,
1803
+ expression: Any,
1804
+ partition_by: Any = None,
1805
+ order_by: Any = None,
1806
+ frame: Any = None,
1807
+ output_field: Field | None = None,
1640
1808
  ):
1641
1809
  self.partition_by = partition_by
1642
1810
  self.order_by = order_by
@@ -1665,16 +1833,21 @@ class Window(SQLiteNumericMixin, Expression):
1665
1833
  super().__init__(output_field=output_field)
1666
1834
  self.source_expression = self._parse_expressions(expression)[0]
1667
1835
 
1668
- def _resolve_output_field(self):
1836
+ def _resolve_output_field(self) -> Field | None:
1669
1837
  return self.source_expression.output_field
1670
1838
 
1671
- def get_source_expressions(self):
1839
+ def get_source_expressions(self) -> list[Any]:
1672
1840
  return [self.source_expression, self.partition_by, self.order_by, self.frame]
1673
1841
 
1674
- def set_source_expressions(self, exprs):
1842
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
1675
1843
  self.source_expression, self.partition_by, self.order_by, self.frame = exprs
1676
1844
 
1677
- def as_sql(self, compiler, connection, template=None):
1845
+ def as_sql(
1846
+ self,
1847
+ compiler: SQLCompiler,
1848
+ connection: BaseDatabaseWrapper,
1849
+ template: str | None = None,
1850
+ ) -> tuple[str, tuple[Any, ...]]:
1678
1851
  connection.ops.check_expression_support(self)
1679
1852
  if not connection.features.supports_over_clause:
1680
1853
  raise NotSupportedError("This backend does not support window expressions.")
@@ -1707,7 +1880,9 @@ class Window(SQLiteNumericMixin, Expression):
1707
1880
  (*params, *window_params),
1708
1881
  )
1709
1882
 
1710
- def as_sqlite(self, compiler, connection):
1883
+ def as_sqlite(
1884
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1885
+ ) -> tuple[str, Sequence[Any]]:
1711
1886
  if isinstance(self.output_field, fields.DecimalField):
1712
1887
  # Casting to numeric must be outside of the window expression.
1713
1888
  copy = self.copy()
@@ -1717,7 +1892,7 @@ class Window(SQLiteNumericMixin, Expression):
1717
1892
  return super(Window, copy).as_sqlite(compiler, connection)
1718
1893
  return self.as_sql(compiler, connection)
1719
1894
 
1720
- def __str__(self):
1895
+ def __str__(self) -> str:
1721
1896
  return "{} OVER ({}{}{})".format(
1722
1897
  str(self.source_expression),
1723
1898
  "PARTITION BY " + str(self.partition_by) if self.partition_by else "",
@@ -1725,10 +1900,10 @@ class Window(SQLiteNumericMixin, Expression):
1725
1900
  str(self.frame or ""),
1726
1901
  )
1727
1902
 
1728
- def __repr__(self):
1903
+ def __repr__(self) -> str:
1729
1904
  return f"<{self.__class__.__name__}: {self}>"
1730
1905
 
1731
- def get_group_by_cols(self):
1906
+ def get_group_by_cols(self) -> list[Any]:
1732
1907
  group_by_cols = []
1733
1908
  if self.partition_by:
1734
1909
  group_by_cols.extend(self.partition_by.get_group_by_cols())
@@ -1748,17 +1923,19 @@ class WindowFrame(Expression):
1748
1923
 
1749
1924
  template = "%(frame_type)s BETWEEN %(start)s AND %(end)s"
1750
1925
 
1751
- def __init__(self, start=None, end=None):
1926
+ def __init__(self, start: int | None = None, end: int | None = None):
1752
1927
  self.start = Value(start)
1753
1928
  self.end = Value(end)
1754
1929
 
1755
- def set_source_expressions(self, exprs):
1930
+ def set_source_expressions(self, exprs: Sequence[Any]) -> None:
1756
1931
  self.start, self.end = exprs
1757
1932
 
1758
- def get_source_expressions(self):
1933
+ def get_source_expressions(self) -> list[Any]:
1759
1934
  return [self.start, self.end]
1760
1935
 
1761
- def as_sql(self, compiler, connection):
1936
+ def as_sql(
1937
+ self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
1938
+ ) -> tuple[str, list[Any]]:
1762
1939
  connection.ops.check_expression_support(self)
1763
1940
  start, end = self.window_frame_start_end(
1764
1941
  connection, self.start.value, self.end.value
@@ -1773,13 +1950,13 @@ class WindowFrame(Expression):
1773
1950
  [],
1774
1951
  )
1775
1952
 
1776
- def __repr__(self):
1953
+ def __repr__(self) -> str:
1777
1954
  return f"<{self.__class__.__name__}: {self}>"
1778
1955
 
1779
- def get_group_by_cols(self):
1956
+ def get_group_by_cols(self) -> list[Any]:
1780
1957
  return []
1781
1958
 
1782
- def __str__(self):
1959
+ def __str__(self) -> str:
1783
1960
  if self.start.value is not None and self.start.value < 0:
1784
1961
  start = f"{abs(self.start.value)} {db_connection.ops.PRECEDING}"
1785
1962
  elif self.start.value is not None and self.start.value == 0:
@@ -1799,19 +1976,25 @@ class WindowFrame(Expression):
1799
1976
  "end": end,
1800
1977
  }
1801
1978
 
1802
- def window_frame_start_end(self, connection, start, end):
1979
+ def window_frame_start_end(
1980
+ self, connection: BaseDatabaseWrapper, start: int | None, end: int | None
1981
+ ) -> tuple[str, str]:
1803
1982
  raise NotImplementedError("Subclasses must implement window_frame_start_end().")
1804
1983
 
1805
1984
 
1806
1985
  class RowRange(WindowFrame):
1807
1986
  frame_type = "ROWS"
1808
1987
 
1809
- def window_frame_start_end(self, connection, start, end):
1988
+ def window_frame_start_end(
1989
+ self, connection: BaseDatabaseWrapper, start: int | None, end: int | None
1990
+ ) -> tuple[str, str]:
1810
1991
  return connection.ops.window_frame_rows_start_end(start, end)
1811
1992
 
1812
1993
 
1813
1994
  class ValueRange(WindowFrame):
1814
1995
  frame_type = "RANGE"
1815
1996
 
1816
- def window_frame_start_end(self, connection, start, end):
1997
+ def window_frame_start_end(
1998
+ self, connection: BaseDatabaseWrapper, start: int | None, end: int | None
1999
+ ) -> tuple[str, str]:
1817
2000
  return connection.ops.window_frame_range_start_end(start, end)