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