plain.models 0.49.2__py3-none-any.whl → 0.50.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plain/models/CHANGELOG.md +13 -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 +31 -22
- 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.2.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.2.dist-info/RECORD +0 -122
- {plain_models-0.49.2.dist-info → plain_models-0.50.0.dist-info}/WHEEL +0 -0
- {plain_models-0.49.2.dist-info → plain_models-0.50.0.dist-info}/entry_points.txt +0 -0
- {plain_models-0.49.2.dist-info → plain_models-0.50.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,14 +1,23 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
from functools import cached_property
|
4
|
+
from typing import TYPE_CHECKING, Any
|
2
5
|
|
3
6
|
from plain import models
|
7
|
+
from plain.models.base import ModelBase
|
4
8
|
from plain.models.migrations.operations.base import Operation
|
5
9
|
from plain.models.migrations.state import ModelState
|
6
10
|
from plain.models.migrations.utils import field_references, resolve_relation
|
7
11
|
|
8
12
|
from .fields import AddField, AlterField, FieldOperation, RemoveField, RenameField
|
9
13
|
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
from plain.models.backends.base.schema import BaseDatabaseSchemaEditor
|
16
|
+
from plain.models.fields import Field
|
17
|
+
from plain.models.migrations.state import ProjectState
|
18
|
+
|
10
19
|
|
11
|
-
def _check_for_duplicates(arg_name, objs):
|
20
|
+
def _check_for_duplicates(arg_name: str, objs: Any) -> None:
|
12
21
|
used_vals = set()
|
13
22
|
for val in objs:
|
14
23
|
if val in used_vals:
|
@@ -19,22 +28,24 @@ def _check_for_duplicates(arg_name, objs):
|
|
19
28
|
|
20
29
|
|
21
30
|
class ModelOperation(Operation):
|
22
|
-
def __init__(self, name):
|
31
|
+
def __init__(self, name: str) -> None:
|
23
32
|
self.name = name
|
24
33
|
|
25
34
|
@cached_property
|
26
|
-
def name_lower(self):
|
35
|
+
def name_lower(self) -> str:
|
27
36
|
return self.name.lower()
|
28
37
|
|
29
|
-
def references_model(self, name, package_label):
|
38
|
+
def references_model(self, name: str, package_label: str) -> bool:
|
30
39
|
return name.lower() == self.name_lower
|
31
40
|
|
32
|
-
def reduce(
|
33
|
-
|
41
|
+
def reduce(
|
42
|
+
self, operation: Operation, package_label: str
|
43
|
+
) -> bool | list[Operation]:
|
44
|
+
return super().reduce(operation, package_label) or self.can_reduce_through( # type: ignore[misc]
|
34
45
|
operation, package_label
|
35
46
|
)
|
36
47
|
|
37
|
-
def can_reduce_through(self, operation, package_label):
|
48
|
+
def can_reduce_through(self, operation: Operation, package_label: str) -> bool:
|
38
49
|
return not operation.references_model(self.name, package_label)
|
39
50
|
|
40
51
|
|
@@ -43,7 +54,13 @@ class CreateModel(ModelOperation):
|
|
43
54
|
|
44
55
|
serialization_expand_args = ["fields", "options"]
|
45
56
|
|
46
|
-
def __init__(
|
57
|
+
def __init__(
|
58
|
+
self,
|
59
|
+
name: str,
|
60
|
+
fields: list[tuple[str, Field]],
|
61
|
+
options: dict[str, Any] | None = None,
|
62
|
+
bases: tuple[Any, ...] | None = None,
|
63
|
+
) -> None:
|
47
64
|
self.fields = fields
|
48
65
|
self.options = options or {}
|
49
66
|
self.bases = bases or (models.Model,)
|
@@ -53,7 +70,7 @@ class CreateModel(ModelOperation):
|
|
53
70
|
_check_for_duplicates(
|
54
71
|
"bases",
|
55
72
|
(
|
56
|
-
base._meta.label_lower
|
73
|
+
base._meta.label_lower # type: ignore[attr-defined]
|
57
74
|
if hasattr(base, "_meta")
|
58
75
|
else base.lower()
|
59
76
|
if isinstance(base, str)
|
@@ -62,8 +79,8 @@ class CreateModel(ModelOperation):
|
|
62
79
|
),
|
63
80
|
)
|
64
81
|
|
65
|
-
def deconstruct(self):
|
66
|
-
kwargs = {
|
82
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
83
|
+
kwargs: dict[str, Any] = {
|
67
84
|
"name": self.name,
|
68
85
|
"fields": self.fields,
|
69
86
|
}
|
@@ -73,7 +90,7 @@ class CreateModel(ModelOperation):
|
|
73
90
|
kwargs["bases"] = self.bases
|
74
91
|
return (self.__class__.__qualname__, [], kwargs)
|
75
92
|
|
76
|
-
def state_forwards(self, package_label, state):
|
93
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
77
94
|
state.add_model(
|
78
95
|
ModelState(
|
79
96
|
package_label,
|
@@ -84,19 +101,25 @@ class CreateModel(ModelOperation):
|
|
84
101
|
)
|
85
102
|
)
|
86
103
|
|
87
|
-
def database_forwards(
|
88
|
-
|
104
|
+
def database_forwards(
|
105
|
+
self,
|
106
|
+
package_label: str,
|
107
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
108
|
+
from_state: ProjectState,
|
109
|
+
to_state: ProjectState,
|
110
|
+
) -> None:
|
111
|
+
model = to_state.models_registry.get_model(package_label, self.name) # type: ignore[attr-defined]
|
89
112
|
if self.allow_migrate_model(schema_editor.connection, model):
|
90
113
|
schema_editor.create_model(model)
|
91
114
|
|
92
|
-
def describe(self):
|
115
|
+
def describe(self) -> str:
|
93
116
|
return f"Create model {self.name}"
|
94
117
|
|
95
118
|
@property
|
96
|
-
def migration_name_fragment(self):
|
119
|
+
def migration_name_fragment(self) -> str:
|
97
120
|
return self.name_lower
|
98
121
|
|
99
|
-
def references_model(self, name, package_label):
|
122
|
+
def references_model(self, name: str, package_label: str) -> bool:
|
100
123
|
name_lower = name.lower()
|
101
124
|
if name_lower == self.name_lower:
|
102
125
|
return True
|
@@ -106,7 +129,7 @@ class CreateModel(ModelOperation):
|
|
106
129
|
for base in self.bases:
|
107
130
|
if (
|
108
131
|
base is not models.Model
|
109
|
-
and isinstance(base,
|
132
|
+
and isinstance(base, ModelBase | str)
|
110
133
|
and resolve_relation(base, package_label) == reference_model_tuple
|
111
134
|
):
|
112
135
|
return True
|
@@ -119,7 +142,9 @@ class CreateModel(ModelOperation):
|
|
119
142
|
return True
|
120
143
|
return False
|
121
144
|
|
122
|
-
def reduce(
|
145
|
+
def reduce(
|
146
|
+
self, operation: Operation, package_label: str
|
147
|
+
) -> bool | list[Operation]:
|
123
148
|
if (
|
124
149
|
isinstance(operation, DeleteModel)
|
125
150
|
and self.name_lower == operation.name_lower
|
@@ -213,104 +238,118 @@ class CreateModel(ModelOperation):
|
|
213
238
|
class DeleteModel(ModelOperation):
|
214
239
|
"""Drop a model's table."""
|
215
240
|
|
216
|
-
def deconstruct(self):
|
217
|
-
kwargs = {
|
241
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
242
|
+
kwargs: dict[str, Any] = {
|
218
243
|
"name": self.name,
|
219
244
|
}
|
220
245
|
return (self.__class__.__qualname__, [], kwargs)
|
221
246
|
|
222
|
-
def state_forwards(self, package_label, state):
|
247
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
223
248
|
state.remove_model(package_label, self.name_lower)
|
224
249
|
|
225
|
-
def database_forwards(
|
226
|
-
|
250
|
+
def database_forwards(
|
251
|
+
self,
|
252
|
+
package_label: str,
|
253
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
254
|
+
from_state: ProjectState,
|
255
|
+
to_state: ProjectState,
|
256
|
+
) -> None:
|
257
|
+
model = from_state.models_registry.get_model(package_label, self.name) # type: ignore[attr-defined]
|
227
258
|
if self.allow_migrate_model(schema_editor.connection, model):
|
228
259
|
schema_editor.delete_model(model)
|
229
260
|
|
230
|
-
def references_model(self, name, package_label):
|
261
|
+
def references_model(self, name: str, package_label: str) -> bool:
|
231
262
|
# The deleted model could be referencing the specified model through
|
232
263
|
# related fields.
|
233
264
|
return True
|
234
265
|
|
235
|
-
def describe(self):
|
266
|
+
def describe(self) -> str:
|
236
267
|
return f"Delete model {self.name}"
|
237
268
|
|
238
269
|
@property
|
239
|
-
def migration_name_fragment(self):
|
270
|
+
def migration_name_fragment(self) -> str:
|
240
271
|
return f"delete_{self.name_lower}"
|
241
272
|
|
242
273
|
|
243
274
|
class RenameModel(ModelOperation):
|
244
275
|
"""Rename a model."""
|
245
276
|
|
246
|
-
def __init__(self, old_name, new_name):
|
277
|
+
def __init__(self, old_name: str, new_name: str) -> None:
|
247
278
|
self.old_name = old_name
|
248
279
|
self.new_name = new_name
|
249
280
|
super().__init__(old_name)
|
250
281
|
|
251
282
|
@cached_property
|
252
|
-
def old_name_lower(self):
|
283
|
+
def old_name_lower(self) -> str:
|
253
284
|
return self.old_name.lower()
|
254
285
|
|
255
286
|
@cached_property
|
256
|
-
def new_name_lower(self):
|
287
|
+
def new_name_lower(self) -> str:
|
257
288
|
return self.new_name.lower()
|
258
289
|
|
259
|
-
def deconstruct(self):
|
260
|
-
kwargs = {
|
290
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
291
|
+
kwargs: dict[str, Any] = {
|
261
292
|
"old_name": self.old_name,
|
262
293
|
"new_name": self.new_name,
|
263
294
|
}
|
264
295
|
return (self.__class__.__qualname__, [], kwargs)
|
265
296
|
|
266
|
-
def state_forwards(self, package_label, state):
|
297
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
267
298
|
state.rename_model(package_label, self.old_name, self.new_name)
|
268
299
|
|
269
|
-
def database_forwards(
|
270
|
-
|
300
|
+
def database_forwards(
|
301
|
+
self,
|
302
|
+
package_label: str,
|
303
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
304
|
+
from_state: ProjectState,
|
305
|
+
to_state: ProjectState,
|
306
|
+
) -> None:
|
307
|
+
new_model = to_state.models_registry.get_model(package_label, self.new_name) # type: ignore[attr-defined]
|
271
308
|
if self.allow_migrate_model(schema_editor.connection, new_model):
|
272
|
-
old_model = from_state.models_registry.get_model(
|
309
|
+
old_model = from_state.models_registry.get_model( # type: ignore[attr-defined]
|
273
310
|
package_label, self.old_name
|
274
311
|
)
|
275
312
|
# Move the main table
|
276
313
|
schema_editor.alter_db_table(
|
277
314
|
new_model,
|
278
|
-
old_model._meta.db_table,
|
279
|
-
new_model._meta.db_table,
|
315
|
+
old_model._meta.db_table, # type: ignore[attr-defined]
|
316
|
+
new_model._meta.db_table, # type: ignore[attr-defined]
|
280
317
|
)
|
281
318
|
# Alter the fields pointing to us
|
282
|
-
for related_object in old_model._meta.related_objects:
|
283
|
-
if related_object.related_model == old_model:
|
319
|
+
for related_object in old_model._meta.related_objects: # type: ignore[attr-defined]
|
320
|
+
if related_object.related_model == old_model: # type: ignore[attr-defined]
|
284
321
|
model = new_model
|
285
322
|
related_key = (package_label, self.new_name_lower)
|
286
323
|
else:
|
287
|
-
model = related_object.related_model
|
324
|
+
model = related_object.related_model # type: ignore[attr-defined]
|
288
325
|
related_key = (
|
289
|
-
related_object.related_model._meta.package_label,
|
290
|
-
related_object.related_model._meta.model_name,
|
326
|
+
related_object.related_model._meta.package_label, # type: ignore[attr-defined]
|
327
|
+
related_object.related_model._meta.model_name, # type: ignore[attr-defined]
|
291
328
|
)
|
292
|
-
to_field = to_state.models_registry.get_model(
|
329
|
+
to_field = to_state.models_registry.get_model( # type: ignore[attr-defined]
|
293
330
|
*related_key
|
294
|
-
)._meta.get_field(related_object.field.name)
|
331
|
+
)._meta.get_field(related_object.field.name) # type: ignore[attr-defined]
|
295
332
|
schema_editor.alter_field(
|
296
333
|
model,
|
297
|
-
related_object.field,
|
334
|
+
related_object.field, # type: ignore[attr-defined]
|
298
335
|
to_field,
|
299
336
|
)
|
300
337
|
|
301
|
-
def references_model(self, name, package_label):
|
338
|
+
def references_model(self, name: str, package_label: str) -> bool:
|
302
339
|
return (
|
303
340
|
name.lower() == self.old_name_lower or name.lower() == self.new_name_lower
|
304
341
|
)
|
305
342
|
|
306
|
-
def describe(self):
|
343
|
+
def describe(self) -> str:
|
307
344
|
return f"Rename model {self.old_name} to {self.new_name}"
|
308
345
|
|
309
346
|
@property
|
310
|
-
def migration_name_fragment(self):
|
347
|
+
def migration_name_fragment(self) -> str:
|
311
348
|
return f"rename_{self.old_name_lower}_{self.new_name_lower}"
|
312
349
|
|
313
|
-
def reduce(
|
350
|
+
def reduce(
|
351
|
+
self, operation: Operation, package_label: str
|
352
|
+
) -> bool | list[Operation]:
|
314
353
|
if (
|
315
354
|
isinstance(operation, RenameModel)
|
316
355
|
and self.new_name_lower == operation.old_name_lower
|
@@ -323,13 +362,15 @@ class RenameModel(ModelOperation):
|
|
323
362
|
]
|
324
363
|
# Skip `ModelOperation.reduce` as we want to run `references_model`
|
325
364
|
# against self.new_name.
|
326
|
-
return super(ModelOperation, self).reduce(
|
365
|
+
return super(ModelOperation, self).reduce( # type: ignore[misc]
|
327
366
|
operation, package_label
|
328
367
|
) or not operation.references_model(self.new_name, package_label)
|
329
368
|
|
330
369
|
|
331
370
|
class ModelOptionOperation(ModelOperation):
|
332
|
-
def reduce(
|
371
|
+
def reduce(
|
372
|
+
self, operation: Operation, package_label: str
|
373
|
+
) -> bool | list[Operation]:
|
333
374
|
if (
|
334
375
|
isinstance(operation, self.__class__ | DeleteModel)
|
335
376
|
and self.name_lower == operation.name_lower
|
@@ -341,75 +382,87 @@ class ModelOptionOperation(ModelOperation):
|
|
341
382
|
class AlterModelTable(ModelOptionOperation):
|
342
383
|
"""Rename a model's table."""
|
343
384
|
|
344
|
-
def __init__(self, name, table):
|
385
|
+
def __init__(self, name: str, table: str | None) -> None:
|
345
386
|
self.table = table
|
346
387
|
super().__init__(name)
|
347
388
|
|
348
|
-
def deconstruct(self):
|
349
|
-
kwargs = {
|
389
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
390
|
+
kwargs: dict[str, Any] = {
|
350
391
|
"name": self.name,
|
351
392
|
"table": self.table,
|
352
393
|
}
|
353
394
|
return (self.__class__.__qualname__, [], kwargs)
|
354
395
|
|
355
|
-
def state_forwards(self, package_label, state):
|
396
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
356
397
|
state.alter_model_options(
|
357
398
|
package_label, self.name_lower, {"db_table": self.table}
|
358
399
|
)
|
359
400
|
|
360
|
-
def database_forwards(
|
361
|
-
|
401
|
+
def database_forwards(
|
402
|
+
self,
|
403
|
+
package_label: str,
|
404
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
405
|
+
from_state: ProjectState,
|
406
|
+
to_state: ProjectState,
|
407
|
+
) -> None:
|
408
|
+
new_model = to_state.models_registry.get_model(package_label, self.name) # type: ignore[attr-defined]
|
362
409
|
if self.allow_migrate_model(schema_editor.connection, new_model):
|
363
|
-
old_model = from_state.models_registry.get_model(package_label, self.name)
|
410
|
+
old_model = from_state.models_registry.get_model(package_label, self.name) # type: ignore[attr-defined]
|
364
411
|
schema_editor.alter_db_table(
|
365
412
|
new_model,
|
366
|
-
old_model._meta.db_table,
|
367
|
-
new_model._meta.db_table,
|
413
|
+
old_model._meta.db_table, # type: ignore[attr-defined]
|
414
|
+
new_model._meta.db_table, # type: ignore[attr-defined]
|
368
415
|
)
|
369
416
|
|
370
|
-
def describe(self):
|
417
|
+
def describe(self) -> str:
|
371
418
|
return "Rename table for {} to {}".format(
|
372
419
|
self.name,
|
373
420
|
self.table if self.table is not None else "(default)",
|
374
421
|
)
|
375
422
|
|
376
423
|
@property
|
377
|
-
def migration_name_fragment(self):
|
424
|
+
def migration_name_fragment(self) -> str:
|
378
425
|
return f"alter_{self.name_lower}_table"
|
379
426
|
|
380
427
|
|
381
428
|
class AlterModelTableComment(ModelOptionOperation):
|
382
|
-
def __init__(self, name, table_comment):
|
429
|
+
def __init__(self, name: str, table_comment: str | None) -> None:
|
383
430
|
self.table_comment = table_comment
|
384
431
|
super().__init__(name)
|
385
432
|
|
386
|
-
def deconstruct(self):
|
387
|
-
kwargs = {
|
433
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
434
|
+
kwargs: dict[str, Any] = {
|
388
435
|
"name": self.name,
|
389
436
|
"table_comment": self.table_comment,
|
390
437
|
}
|
391
438
|
return (self.__class__.__qualname__, [], kwargs)
|
392
439
|
|
393
|
-
def state_forwards(self, package_label, state):
|
440
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
394
441
|
state.alter_model_options(
|
395
442
|
package_label, self.name_lower, {"db_table_comment": self.table_comment}
|
396
443
|
)
|
397
444
|
|
398
|
-
def database_forwards(
|
399
|
-
|
445
|
+
def database_forwards(
|
446
|
+
self,
|
447
|
+
package_label: str,
|
448
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
449
|
+
from_state: ProjectState,
|
450
|
+
to_state: ProjectState,
|
451
|
+
) -> None:
|
452
|
+
new_model = to_state.models_registry.get_model(package_label, self.name) # type: ignore[attr-defined]
|
400
453
|
if self.allow_migrate_model(schema_editor.connection, new_model):
|
401
|
-
old_model = from_state.models_registry.get_model(package_label, self.name)
|
454
|
+
old_model = from_state.models_registry.get_model(package_label, self.name) # type: ignore[attr-defined]
|
402
455
|
schema_editor.alter_db_table_comment(
|
403
456
|
new_model,
|
404
|
-
old_model._meta.db_table_comment,
|
405
|
-
new_model._meta.db_table_comment,
|
457
|
+
old_model._meta.db_table_comment, # type: ignore[attr-defined]
|
458
|
+
new_model._meta.db_table_comment, # type: ignore[attr-defined]
|
406
459
|
)
|
407
460
|
|
408
|
-
def describe(self):
|
461
|
+
def describe(self) -> str:
|
409
462
|
return f"Alter {self.name} table comment"
|
410
463
|
|
411
464
|
@property
|
412
|
-
def migration_name_fragment(self):
|
465
|
+
def migration_name_fragment(self) -> str:
|
413
466
|
return f"alter_{self.name_lower}_table_comment"
|
414
467
|
|
415
468
|
|
@@ -425,18 +478,18 @@ class AlterModelOptions(ModelOptionOperation):
|
|
425
478
|
"ordering",
|
426
479
|
]
|
427
480
|
|
428
|
-
def __init__(self, name, options):
|
481
|
+
def __init__(self, name: str, options: dict[str, Any]) -> None:
|
429
482
|
self.options = options
|
430
483
|
super().__init__(name)
|
431
484
|
|
432
|
-
def deconstruct(self):
|
433
|
-
kwargs = {
|
485
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
486
|
+
kwargs: dict[str, Any] = {
|
434
487
|
"name": self.name,
|
435
488
|
"options": self.options,
|
436
489
|
}
|
437
490
|
return (self.__class__.__qualname__, [], kwargs)
|
438
491
|
|
439
|
-
def state_forwards(self, package_label, state):
|
492
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
440
493
|
state.alter_model_options(
|
441
494
|
package_label,
|
442
495
|
self.name_lower,
|
@@ -444,14 +497,20 @@ class AlterModelOptions(ModelOptionOperation):
|
|
444
497
|
self.ALTER_OPTION_KEYS,
|
445
498
|
)
|
446
499
|
|
447
|
-
def database_forwards(
|
500
|
+
def database_forwards(
|
501
|
+
self,
|
502
|
+
package_label: str,
|
503
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
504
|
+
from_state: ProjectState,
|
505
|
+
to_state: ProjectState,
|
506
|
+
) -> None:
|
448
507
|
pass
|
449
508
|
|
450
|
-
def describe(self):
|
509
|
+
def describe(self) -> str:
|
451
510
|
return f"Change Meta options on {self.name}"
|
452
511
|
|
453
512
|
@property
|
454
|
-
def migration_name_fragment(self):
|
513
|
+
def migration_name_fragment(self) -> str:
|
455
514
|
return f"alter_{self.name_lower}_options"
|
456
515
|
|
457
516
|
|
@@ -459,32 +518,38 @@ class IndexOperation(Operation):
|
|
459
518
|
option_name = "indexes"
|
460
519
|
|
461
520
|
@cached_property
|
462
|
-
def model_name_lower(self):
|
463
|
-
return self.model_name.lower()
|
521
|
+
def model_name_lower(self) -> str:
|
522
|
+
return self.model_name.lower() # type: ignore[attr-defined]
|
464
523
|
|
465
524
|
|
466
525
|
class AddIndex(IndexOperation):
|
467
526
|
"""Add an index on a model."""
|
468
527
|
|
469
|
-
def __init__(self, model_name, index):
|
528
|
+
def __init__(self, model_name: str, index: Any) -> None:
|
470
529
|
self.model_name = model_name
|
471
|
-
if not index.name:
|
530
|
+
if not index.name: # type: ignore[attr-defined]
|
472
531
|
raise ValueError(
|
473
532
|
"Indexes passed to AddIndex operations require a name "
|
474
533
|
f"argument. {index!r} doesn't have one."
|
475
534
|
)
|
476
535
|
self.index = index
|
477
536
|
|
478
|
-
def state_forwards(self, package_label, state):
|
537
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
479
538
|
state.add_index(package_label, self.model_name_lower, self.index)
|
480
539
|
|
481
|
-
def database_forwards(
|
482
|
-
|
540
|
+
def database_forwards(
|
541
|
+
self,
|
542
|
+
package_label: str,
|
543
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
544
|
+
from_state: ProjectState,
|
545
|
+
to_state: ProjectState,
|
546
|
+
) -> None:
|
547
|
+
model = to_state.models_registry.get_model(package_label, self.model_name) # type: ignore[attr-defined]
|
483
548
|
if self.allow_migrate_model(schema_editor.connection, model):
|
484
549
|
schema_editor.add_index(model, self.index)
|
485
550
|
|
486
|
-
def deconstruct(self):
|
487
|
-
kwargs = {
|
551
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
552
|
+
kwargs: dict[str, Any] = {
|
488
553
|
"model_name": self.model_name,
|
489
554
|
"index": self.index,
|
490
555
|
}
|
@@ -494,43 +559,49 @@ class AddIndex(IndexOperation):
|
|
494
559
|
kwargs,
|
495
560
|
)
|
496
561
|
|
497
|
-
def describe(self):
|
498
|
-
if self.index.expressions:
|
562
|
+
def describe(self) -> str:
|
563
|
+
if self.index.expressions: # type: ignore[attr-defined]
|
499
564
|
return "Create index {} on {} on model {}".format(
|
500
|
-
self.index.name,
|
501
|
-
", ".join([str(expression) for expression in self.index.expressions]),
|
565
|
+
self.index.name, # type: ignore[attr-defined]
|
566
|
+
", ".join([str(expression) for expression in self.index.expressions]), # type: ignore[attr-defined]
|
502
567
|
self.model_name,
|
503
568
|
)
|
504
569
|
return "Create index {} on field(s) {} of model {}".format(
|
505
|
-
self.index.name,
|
506
|
-
", ".join(self.index.fields),
|
570
|
+
self.index.name, # type: ignore[attr-defined]
|
571
|
+
", ".join(self.index.fields), # type: ignore[attr-defined]
|
507
572
|
self.model_name,
|
508
573
|
)
|
509
574
|
|
510
575
|
@property
|
511
|
-
def migration_name_fragment(self):
|
512
|
-
return f"{self.model_name_lower}_{self.index.name.lower()}"
|
576
|
+
def migration_name_fragment(self) -> str:
|
577
|
+
return f"{self.model_name_lower}_{self.index.name.lower()}" # type: ignore[attr-defined]
|
513
578
|
|
514
579
|
|
515
580
|
class RemoveIndex(IndexOperation):
|
516
581
|
"""Remove an index from a model."""
|
517
582
|
|
518
|
-
def __init__(self, model_name, name):
|
583
|
+
def __init__(self, model_name: str, name: str) -> None:
|
519
584
|
self.model_name = model_name
|
520
585
|
self.name = name
|
521
586
|
|
522
|
-
def state_forwards(self, package_label, state):
|
587
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
523
588
|
state.remove_index(package_label, self.model_name_lower, self.name)
|
524
589
|
|
525
|
-
def database_forwards(
|
526
|
-
|
590
|
+
def database_forwards(
|
591
|
+
self,
|
592
|
+
package_label: str,
|
593
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
594
|
+
from_state: ProjectState,
|
595
|
+
to_state: ProjectState,
|
596
|
+
) -> None:
|
597
|
+
model = from_state.models_registry.get_model(package_label, self.model_name) # type: ignore[attr-defined]
|
527
598
|
if self.allow_migrate_model(schema_editor.connection, model):
|
528
599
|
from_model_state = from_state.models[package_label, self.model_name_lower]
|
529
600
|
index = from_model_state.get_index_by_name(self.name)
|
530
601
|
schema_editor.remove_index(model, index)
|
531
602
|
|
532
|
-
def deconstruct(self):
|
533
|
-
kwargs = {
|
603
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
604
|
+
kwargs: dict[str, Any] = {
|
534
605
|
"model_name": self.model_name,
|
535
606
|
"name": self.name,
|
536
607
|
}
|
@@ -540,18 +611,24 @@ class RemoveIndex(IndexOperation):
|
|
540
611
|
kwargs,
|
541
612
|
)
|
542
613
|
|
543
|
-
def describe(self):
|
614
|
+
def describe(self) -> str:
|
544
615
|
return f"Remove index {self.name} from {self.model_name}"
|
545
616
|
|
546
617
|
@property
|
547
|
-
def migration_name_fragment(self):
|
618
|
+
def migration_name_fragment(self) -> str:
|
548
619
|
return f"remove_{self.model_name_lower}_{self.name.lower()}"
|
549
620
|
|
550
621
|
|
551
622
|
class RenameIndex(IndexOperation):
|
552
623
|
"""Rename an index."""
|
553
624
|
|
554
|
-
def __init__(
|
625
|
+
def __init__(
|
626
|
+
self,
|
627
|
+
model_name: str,
|
628
|
+
new_name: str,
|
629
|
+
old_name: str | None = None,
|
630
|
+
old_fields: list[str] | tuple[str, ...] | None = None,
|
631
|
+
) -> None:
|
555
632
|
if not old_name and not old_fields:
|
556
633
|
raise ValueError(
|
557
634
|
"RenameIndex requires one of old_name and old_fields arguments to be "
|
@@ -567,15 +644,15 @@ class RenameIndex(IndexOperation):
|
|
567
644
|
self.old_fields = old_fields
|
568
645
|
|
569
646
|
@cached_property
|
570
|
-
def old_name_lower(self):
|
571
|
-
return self.old_name.lower()
|
647
|
+
def old_name_lower(self) -> str:
|
648
|
+
return self.old_name.lower() # type: ignore[union-attr]
|
572
649
|
|
573
650
|
@cached_property
|
574
|
-
def new_name_lower(self):
|
651
|
+
def new_name_lower(self) -> str:
|
575
652
|
return self.new_name.lower()
|
576
653
|
|
577
|
-
def deconstruct(self):
|
578
|
-
kwargs = {
|
654
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
655
|
+
kwargs: dict[str, Any] = {
|
579
656
|
"model_name": self.model_name,
|
580
657
|
"new_name": self.new_name,
|
581
658
|
}
|
@@ -585,7 +662,7 @@ class RenameIndex(IndexOperation):
|
|
585
662
|
kwargs["old_fields"] = self.old_fields
|
586
663
|
return (self.__class__.__qualname__, [], kwargs)
|
587
664
|
|
588
|
-
def state_forwards(self, package_label, state):
|
665
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
589
666
|
if self.old_fields:
|
590
667
|
state.add_index(
|
591
668
|
package_label,
|
@@ -594,20 +671,30 @@ class RenameIndex(IndexOperation):
|
|
594
671
|
)
|
595
672
|
else:
|
596
673
|
state.rename_index(
|
597
|
-
package_label,
|
674
|
+
package_label,
|
675
|
+
self.model_name_lower,
|
676
|
+
self.old_name,
|
677
|
+
self.new_name, # type: ignore[arg-type]
|
598
678
|
)
|
599
679
|
|
600
|
-
def database_forwards(
|
601
|
-
|
680
|
+
def database_forwards(
|
681
|
+
self,
|
682
|
+
package_label: str,
|
683
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
684
|
+
from_state: ProjectState,
|
685
|
+
to_state: ProjectState,
|
686
|
+
) -> None:
|
687
|
+
model = to_state.models_registry.get_model(package_label, self.model_name) # type: ignore[attr-defined]
|
602
688
|
if not self.allow_migrate_model(schema_editor.connection, model):
|
603
|
-
return
|
689
|
+
return None
|
604
690
|
|
605
691
|
if self.old_fields:
|
606
|
-
from_model = from_state.models_registry.get_model(
|
692
|
+
from_model = from_state.models_registry.get_model( # type: ignore[attr-defined]
|
607
693
|
package_label, self.model_name
|
608
694
|
)
|
609
695
|
columns = [
|
610
|
-
from_model._meta.get_field(field).column
|
696
|
+
from_model._meta.get_field(field).column # type: ignore[attr-defined]
|
697
|
+
for field in self.old_fields
|
611
698
|
]
|
612
699
|
matching_index_name = schema_editor._constraint_names(
|
613
700
|
from_model, column_names=columns, index=True
|
@@ -616,7 +703,7 @@ class RenameIndex(IndexOperation):
|
|
616
703
|
raise ValueError(
|
617
704
|
"Found wrong number ({}) of indexes for {}({}).".format(
|
618
705
|
len(matching_index_name),
|
619
|
-
from_model._meta.db_table,
|
706
|
+
from_model._meta.db_table, # type: ignore[attr-defined]
|
620
707
|
", ".join(columns),
|
621
708
|
)
|
622
709
|
)
|
@@ -626,16 +713,17 @@ class RenameIndex(IndexOperation):
|
|
626
713
|
)
|
627
714
|
else:
|
628
715
|
from_model_state = from_state.models[package_label, self.model_name_lower]
|
629
|
-
old_index = from_model_state.get_index_by_name(self.old_name)
|
716
|
+
old_index = from_model_state.get_index_by_name(self.old_name) # type: ignore[arg-type]
|
630
717
|
# Don't alter when the index name is not changed.
|
631
|
-
if old_index.name == self.new_name:
|
632
|
-
return
|
718
|
+
if old_index.name == self.new_name: # type: ignore[attr-defined]
|
719
|
+
return None
|
633
720
|
|
634
721
|
to_model_state = to_state.models[package_label, self.model_name_lower]
|
635
722
|
new_index = to_model_state.get_index_by_name(self.new_name)
|
636
723
|
schema_editor.rename_index(model, old_index, new_index)
|
724
|
+
return None
|
637
725
|
|
638
|
-
def describe(self):
|
726
|
+
def describe(self) -> str:
|
639
727
|
if self.old_name:
|
640
728
|
return (
|
641
729
|
f"Rename index {self.old_name} on {self.model_name} to {self.new_name}"
|
@@ -646,16 +734,18 @@ class RenameIndex(IndexOperation):
|
|
646
734
|
)
|
647
735
|
|
648
736
|
@property
|
649
|
-
def migration_name_fragment(self):
|
737
|
+
def migration_name_fragment(self) -> str:
|
650
738
|
if self.old_name:
|
651
739
|
return f"rename_{self.old_name_lower}_{self.new_name_lower}"
|
652
740
|
return "rename_{}_{}_{}".format(
|
653
741
|
self.model_name_lower,
|
654
|
-
"_".join(self.old_fields),
|
742
|
+
"_".join(self.old_fields), # type: ignore[arg-type]
|
655
743
|
self.new_name_lower,
|
656
744
|
)
|
657
745
|
|
658
|
-
def reduce(
|
746
|
+
def reduce(
|
747
|
+
self, operation: Operation, package_label: str
|
748
|
+
) -> bool | list[Operation]:
|
659
749
|
if (
|
660
750
|
isinstance(operation, RenameIndex)
|
661
751
|
and self.model_name_lower == operation.model_name_lower
|
@@ -676,19 +766,25 @@ class RenameIndex(IndexOperation):
|
|
676
766
|
class AddConstraint(IndexOperation):
|
677
767
|
option_name = "constraints"
|
678
768
|
|
679
|
-
def __init__(self, model_name, constraint):
|
769
|
+
def __init__(self, model_name: str, constraint: Any) -> None:
|
680
770
|
self.model_name = model_name
|
681
771
|
self.constraint = constraint
|
682
772
|
|
683
|
-
def state_forwards(self, package_label, state):
|
773
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
684
774
|
state.add_constraint(package_label, self.model_name_lower, self.constraint)
|
685
775
|
|
686
|
-
def database_forwards(
|
687
|
-
|
776
|
+
def database_forwards(
|
777
|
+
self,
|
778
|
+
package_label: str,
|
779
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
780
|
+
from_state: ProjectState,
|
781
|
+
to_state: ProjectState,
|
782
|
+
) -> None:
|
783
|
+
model = to_state.models_registry.get_model(package_label, self.model_name) # type: ignore[attr-defined]
|
688
784
|
if self.allow_migrate_model(schema_editor.connection, model):
|
689
785
|
schema_editor.add_constraint(model, self.constraint)
|
690
786
|
|
691
|
-
def deconstruct(self):
|
787
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
692
788
|
return (
|
693
789
|
self.__class__.__name__,
|
694
790
|
[],
|
@@ -698,32 +794,38 @@ class AddConstraint(IndexOperation):
|
|
698
794
|
},
|
699
795
|
)
|
700
796
|
|
701
|
-
def describe(self):
|
702
|
-
return f"Create constraint {self.constraint.name} on model {self.model_name}"
|
797
|
+
def describe(self) -> str:
|
798
|
+
return f"Create constraint {self.constraint.name} on model {self.model_name}" # type: ignore[attr-defined]
|
703
799
|
|
704
800
|
@property
|
705
|
-
def migration_name_fragment(self):
|
706
|
-
return f"{self.model_name_lower}_{self.constraint.name.lower()}"
|
801
|
+
def migration_name_fragment(self) -> str:
|
802
|
+
return f"{self.model_name_lower}_{self.constraint.name.lower()}" # type: ignore[attr-defined]
|
707
803
|
|
708
804
|
|
709
805
|
class RemoveConstraint(IndexOperation):
|
710
806
|
option_name = "constraints"
|
711
807
|
|
712
|
-
def __init__(self, model_name, name):
|
808
|
+
def __init__(self, model_name: str, name: str) -> None:
|
713
809
|
self.model_name = model_name
|
714
810
|
self.name = name
|
715
811
|
|
716
|
-
def state_forwards(self, package_label, state):
|
812
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
717
813
|
state.remove_constraint(package_label, self.model_name_lower, self.name)
|
718
814
|
|
719
|
-
def database_forwards(
|
720
|
-
|
815
|
+
def database_forwards(
|
816
|
+
self,
|
817
|
+
package_label: str,
|
818
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
819
|
+
from_state: ProjectState,
|
820
|
+
to_state: ProjectState,
|
821
|
+
) -> None:
|
822
|
+
model = to_state.models_registry.get_model(package_label, self.model_name) # type: ignore[attr-defined]
|
721
823
|
if self.allow_migrate_model(schema_editor.connection, model):
|
722
824
|
from_model_state = from_state.models[package_label, self.model_name_lower]
|
723
825
|
constraint = from_model_state.get_constraint_by_name(self.name)
|
724
826
|
schema_editor.remove_constraint(model, constraint)
|
725
827
|
|
726
|
-
def deconstruct(self):
|
828
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
727
829
|
return (
|
728
830
|
self.__class__.__name__,
|
729
831
|
[],
|
@@ -733,9 +835,9 @@ class RemoveConstraint(IndexOperation):
|
|
733
835
|
},
|
734
836
|
)
|
735
837
|
|
736
|
-
def describe(self):
|
838
|
+
def describe(self) -> str:
|
737
839
|
return f"Remove constraint {self.name} from model {self.model_name}"
|
738
840
|
|
739
841
|
@property
|
740
|
-
def migration_name_fragment(self):
|
842
|
+
def migration_name_fragment(self) -> str:
|
741
843
|
return f"remove_{self.model_name_lower}_{self.name.lower()}"
|