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
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
from typing import Any
|
2
2
|
from http import HTTPStatus
|
3
3
|
|
4
4
|
from hypercorn.middleware import DispatcherMiddleware
|
@@ -6,6 +6,7 @@ from piccolo.engine import engine_finder
|
|
6
6
|
from piccolo_admin.endpoints import create_admin
|
7
7
|
from piccolo_api.crud.serializers import create_pydantic_model
|
8
8
|
from quart import Quart
|
9
|
+
from quart.helpers import abort
|
9
10
|
from quart_schema import (
|
10
11
|
Info,
|
11
12
|
QuartSchema,
|
@@ -24,17 +25,24 @@ app = Quart(__name__, static_folder="static")
|
|
24
25
|
QuartSchema(app, info=Info(title="Quart API", version="0.1.0"))
|
25
26
|
|
26
27
|
|
27
|
-
TaskModelIn:
|
28
|
+
TaskModelIn: Any = create_pydantic_model(
|
28
29
|
table=Task,
|
29
30
|
model_name="TaskModelIn",
|
30
31
|
)
|
31
|
-
TaskModelOut:
|
32
|
+
TaskModelOut: Any = create_pydantic_model(
|
32
33
|
table=Task,
|
33
34
|
include_default_columns=True,
|
34
35
|
model_name="TaskModelOut",
|
35
36
|
)
|
36
37
|
|
37
38
|
|
39
|
+
# Check if the record is None. Use for query callback
|
40
|
+
def check_record_not_found(result: dict[str, Any]) -> dict[str, Any]:
|
41
|
+
if result is None:
|
42
|
+
abort(code=HTTPStatus.NOT_FOUND)
|
43
|
+
return result
|
44
|
+
|
45
|
+
|
38
46
|
@app.get("/")
|
39
47
|
@hide
|
40
48
|
def home():
|
@@ -42,10 +50,24 @@ def home():
|
|
42
50
|
|
43
51
|
|
44
52
|
@app.get("/tasks/")
|
45
|
-
@validate_response(
|
53
|
+
@validate_response(list[TaskModelOut])
|
46
54
|
@tag(["Task"])
|
47
55
|
async def tasks():
|
48
|
-
|
56
|
+
tasks = await Task.select().order_by(Task._meta.primary_key, ascending=False)
|
57
|
+
return [TaskModelOut(**task) for task in tasks], HTTPStatus.OK
|
58
|
+
|
59
|
+
|
60
|
+
@app.get("/tasks/<int:task_id>/")
|
61
|
+
@validate_response(TaskModelOut)
|
62
|
+
@tag(["Task"])
|
63
|
+
async def single_task(task_id: int):
|
64
|
+
task = (
|
65
|
+
await Task.select()
|
66
|
+
.where(Task._meta.primary_key == task_id)
|
67
|
+
.first()
|
68
|
+
.callback(check_record_not_found)
|
69
|
+
)
|
70
|
+
return TaskModelOut(**task), HTTPStatus.OK
|
49
71
|
|
50
72
|
|
51
73
|
@app.post("/tasks/")
|
@@ -63,28 +85,29 @@ async def create_task(data: TaskModelIn):
|
|
63
85
|
@validate_response(TaskModelOut)
|
64
86
|
@tag(["Task"])
|
65
87
|
async def update_task(task_id: int, data: TaskModelIn):
|
66
|
-
task =
|
67
|
-
|
68
|
-
|
88
|
+
task = (
|
89
|
+
await Task.objects()
|
90
|
+
.get(Task._meta.primary_key == task_id)
|
91
|
+
.callback(check_record_not_found)
|
92
|
+
)
|
69
93
|
|
70
94
|
for key, value in data.model_dump().items():
|
71
95
|
setattr(task, key, value)
|
72
96
|
|
73
97
|
await task.save()
|
74
98
|
|
75
|
-
return task.to_dict(), HTTPStatus.OK
|
99
|
+
return TaskModelOut(**task.to_dict()), HTTPStatus.OK
|
76
100
|
|
77
101
|
|
78
102
|
@app.delete("/tasks/<int:task_id>/")
|
79
|
-
@validate_response(TaskModelOut)
|
80
103
|
@tag(["Task"])
|
81
104
|
async def delete_task(task_id: int):
|
82
|
-
task =
|
83
|
-
|
84
|
-
|
85
|
-
|
105
|
+
task = (
|
106
|
+
await Task.objects()
|
107
|
+
.get(Task._meta.primary_key == task_id)
|
108
|
+
.callback(check_record_not_found)
|
109
|
+
)
|
86
110
|
await task.remove()
|
87
|
-
|
88
111
|
return {}, HTTPStatus.OK
|
89
112
|
|
90
113
|
|
@@ -1,11 +1,10 @@
|
|
1
|
-
import
|
2
|
-
import typing as t
|
1
|
+
from typing import Any
|
3
2
|
|
4
3
|
from hypercorn.middleware import DispatcherMiddleware
|
5
4
|
from piccolo.engine import engine_finder
|
6
5
|
from piccolo_admin.endpoints import create_admin
|
7
6
|
from piccolo_api.crud.serializers import create_pydantic_model
|
8
|
-
from sanic import Request, Sanic, json
|
7
|
+
from sanic import NotFound, Request, Sanic, json
|
9
8
|
from sanic_ext import openapi
|
10
9
|
|
11
10
|
from home.endpoints import index
|
@@ -16,17 +15,24 @@ app = Sanic(__name__)
|
|
16
15
|
app.static("/static/", "static")
|
17
16
|
|
18
17
|
|
19
|
-
TaskModelIn:
|
18
|
+
TaskModelIn: Any = create_pydantic_model(
|
20
19
|
table=Task,
|
21
20
|
model_name="TaskModelIn",
|
22
21
|
)
|
23
|
-
TaskModelOut:
|
22
|
+
TaskModelOut: Any = create_pydantic_model(
|
24
23
|
table=Task,
|
25
24
|
include_default_columns=True,
|
26
25
|
model_name="TaskModelOut",
|
27
26
|
)
|
28
27
|
|
29
28
|
|
29
|
+
# Check if the record is None. Use for query callback
|
30
|
+
def check_record_not_found(result: dict[str, Any]) -> dict[str, Any]:
|
31
|
+
if result is None:
|
32
|
+
raise NotFound(message="Record not found")
|
33
|
+
return result
|
34
|
+
|
35
|
+
|
30
36
|
@app.get("/")
|
31
37
|
@openapi.exclude()
|
32
38
|
def home(request: Request):
|
@@ -43,6 +49,19 @@ async def tasks(request: Request):
|
|
43
49
|
)
|
44
50
|
|
45
51
|
|
52
|
+
@app.get("/tasks/<task_id:int>/")
|
53
|
+
@openapi.tag("Task")
|
54
|
+
@openapi.response(200, {"application/json": TaskModelOut.model_json_schema()})
|
55
|
+
async def single_task(request: Request, task_id: int):
|
56
|
+
task = (
|
57
|
+
await Task.select()
|
58
|
+
.where(Task._meta.primary_key == task_id)
|
59
|
+
.first()
|
60
|
+
.callback(check_record_not_found)
|
61
|
+
)
|
62
|
+
return json(task, status=200)
|
63
|
+
|
64
|
+
|
46
65
|
@app.post("/tasks/")
|
47
66
|
@openapi.definition(
|
48
67
|
body={"application/json": TaskModelIn.model_json_schema()},
|
@@ -62,9 +81,11 @@ async def create_task(request: Request):
|
|
62
81
|
)
|
63
82
|
@openapi.response(200, {"application/json": TaskModelOut.model_json_schema()})
|
64
83
|
async def update_task(request: Request, task_id: int):
|
65
|
-
task =
|
66
|
-
|
67
|
-
|
84
|
+
task = (
|
85
|
+
await Task.objects()
|
86
|
+
.get(Task._meta.primary_key == task_id)
|
87
|
+
.callback(check_record_not_found)
|
88
|
+
)
|
68
89
|
for key, value in request.json.items():
|
69
90
|
setattr(task, key, value)
|
70
91
|
|
@@ -75,9 +96,11 @@ async def update_task(request: Request, task_id: int):
|
|
75
96
|
@app.delete("/tasks/<task_id:int>/")
|
76
97
|
@openapi.tag("Task")
|
77
98
|
async def delete_task(request: Request, task_id: int):
|
78
|
-
task =
|
79
|
-
|
80
|
-
|
99
|
+
task = (
|
100
|
+
await Task.objects()
|
101
|
+
.get(Task._meta.primary_key == task_id)
|
102
|
+
.callback(check_record_not_found)
|
103
|
+
)
|
81
104
|
await task.remove()
|
82
105
|
return json({}, status=200)
|
83
106
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
|
3
|
+
from typing import Any, Optional
|
4
4
|
|
5
5
|
from piccolo.apps.fixtures.commands.shared import (
|
6
6
|
FixtureConfig,
|
@@ -11,8 +11,8 @@ from piccolo.table import sort_table_classes
|
|
11
11
|
|
12
12
|
|
13
13
|
async def get_dump(
|
14
|
-
fixture_configs:
|
15
|
-
) ->
|
14
|
+
fixture_configs: list[FixtureConfig],
|
15
|
+
) -> dict[str, Any]:
|
16
16
|
"""
|
17
17
|
Gets the data for each table specified and returns a data structure like:
|
18
18
|
|
@@ -32,7 +32,7 @@ async def get_dump(
|
|
32
32
|
"""
|
33
33
|
finder = Finder()
|
34
34
|
|
35
|
-
output:
|
35
|
+
output: dict[str, Any] = {}
|
36
36
|
|
37
37
|
for fixture_config in fixture_configs:
|
38
38
|
app_config = finder.get_app_config(app_name=fixture_config.app_name)
|
@@ -53,7 +53,7 @@ async def get_dump(
|
|
53
53
|
|
54
54
|
|
55
55
|
async def dump_to_json_string(
|
56
|
-
fixture_configs:
|
56
|
+
fixture_configs: list[FixtureConfig],
|
57
57
|
) -> str:
|
58
58
|
"""
|
59
59
|
Dumps all of the data for the given tables into a JSON string.
|
@@ -65,7 +65,7 @@ async def dump_to_json_string(
|
|
65
65
|
return pydantic_model(**dump).model_dump_json(indent=4)
|
66
66
|
|
67
67
|
|
68
|
-
def parse_args(apps: str, tables: str) ->
|
68
|
+
def parse_args(apps: str, tables: str) -> list[FixtureConfig]:
|
69
69
|
"""
|
70
70
|
Works out which apps and tables the user is referring to.
|
71
71
|
"""
|
@@ -80,11 +80,11 @@ def parse_args(apps: str, tables: str) -> t.List[FixtureConfig]:
|
|
80
80
|
# Must be a single app name
|
81
81
|
app_names.append(apps)
|
82
82
|
|
83
|
-
table_class_names:
|
83
|
+
table_class_names: Optional[list[str]] = None
|
84
84
|
|
85
85
|
if tables != "all":
|
86
86
|
table_class_names = tables.split(",") if "," in tables else [tables]
|
87
|
-
output:
|
87
|
+
output: list[FixtureConfig] = []
|
88
88
|
|
89
89
|
for app_name in app_names:
|
90
90
|
app_config = finder.get_app_config(app_name=app_name)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import sys
|
4
|
-
|
4
|
+
from typing import Optional
|
5
5
|
|
6
6
|
import typing_extensions
|
7
7
|
|
@@ -20,7 +20,7 @@ from piccolo.utils.list import batch
|
|
20
20
|
async def load_json_string(
|
21
21
|
json_string: str,
|
22
22
|
chunk_size: int = 1000,
|
23
|
-
on_conflict_action:
|
23
|
+
on_conflict_action: Optional[OnConflictAction] = None,
|
24
24
|
):
|
25
25
|
"""
|
26
26
|
Parses the JSON string, and inserts the parsed data into the database.
|
@@ -55,7 +55,7 @@ async def load_json_string(
|
|
55
55
|
raise Exception("Unable to find the engine.")
|
56
56
|
|
57
57
|
# This is what we want to the insert into the database:
|
58
|
-
data:
|
58
|
+
data: dict[type[Table], list[Table]] = {}
|
59
59
|
|
60
60
|
for app_name in app_names:
|
61
61
|
app_model = getattr(fixture_pydantic_model, app_name)
|
@@ -94,7 +94,7 @@ async def load_json_string(
|
|
94
94
|
async def load(
|
95
95
|
path: str = "fixture.json",
|
96
96
|
chunk_size: int = 1000,
|
97
|
-
on_conflict:
|
97
|
+
on_conflict: Optional[
|
98
98
|
typing_extensions.Literal["DO NOTHING", "DO UPDATE"]
|
99
99
|
] = None,
|
100
100
|
):
|
@@ -118,7 +118,7 @@ async def load(
|
|
118
118
|
with open(path, "r") as f:
|
119
119
|
contents = f.read()
|
120
120
|
|
121
|
-
on_conflict_action:
|
121
|
+
on_conflict_action: Optional[OnConflictAction] = None
|
122
122
|
|
123
123
|
if on_conflict:
|
124
124
|
try:
|
@@ -1,42 +1,42 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import typing as t
|
4
3
|
from dataclasses import dataclass
|
4
|
+
from typing import TYPE_CHECKING, Any
|
5
5
|
|
6
6
|
import pydantic
|
7
7
|
|
8
8
|
from piccolo.conf.apps import Finder
|
9
9
|
from piccolo.utils.pydantic import create_pydantic_model
|
10
10
|
|
11
|
-
if
|
11
|
+
if TYPE_CHECKING: # pragma: no cover
|
12
12
|
from piccolo.table import Table
|
13
13
|
|
14
14
|
|
15
15
|
@dataclass
|
16
16
|
class FixtureConfig:
|
17
17
|
app_name: str
|
18
|
-
table_class_names:
|
18
|
+
table_class_names: list[str]
|
19
19
|
|
20
20
|
|
21
|
-
def create_pydantic_fixture_model(fixture_configs:
|
21
|
+
def create_pydantic_fixture_model(fixture_configs: list[FixtureConfig]):
|
22
22
|
"""
|
23
23
|
Returns a nested Pydantic model for serialising and deserialising fixtures.
|
24
24
|
"""
|
25
|
-
columns:
|
25
|
+
columns: dict[str, Any] = {}
|
26
26
|
|
27
27
|
finder = Finder()
|
28
28
|
|
29
29
|
for fixture_config in fixture_configs:
|
30
30
|
|
31
|
-
app_columns:
|
31
|
+
app_columns: dict[str, Any] = {}
|
32
32
|
|
33
33
|
for table_class_name in fixture_config.table_class_names:
|
34
|
-
table_class:
|
34
|
+
table_class: type[Table] = finder.get_table_with_name(
|
35
35
|
app_name=fixture_config.app_name,
|
36
36
|
table_class_name=table_class_name,
|
37
37
|
)
|
38
38
|
app_columns[table_class_name] = (
|
39
|
-
|
39
|
+
list[ # type: ignore
|
40
40
|
create_pydantic_model(
|
41
41
|
table_class, include_default_columns=True
|
42
42
|
)
|
@@ -44,7 +44,7 @@ def create_pydantic_fixture_model(fixture_configs: t.List[FixtureConfig]):
|
|
44
44
|
...,
|
45
45
|
)
|
46
46
|
|
47
|
-
app_model:
|
47
|
+
app_model: Any = pydantic.create_model(
|
48
48
|
f"{fixture_config.app_name.title()}Model", **app_columns
|
49
49
|
)
|
50
50
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import typing as t
|
4
3
|
from dataclasses import dataclass, field
|
4
|
+
from typing import Any, Optional
|
5
5
|
|
6
6
|
from piccolo.apps.migrations.auto.operations import (
|
7
7
|
AddColumn,
|
@@ -17,8 +17,8 @@ from piccolo.table import Table, create_table_class
|
|
17
17
|
|
18
18
|
|
19
19
|
def compare_dicts(
|
20
|
-
dict_1:
|
21
|
-
) ->
|
20
|
+
dict_1: dict[str, Any], dict_2: dict[str, Any]
|
21
|
+
) -> dict[str, Any]:
|
22
22
|
"""
|
23
23
|
Returns a new dictionary which only contains key, value pairs which are in
|
24
24
|
the first dictionary and not the second.
|
@@ -59,9 +59,9 @@ def compare_dicts(
|
|
59
59
|
|
60
60
|
@dataclass
|
61
61
|
class TableDelta:
|
62
|
-
add_columns:
|
63
|
-
drop_columns:
|
64
|
-
alter_columns:
|
62
|
+
add_columns: list[AddColumn] = field(default_factory=list)
|
63
|
+
drop_columns: list[DropColumn] = field(default_factory=list)
|
64
|
+
alter_columns: list[AlterColumn] = field(default_factory=list)
|
65
65
|
|
66
66
|
def __eq__(self, value: TableDelta) -> bool: # type: ignore
|
67
67
|
"""
|
@@ -101,12 +101,12 @@ class DiffableTable:
|
|
101
101
|
|
102
102
|
class_name: str
|
103
103
|
tablename: str
|
104
|
-
schema:
|
105
|
-
columns:
|
106
|
-
previous_class_name:
|
104
|
+
schema: Optional[str] = None
|
105
|
+
columns: list[Column] = field(default_factory=list)
|
106
|
+
previous_class_name: Optional[str] = None
|
107
107
|
|
108
108
|
def __post_init__(self) -> None:
|
109
|
-
self.columns_map:
|
109
|
+
self.columns_map: dict[str, Column] = {
|
110
110
|
i._meta.name: i for i in self.columns
|
111
111
|
}
|
112
112
|
|
@@ -163,7 +163,7 @@ class DiffableTable:
|
|
163
163
|
|
164
164
|
#######################################################################
|
165
165
|
|
166
|
-
alter_columns:
|
166
|
+
alter_columns: list[AlterColumn] = []
|
167
167
|
|
168
168
|
for existing_column in value.columns:
|
169
169
|
column = self.columns_map.get(existing_column._meta.name)
|
@@ -221,7 +221,7 @@ class DiffableTable:
|
|
221
221
|
def __str__(self):
|
222
222
|
return f"{self.class_name} - {self.tablename}"
|
223
223
|
|
224
|
-
def to_table_class(self) ->
|
224
|
+
def to_table_class(self) -> type[Table]:
|
225
225
|
"""
|
226
226
|
Converts the DiffableTable into a Table subclass.
|
227
227
|
"""
|