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