piccolo 1.27.1__py3-none-any.whl → 1.29.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.
- piccolo/__init__.py +1 -1
- piccolo/apps/app/commands/new.py +3 -3
- piccolo/apps/asgi/commands/new.py +2 -3
- piccolo/apps/asgi/commands/templates/app/_blacksheep_app.py.jinja +57 -29
- piccolo/apps/asgi/commands/templates/app/_esmerald_app.py.jinja +48 -21
- piccolo/apps/asgi/commands/templates/app/_falcon_app.py.jinja +63 -8
- piccolo/apps/asgi/commands/templates/app/_fastapi_app.py.jinja +51 -24
- piccolo/apps/asgi/commands/templates/app/_litestar_app.py.jinja +34 -10
- piccolo/apps/asgi/commands/templates/app/_quart_app.py.jinja +38 -15
- piccolo/apps/asgi/commands/templates/app/_sanic_app.py.jinja +34 -11
- piccolo/apps/fixtures/commands/dump.py +8 -8
- piccolo/apps/fixtures/commands/load.py +5 -5
- piccolo/apps/fixtures/commands/shared.py +9 -9
- piccolo/apps/migrations/auto/diffable_table.py +12 -12
- piccolo/apps/migrations/auto/migration_manager.py +59 -66
- piccolo/apps/migrations/auto/operations.py +14 -14
- piccolo/apps/migrations/auto/schema_differ.py +35 -34
- piccolo/apps/migrations/auto/schema_snapshot.py +3 -4
- piccolo/apps/migrations/auto/serialisation.py +27 -24
- piccolo/apps/migrations/auto/serialisation_legacy.py +2 -2
- piccolo/apps/migrations/commands/backwards.py +1 -2
- piccolo/apps/migrations/commands/base.py +12 -12
- piccolo/apps/migrations/commands/check.py +2 -3
- piccolo/apps/migrations/commands/clean.py +3 -3
- piccolo/apps/migrations/commands/forwards.py +1 -2
- piccolo/apps/migrations/commands/new.py +6 -6
- piccolo/apps/migrations/tables.py +3 -3
- piccolo/apps/playground/commands/run.py +72 -13
- piccolo/apps/schema/commands/generate.py +49 -49
- piccolo/apps/schema/commands/graph.py +5 -5
- piccolo/apps/shell/commands/run.py +1 -2
- piccolo/apps/sql_shell/commands/run.py +4 -4
- piccolo/apps/tester/commands/run.py +3 -3
- piccolo/apps/user/commands/change_permissions.py +6 -6
- piccolo/apps/user/commands/create.py +7 -7
- piccolo/apps/user/commands/list.py +2 -2
- piccolo/apps/user/tables.py +8 -8
- piccolo/columns/base.py +84 -52
- piccolo/columns/choices.py +2 -2
- piccolo/columns/column_types.py +299 -177
- piccolo/columns/combination.py +15 -12
- piccolo/columns/defaults/base.py +4 -4
- piccolo/columns/defaults/date.py +4 -3
- piccolo/columns/defaults/interval.py +4 -3
- piccolo/columns/defaults/time.py +4 -3
- piccolo/columns/defaults/timestamp.py +4 -3
- piccolo/columns/defaults/timestamptz.py +4 -3
- piccolo/columns/defaults/uuid.py +3 -2
- piccolo/columns/m2m.py +28 -35
- piccolo/columns/readable.py +4 -3
- piccolo/columns/reference.py +9 -9
- piccolo/conf/apps.py +53 -54
- piccolo/custom_types.py +28 -6
- piccolo/engine/base.py +14 -14
- piccolo/engine/cockroach.py +5 -4
- piccolo/engine/finder.py +2 -2
- piccolo/engine/postgres.py +20 -19
- piccolo/engine/sqlite.py +23 -22
- piccolo/query/base.py +30 -29
- piccolo/query/functions/__init__.py +12 -0
- piccolo/query/functions/aggregate.py +4 -3
- piccolo/query/functions/array.py +151 -0
- piccolo/query/functions/base.py +3 -3
- piccolo/query/functions/datetime.py +22 -22
- piccolo/query/functions/string.py +4 -4
- piccolo/query/functions/type_conversion.py +30 -15
- piccolo/query/methods/alter.py +47 -46
- piccolo/query/methods/count.py +11 -10
- piccolo/query/methods/create.py +6 -5
- piccolo/query/methods/create_index.py +9 -8
- piccolo/query/methods/delete.py +7 -6
- piccolo/query/methods/drop_index.py +7 -6
- piccolo/query/methods/exists.py +6 -5
- piccolo/query/methods/indexes.py +4 -4
- piccolo/query/methods/insert.py +21 -14
- piccolo/query/methods/objects.py +60 -50
- piccolo/query/methods/raw.py +7 -6
- piccolo/query/methods/refresh.py +8 -7
- piccolo/query/methods/select.py +56 -49
- piccolo/query/methods/table_exists.py +5 -5
- piccolo/query/methods/update.py +8 -7
- piccolo/query/mixins.py +56 -61
- piccolo/query/operators/json.py +11 -11
- piccolo/query/proxy.py +8 -9
- piccolo/querystring.py +14 -15
- piccolo/schema.py +10 -10
- piccolo/table.py +105 -98
- piccolo/table_reflection.py +9 -9
- piccolo/testing/model_builder.py +16 -13
- piccolo/testing/random_builder.py +14 -2
- piccolo/testing/test_case.py +4 -4
- piccolo/utils/dictionary.py +3 -3
- piccolo/utils/encoding.py +5 -5
- piccolo/utils/lazy_loader.py +3 -3
- piccolo/utils/list.py +7 -8
- piccolo/utils/objects.py +4 -6
- piccolo/utils/pydantic.py +21 -24
- piccolo/utils/sql_values.py +3 -3
- piccolo/utils/sync.py +4 -3
- piccolo/utils/warnings.py +1 -2
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/METADATA +1 -1
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/RECORD +132 -131
- tests/apps/fixtures/commands/test_dump_load.py +1 -2
- tests/apps/migrations/auto/integration/test_migrations.py +32 -7
- tests/apps/migrations/auto/test_migration_manager.py +2 -2
- tests/apps/migrations/auto/test_schema_differ.py +22 -23
- tests/apps/migrations/commands/test_forwards_backwards.py +3 -3
- tests/columns/m2m/base.py +20 -49
- tests/columns/test_array.py +176 -10
- tests/columns/test_boolean.py +2 -4
- tests/columns/test_combination.py +29 -1
- tests/columns/test_db_column_name.py +2 -2
- tests/engine/test_extra_nodes.py +2 -2
- tests/engine/test_pool.py +3 -3
- tests/engine/test_transaction.py +4 -4
- tests/query/test_freeze.py +4 -4
- tests/table/instance/test_get_related.py +2 -2
- tests/table/test_alter.py +4 -4
- tests/table/test_indexes.py +1 -2
- tests/table/test_metaclass.py +7 -3
- tests/table/test_refresh.py +2 -2
- tests/table/test_select.py +58 -0
- tests/table/test_str.py +30 -22
- tests/table/test_update.py +18 -3
- tests/testing/test_model_builder.py +1 -2
- tests/testing/test_random_builder.py +5 -0
- tests/utils/test_pydantic.py +152 -134
- tests/utils/test_table_reflection.py +1 -2
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/WHEEL +0 -0
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/entry_points.txt +0 -0
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/licenses/LICENSE +0 -0
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/top_level.txt +0 -0
@@ -2,8 +2,9 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import inspect
|
4
4
|
import logging
|
5
|
-
import
|
5
|
+
from collections.abc import Callable, Coroutine
|
6
6
|
from dataclasses import dataclass, field
|
7
|
+
from typing import Any, Optional, Union
|
7
8
|
|
8
9
|
from piccolo.apps.migrations.auto.diffable_table import DiffableTable
|
9
10
|
from piccolo.apps.migrations.auto.operations import (
|
@@ -32,19 +33,19 @@ class AddColumnClass:
|
|
32
33
|
column: Column
|
33
34
|
table_class_name: str
|
34
35
|
tablename: str
|
35
|
-
schema:
|
36
|
+
schema: Optional[str]
|
36
37
|
|
37
38
|
|
38
39
|
@dataclass
|
39
40
|
class AddColumnCollection:
|
40
|
-
add_columns:
|
41
|
+
add_columns: list[AddColumnClass] = field(default_factory=list)
|
41
42
|
|
42
43
|
def append(self, add_column: AddColumnClass):
|
43
44
|
self.add_columns.append(add_column)
|
44
45
|
|
45
46
|
def for_table_class_name(
|
46
47
|
self, table_class_name: str
|
47
|
-
) ->
|
48
|
+
) -> list[AddColumnClass]:
|
48
49
|
return [
|
49
50
|
i
|
50
51
|
for i in self.add_columns
|
@@ -53,7 +54,7 @@ class AddColumnCollection:
|
|
53
54
|
|
54
55
|
def columns_for_table_class_name(
|
55
56
|
self, table_class_name: str
|
56
|
-
) ->
|
57
|
+
) -> list[Column]:
|
57
58
|
return [
|
58
59
|
i.column
|
59
60
|
for i in self.add_columns
|
@@ -61,20 +62,18 @@ class AddColumnCollection:
|
|
61
62
|
]
|
62
63
|
|
63
64
|
@property
|
64
|
-
def table_class_names(self) ->
|
65
|
+
def table_class_names(self) -> list[str]:
|
65
66
|
return list({i.table_class_name for i in self.add_columns})
|
66
67
|
|
67
68
|
|
68
69
|
@dataclass
|
69
70
|
class DropColumnCollection:
|
70
|
-
drop_columns:
|
71
|
+
drop_columns: list[DropColumn] = field(default_factory=list)
|
71
72
|
|
72
73
|
def append(self, drop_column: DropColumn):
|
73
74
|
self.drop_columns.append(drop_column)
|
74
75
|
|
75
|
-
def for_table_class_name(
|
76
|
-
self, table_class_name: str
|
77
|
-
) -> t.List[DropColumn]:
|
76
|
+
def for_table_class_name(self, table_class_name: str) -> list[DropColumn]:
|
78
77
|
return [
|
79
78
|
i
|
80
79
|
for i in self.drop_columns
|
@@ -82,20 +81,20 @@ class DropColumnCollection:
|
|
82
81
|
]
|
83
82
|
|
84
83
|
@property
|
85
|
-
def table_class_names(self) ->
|
84
|
+
def table_class_names(self) -> list[str]:
|
86
85
|
return list({i.table_class_name for i in self.drop_columns})
|
87
86
|
|
88
87
|
|
89
88
|
@dataclass
|
90
89
|
class RenameColumnCollection:
|
91
|
-
rename_columns:
|
90
|
+
rename_columns: list[RenameColumn] = field(default_factory=list)
|
92
91
|
|
93
92
|
def append(self, rename_column: RenameColumn):
|
94
93
|
self.rename_columns.append(rename_column)
|
95
94
|
|
96
95
|
def for_table_class_name(
|
97
96
|
self, table_class_name: str
|
98
|
-
) ->
|
97
|
+
) -> list[RenameColumn]:
|
99
98
|
return [
|
100
99
|
i
|
101
100
|
for i in self.rename_columns
|
@@ -103,20 +102,18 @@ class RenameColumnCollection:
|
|
103
102
|
]
|
104
103
|
|
105
104
|
@property
|
106
|
-
def table_class_names(self) ->
|
105
|
+
def table_class_names(self) -> list[str]:
|
107
106
|
return list({i.table_class_name for i in self.rename_columns})
|
108
107
|
|
109
108
|
|
110
109
|
@dataclass
|
111
110
|
class AlterColumnCollection:
|
112
|
-
alter_columns:
|
111
|
+
alter_columns: list[AlterColumn] = field(default_factory=list)
|
113
112
|
|
114
113
|
def append(self, alter_column: AlterColumn):
|
115
114
|
self.alter_columns.append(alter_column)
|
116
115
|
|
117
|
-
def for_table_class_name(
|
118
|
-
self, table_class_name: str
|
119
|
-
) -> t.List[AlterColumn]:
|
116
|
+
def for_table_class_name(self, table_class_name: str) -> list[AlterColumn]:
|
120
117
|
return [
|
121
118
|
i
|
122
119
|
for i in self.alter_columns
|
@@ -124,11 +121,11 @@ class AlterColumnCollection:
|
|
124
121
|
]
|
125
122
|
|
126
123
|
@property
|
127
|
-
def table_class_names(self) ->
|
124
|
+
def table_class_names(self) -> list[str]:
|
128
125
|
return list({i.table_class_name for i in self.alter_columns})
|
129
126
|
|
130
127
|
|
131
|
-
AsyncFunction =
|
128
|
+
AsyncFunction = Callable[[], Coroutine]
|
132
129
|
|
133
130
|
|
134
131
|
class SkippedTransaction:
|
@@ -158,12 +155,10 @@ class MigrationManager:
|
|
158
155
|
app_name: str = ""
|
159
156
|
description: str = ""
|
160
157
|
preview: bool = False
|
161
|
-
add_tables:
|
162
|
-
drop_tables:
|
163
|
-
rename_tables:
|
164
|
-
change_table_schemas:
|
165
|
-
default_factory=list
|
166
|
-
)
|
158
|
+
add_tables: list[DiffableTable] = field(default_factory=list)
|
159
|
+
drop_tables: list[DiffableTable] = field(default_factory=list)
|
160
|
+
rename_tables: list[RenameTable] = field(default_factory=list)
|
161
|
+
change_table_schemas: list[ChangeTableSchema] = field(default_factory=list)
|
167
162
|
add_columns: AddColumnCollection = field(
|
168
163
|
default_factory=AddColumnCollection
|
169
164
|
)
|
@@ -176,10 +171,8 @@ class MigrationManager:
|
|
176
171
|
alter_columns: AlterColumnCollection = field(
|
177
172
|
default_factory=AlterColumnCollection
|
178
173
|
)
|
179
|
-
raw:
|
180
|
-
|
181
|
-
)
|
182
|
-
raw_backwards: t.List[t.Union[t.Callable, AsyncFunction]] = field(
|
174
|
+
raw: list[Union[Callable, AsyncFunction]] = field(default_factory=list)
|
175
|
+
raw_backwards: list[Union[Callable, AsyncFunction]] = field(
|
183
176
|
default_factory=list
|
184
177
|
)
|
185
178
|
fake: bool = False
|
@@ -189,8 +182,8 @@ class MigrationManager:
|
|
189
182
|
self,
|
190
183
|
class_name: str,
|
191
184
|
tablename: str,
|
192
|
-
schema:
|
193
|
-
columns:
|
185
|
+
schema: Optional[str] = None,
|
186
|
+
columns: Optional[list[Column]] = None,
|
194
187
|
):
|
195
188
|
if not columns:
|
196
189
|
columns = []
|
@@ -205,7 +198,7 @@ class MigrationManager:
|
|
205
198
|
)
|
206
199
|
|
207
200
|
def drop_table(
|
208
|
-
self, class_name: str, tablename: str, schema:
|
201
|
+
self, class_name: str, tablename: str, schema: Optional[str] = None
|
209
202
|
):
|
210
203
|
self.drop_tables.append(
|
211
204
|
DiffableTable(
|
@@ -217,8 +210,8 @@ class MigrationManager:
|
|
217
210
|
self,
|
218
211
|
class_name: str,
|
219
212
|
tablename: str,
|
220
|
-
new_schema:
|
221
|
-
old_schema:
|
213
|
+
new_schema: Optional[str] = None,
|
214
|
+
old_schema: Optional[str] = None,
|
222
215
|
):
|
223
216
|
self.change_table_schemas.append(
|
224
217
|
ChangeTableSchema(
|
@@ -235,7 +228,7 @@ class MigrationManager:
|
|
235
228
|
old_tablename: str,
|
236
229
|
new_class_name: str,
|
237
230
|
new_tablename: str,
|
238
|
-
schema:
|
231
|
+
schema: Optional[str] = None,
|
239
232
|
):
|
240
233
|
self.rename_tables.append(
|
241
234
|
RenameTable(
|
@@ -252,11 +245,11 @@ class MigrationManager:
|
|
252
245
|
table_class_name: str,
|
253
246
|
tablename: str,
|
254
247
|
column_name: str,
|
255
|
-
db_column_name:
|
248
|
+
db_column_name: Optional[str] = None,
|
256
249
|
column_class_name: str = "",
|
257
|
-
column_class:
|
258
|
-
params:
|
259
|
-
schema:
|
250
|
+
column_class: Optional[type[Column]] = None,
|
251
|
+
params: Optional[dict[str, Any]] = None,
|
252
|
+
schema: Optional[str] = None,
|
260
253
|
):
|
261
254
|
"""
|
262
255
|
Add a new column to the table.
|
@@ -297,8 +290,8 @@ class MigrationManager:
|
|
297
290
|
table_class_name: str,
|
298
291
|
tablename: str,
|
299
292
|
column_name: str,
|
300
|
-
db_column_name:
|
301
|
-
schema:
|
293
|
+
db_column_name: Optional[str] = None,
|
294
|
+
schema: Optional[str] = None,
|
302
295
|
):
|
303
296
|
self.drop_columns.append(
|
304
297
|
DropColumn(
|
@@ -316,9 +309,9 @@ class MigrationManager:
|
|
316
309
|
tablename: str,
|
317
310
|
old_column_name: str,
|
318
311
|
new_column_name: str,
|
319
|
-
old_db_column_name:
|
320
|
-
new_db_column_name:
|
321
|
-
schema:
|
312
|
+
old_db_column_name: Optional[str] = None,
|
313
|
+
new_db_column_name: Optional[str] = None,
|
314
|
+
schema: Optional[str] = None,
|
322
315
|
):
|
323
316
|
self.rename_columns.append(
|
324
317
|
RenameColumn(
|
@@ -337,12 +330,12 @@ class MigrationManager:
|
|
337
330
|
table_class_name: str,
|
338
331
|
tablename: str,
|
339
332
|
column_name: str,
|
340
|
-
db_column_name:
|
341
|
-
params:
|
342
|
-
old_params:
|
343
|
-
column_class:
|
344
|
-
old_column_class:
|
345
|
-
schema:
|
333
|
+
db_column_name: Optional[str] = None,
|
334
|
+
params: Optional[dict[str, Any]] = None,
|
335
|
+
old_params: Optional[dict[str, Any]] = None,
|
336
|
+
column_class: Optional[type[Column]] = None,
|
337
|
+
old_column_class: Optional[type[Column]] = None,
|
338
|
+
schema: Optional[str] = None,
|
346
339
|
):
|
347
340
|
"""
|
348
341
|
All possible alterations aren't currently supported.
|
@@ -365,14 +358,14 @@ class MigrationManager:
|
|
365
358
|
)
|
366
359
|
)
|
367
360
|
|
368
|
-
def add_raw(self, raw:
|
361
|
+
def add_raw(self, raw: Union[Callable, AsyncFunction]):
|
369
362
|
"""
|
370
363
|
A migration manager can execute arbitrary functions or coroutines when
|
371
364
|
run. This is useful if you want to execute raw SQL.
|
372
365
|
"""
|
373
366
|
self.raw.append(raw)
|
374
367
|
|
375
|
-
def add_raw_backwards(self, raw:
|
368
|
+
def add_raw_backwards(self, raw: Union[Callable, AsyncFunction]):
|
376
369
|
"""
|
377
370
|
When reversing a migration, you may want to run extra code to help
|
378
371
|
clean up.
|
@@ -384,10 +377,10 @@ class MigrationManager:
|
|
384
377
|
async def get_table_from_snapshot(
|
385
378
|
self,
|
386
379
|
table_class_name: str,
|
387
|
-
app_name:
|
380
|
+
app_name: Optional[str],
|
388
381
|
offset: int = 0,
|
389
|
-
migration_id:
|
390
|
-
) ->
|
382
|
+
migration_id: Optional[str] = None,
|
383
|
+
) -> type[Table]:
|
391
384
|
"""
|
392
385
|
Returns a Table subclass which can be used for modifying data within
|
393
386
|
a migration.
|
@@ -416,13 +409,13 @@ class MigrationManager:
|
|
416
409
|
###########################################################################
|
417
410
|
|
418
411
|
@staticmethod
|
419
|
-
async def _print_query(query:
|
412
|
+
async def _print_query(query: Union[DDL, Query, SchemaDDLBase]):
|
420
413
|
if isinstance(query, DDL):
|
421
414
|
print("\n", ";".join(query.ddl) + ";")
|
422
415
|
else:
|
423
416
|
print(str(query))
|
424
417
|
|
425
|
-
async def _run_query(self, query:
|
418
|
+
async def _run_query(self, query: Union[DDL, Query, SchemaDDLBase]):
|
426
419
|
"""
|
427
420
|
If MigrationManager is in preview mode then it just print the query
|
428
421
|
instead of executing it.
|
@@ -441,7 +434,7 @@ class MigrationManager:
|
|
441
434
|
if not alter_columns:
|
442
435
|
continue
|
443
436
|
|
444
|
-
_Table:
|
437
|
+
_Table: type[Table] = create_table_class(
|
445
438
|
class_name=table_class_name,
|
446
439
|
class_kwargs={
|
447
440
|
"tablename": alter_columns[0].tablename,
|
@@ -494,7 +487,7 @@ class MigrationManager:
|
|
494
487
|
alter_column.db_column_name
|
495
488
|
)
|
496
489
|
|
497
|
-
using_expression:
|
490
|
+
using_expression: Optional[str] = None
|
498
491
|
|
499
492
|
# Postgres won't automatically cast some types to
|
500
493
|
# others. We may as well try, as it will definitely
|
@@ -739,7 +732,7 @@ class MigrationManager:
|
|
739
732
|
else rename_table.new_tablename
|
740
733
|
)
|
741
734
|
|
742
|
-
_Table:
|
735
|
+
_Table: type[Table] = create_table_class(
|
743
736
|
class_name=class_name,
|
744
737
|
class_kwargs={
|
745
738
|
"tablename": tablename,
|
@@ -760,7 +753,7 @@ class MigrationManager:
|
|
760
753
|
if not columns:
|
761
754
|
continue
|
762
755
|
|
763
|
-
_Table:
|
756
|
+
_Table: type[Table] = create_table_class(
|
764
757
|
class_name=table_class_name,
|
765
758
|
class_kwargs={
|
766
759
|
"tablename": columns[0].tablename,
|
@@ -788,12 +781,12 @@ class MigrationManager:
|
|
788
781
|
)
|
789
782
|
|
790
783
|
async def _run_add_tables(self, backwards: bool = False):
|
791
|
-
table_classes:
|
784
|
+
table_classes: list[type[Table]] = []
|
792
785
|
for add_table in self.add_tables:
|
793
|
-
add_columns:
|
786
|
+
add_columns: list[AddColumnClass] = (
|
794
787
|
self.add_columns.for_table_class_name(add_table.class_name)
|
795
788
|
)
|
796
|
-
_Table:
|
789
|
+
_Table: type[Table] = create_table_class(
|
797
790
|
class_name=add_table.class_name,
|
798
791
|
class_kwargs={
|
799
792
|
"tablename": add_table.tablename,
|
@@ -845,7 +838,7 @@ class MigrationManager:
|
|
845
838
|
if table_class_name in [i.class_name for i in self.add_tables]:
|
846
839
|
continue # No need to add columns to new tables
|
847
840
|
|
848
|
-
add_columns:
|
841
|
+
add_columns: list[AddColumnClass] = (
|
849
842
|
self.add_columns.for_table_class_name(table_class_name)
|
850
843
|
)
|
851
844
|
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import typing as t
|
2
1
|
from dataclasses import dataclass
|
2
|
+
from typing import Any, Optional
|
3
3
|
|
4
4
|
from piccolo.columns.base import Column
|
5
5
|
|
@@ -10,15 +10,15 @@ class RenameTable:
|
|
10
10
|
old_tablename: str
|
11
11
|
new_class_name: str
|
12
12
|
new_tablename: str
|
13
|
-
schema:
|
13
|
+
schema: Optional[str] = None
|
14
14
|
|
15
15
|
|
16
16
|
@dataclass
|
17
17
|
class ChangeTableSchema:
|
18
18
|
class_name: str
|
19
19
|
tablename: str
|
20
|
-
old_schema:
|
21
|
-
new_schema:
|
20
|
+
old_schema: Optional[str]
|
21
|
+
new_schema: Optional[str]
|
22
22
|
|
23
23
|
|
24
24
|
@dataclass
|
@@ -29,7 +29,7 @@ class RenameColumn:
|
|
29
29
|
new_column_name: str
|
30
30
|
old_db_column_name: str
|
31
31
|
new_db_column_name: str
|
32
|
-
schema:
|
32
|
+
schema: Optional[str] = None
|
33
33
|
|
34
34
|
|
35
35
|
@dataclass
|
@@ -38,11 +38,11 @@ class AlterColumn:
|
|
38
38
|
column_name: str
|
39
39
|
db_column_name: str
|
40
40
|
tablename: str
|
41
|
-
params:
|
42
|
-
old_params:
|
43
|
-
column_class:
|
44
|
-
old_column_class:
|
45
|
-
schema:
|
41
|
+
params: dict[str, Any]
|
42
|
+
old_params: dict[str, Any]
|
43
|
+
column_class: Optional[type[Column]] = None
|
44
|
+
old_column_class: Optional[type[Column]] = None
|
45
|
+
schema: Optional[str] = None
|
46
46
|
|
47
47
|
|
48
48
|
@dataclass
|
@@ -51,7 +51,7 @@ class DropColumn:
|
|
51
51
|
column_name: str
|
52
52
|
db_column_name: str
|
53
53
|
tablename: str
|
54
|
-
schema:
|
54
|
+
schema: Optional[str] = None
|
55
55
|
|
56
56
|
|
57
57
|
@dataclass
|
@@ -60,6 +60,6 @@ class AddColumn:
|
|
60
60
|
column_name: str
|
61
61
|
db_column_name: str
|
62
62
|
column_class_name: str
|
63
|
-
column_class:
|
64
|
-
params:
|
65
|
-
schema:
|
63
|
+
column_class: type[Column]
|
64
|
+
params: dict[str, Any]
|
65
|
+
schema: Optional[str] = None
|
@@ -1,9 +1,10 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import inspect
|
4
|
-
|
4
|
+
from collections.abc import Callable
|
5
5
|
from copy import deepcopy
|
6
6
|
from dataclasses import dataclass, field
|
7
|
+
from typing import Any, Optional
|
7
8
|
|
8
9
|
from piccolo.apps.migrations.auto.diffable_table import (
|
9
10
|
DiffableTable,
|
@@ -26,7 +27,7 @@ from piccolo.utils.printing import get_fixed_length_string
|
|
26
27
|
|
27
28
|
@dataclass
|
28
29
|
class RenameTableCollection:
|
29
|
-
rename_tables:
|
30
|
+
rename_tables: list[RenameTable] = field(default_factory=list)
|
30
31
|
|
31
32
|
def append(self, renamed_table: RenameTable):
|
32
33
|
self.rename_tables.append(renamed_table)
|
@@ -48,7 +49,7 @@ class RenameTableCollection:
|
|
48
49
|
return True
|
49
50
|
return False
|
50
51
|
|
51
|
-
def renamed_from(self, new_class_name: str) ->
|
52
|
+
def renamed_from(self, new_class_name: str) -> Optional[str]:
|
52
53
|
"""
|
53
54
|
Returns the old class name, if it exists.
|
54
55
|
"""
|
@@ -60,7 +61,7 @@ class RenameTableCollection:
|
|
60
61
|
|
61
62
|
@dataclass
|
62
63
|
class ChangeTableSchemaCollection:
|
63
|
-
collection:
|
64
|
+
collection: list[ChangeTableSchema] = field(default_factory=list)
|
64
65
|
|
65
66
|
def append(self, change_table_schema: ChangeTableSchema):
|
66
67
|
self.collection.append(change_table_schema)
|
@@ -68,14 +69,14 @@ class ChangeTableSchemaCollection:
|
|
68
69
|
|
69
70
|
@dataclass
|
70
71
|
class RenameColumnCollection:
|
71
|
-
rename_columns:
|
72
|
+
rename_columns: list[RenameColumn] = field(default_factory=list)
|
72
73
|
|
73
74
|
def append(self, rename_column: RenameColumn):
|
74
75
|
self.rename_columns.append(rename_column)
|
75
76
|
|
76
77
|
def for_table_class_name(
|
77
78
|
self, table_class_name: str
|
78
|
-
) ->
|
79
|
+
) -> list[RenameColumn]:
|
79
80
|
return [
|
80
81
|
i
|
81
82
|
for i in self.rename_columns
|
@@ -93,9 +94,9 @@ class RenameColumnCollection:
|
|
93
94
|
|
94
95
|
@dataclass
|
95
96
|
class AlterStatements:
|
96
|
-
statements:
|
97
|
-
extra_imports:
|
98
|
-
extra_definitions:
|
97
|
+
statements: list[str] = field(default_factory=list)
|
98
|
+
extra_imports: list[Import] = field(default_factory=list)
|
99
|
+
extra_definitions: list[Definition] = field(default_factory=list)
|
99
100
|
|
100
101
|
def extend(self, alter_statements: AlterStatements):
|
101
102
|
self.statements.extend(alter_statements.statements)
|
@@ -112,19 +113,19 @@ class SchemaDiffer:
|
|
112
113
|
sure - for example, whether a column was renamed.
|
113
114
|
"""
|
114
115
|
|
115
|
-
schema:
|
116
|
-
schema_snapshot:
|
116
|
+
schema: list[DiffableTable]
|
117
|
+
schema_snapshot: list[DiffableTable]
|
117
118
|
|
118
119
|
# Sometimes the SchemaDiffer requires input from a user - for example,
|
119
120
|
# asking if a table was renamed or not. When running in non-interactive
|
120
121
|
# mode (like in a unittest), we can set a default to be used instead, like
|
121
122
|
# 'y'.
|
122
|
-
auto_input:
|
123
|
+
auto_input: Optional[str] = None
|
123
124
|
|
124
125
|
###########################################################################
|
125
126
|
|
126
127
|
def __post_init__(self) -> None:
|
127
|
-
self.schema_snapshot_map:
|
128
|
+
self.schema_snapshot_map: dict[str, DiffableTable] = {
|
128
129
|
i.class_name: i for i in self.schema_snapshot
|
129
130
|
}
|
130
131
|
self.table_schema_changes_collection = (
|
@@ -137,11 +138,11 @@ class SchemaDiffer:
|
|
137
138
|
"""
|
138
139
|
Work out whether any of the tables were renamed.
|
139
140
|
"""
|
140
|
-
drop_tables:
|
141
|
+
drop_tables: list[DiffableTable] = list(
|
141
142
|
set(self.schema_snapshot) - set(self.schema)
|
142
143
|
)
|
143
144
|
|
144
|
-
new_tables:
|
145
|
+
new_tables: list[DiffableTable] = list(
|
145
146
|
set(self.schema) - set(self.schema_snapshot)
|
146
147
|
)
|
147
148
|
|
@@ -267,7 +268,7 @@ class SchemaDiffer:
|
|
267
268
|
# We track which dropped columns have already been identified by
|
268
269
|
# the user as renames, so we don't ask them if another column
|
269
270
|
# was also renamed from it.
|
270
|
-
used_drop_column_names:
|
271
|
+
used_drop_column_names: list[str] = []
|
271
272
|
|
272
273
|
for add_column in delta.add_columns:
|
273
274
|
for drop_column in delta.drop_columns:
|
@@ -300,9 +301,9 @@ class SchemaDiffer:
|
|
300
301
|
|
301
302
|
def _stringify_func(
|
302
303
|
self,
|
303
|
-
func:
|
304
|
-
params:
|
305
|
-
prefix:
|
304
|
+
func: Callable,
|
305
|
+
params: dict[str, Any],
|
306
|
+
prefix: Optional[str] = None,
|
306
307
|
) -> AlterStatements:
|
307
308
|
"""
|
308
309
|
Generates a string representing how to call the given function with the
|
@@ -348,7 +349,7 @@ class SchemaDiffer:
|
|
348
349
|
|
349
350
|
@property
|
350
351
|
def create_tables(self) -> AlterStatements:
|
351
|
-
new_tables:
|
352
|
+
new_tables: list[DiffableTable] = list(
|
352
353
|
set(self.schema) - set(self.schema_snapshot)
|
353
354
|
)
|
354
355
|
|
@@ -379,7 +380,7 @@ class SchemaDiffer:
|
|
379
380
|
|
380
381
|
@property
|
381
382
|
def drop_tables(self) -> AlterStatements:
|
382
|
-
drop_tables:
|
383
|
+
drop_tables: list[DiffableTable] = list(
|
383
384
|
set(self.schema_snapshot) - set(self.schema)
|
384
385
|
)
|
385
386
|
|
@@ -442,7 +443,7 @@ class SchemaDiffer:
|
|
442
443
|
|
443
444
|
def _get_snapshot_table(
|
444
445
|
self, table_class_name: str
|
445
|
-
) ->
|
446
|
+
) -> Optional[DiffableTable]:
|
446
447
|
snapshot_table = self.schema_snapshot_map.get(table_class_name, None)
|
447
448
|
if snapshot_table:
|
448
449
|
return snapshot_table
|
@@ -463,9 +464,9 @@ class SchemaDiffer:
|
|
463
464
|
|
464
465
|
@property
|
465
466
|
def alter_columns(self) -> AlterStatements:
|
466
|
-
response:
|
467
|
-
extra_imports:
|
468
|
-
extra_definitions:
|
467
|
+
response: list[str] = []
|
468
|
+
extra_imports: list[Import] = []
|
469
|
+
extra_definitions: list[Definition] = []
|
469
470
|
for table in self.schema:
|
470
471
|
snapshot_table = self._get_snapshot_table(table.class_name)
|
471
472
|
if snapshot_table:
|
@@ -563,9 +564,9 @@ class SchemaDiffer:
|
|
563
564
|
|
564
565
|
@property
|
565
566
|
def add_columns(self) -> AlterStatements:
|
566
|
-
response:
|
567
|
-
extra_imports:
|
568
|
-
extra_definitions:
|
567
|
+
response: list[str] = []
|
568
|
+
extra_imports: list[Import] = []
|
569
|
+
extra_definitions: list[Definition] = []
|
569
570
|
for table in self.schema:
|
570
571
|
snapshot_table = self._get_snapshot_table(table.class_name)
|
571
572
|
if snapshot_table:
|
@@ -632,13 +633,13 @@ class SchemaDiffer:
|
|
632
633
|
|
633
634
|
@property
|
634
635
|
def new_table_columns(self) -> AlterStatements:
|
635
|
-
new_tables:
|
636
|
+
new_tables: list[DiffableTable] = list(
|
636
637
|
set(self.schema) - set(self.schema_snapshot)
|
637
638
|
)
|
638
639
|
|
639
|
-
response:
|
640
|
-
extra_imports:
|
641
|
-
extra_definitions:
|
640
|
+
response: list[str] = []
|
641
|
+
extra_imports: list[Import] = []
|
642
|
+
extra_definitions: list[Definition] = []
|
642
643
|
for table in new_tables:
|
643
644
|
if (
|
644
645
|
table.class_name
|
@@ -681,11 +682,11 @@ class SchemaDiffer:
|
|
681
682
|
|
682
683
|
###########################################################################
|
683
684
|
|
684
|
-
def get_alter_statements(self) ->
|
685
|
+
def get_alter_statements(self) -> list[AlterStatements]:
|
685
686
|
"""
|
686
687
|
Call to execute the necessary alter commands on the database.
|
687
688
|
"""
|
688
|
-
alter_statements:
|
689
|
+
alter_statements: dict[str, AlterStatements] = {
|
689
690
|
"Created tables": self.create_tables,
|
690
691
|
"Dropped tables": self.drop_tables,
|
691
692
|
"Renamed tables": self.rename_tables,
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import typing as t
|
4
3
|
from dataclasses import dataclass, field
|
5
4
|
|
6
5
|
from piccolo.apps.migrations.auto.diffable_table import DiffableTable
|
@@ -15,7 +14,7 @@ class SchemaSnapshot:
|
|
15
14
|
"""
|
16
15
|
|
17
16
|
# In ascending order of date created.
|
18
|
-
managers:
|
17
|
+
managers: list[MigrationManager] = field(default_factory=list)
|
19
18
|
|
20
19
|
###########################################################################
|
21
20
|
|
@@ -28,8 +27,8 @@ class SchemaSnapshot:
|
|
28
27
|
|
29
28
|
###########################################################################
|
30
29
|
|
31
|
-
def get_snapshot(self) ->
|
32
|
-
tables:
|
30
|
+
def get_snapshot(self) -> list[DiffableTable]:
|
31
|
+
tables: list[DiffableTable] = []
|
33
32
|
|
34
33
|
# Make sure the managers are sorted correctly:
|
35
34
|
sorted_managers = sorted(self.managers, key=lambda x: x.migration_id)
|