Skip to content

Commit 2370efb

Browse files
committed
serialising Array column types in migrations
1 parent 5d0b740 commit 2370efb

File tree

2 files changed

+78
-3
lines changed

2 files changed

+78
-3
lines changed

piccolo/apps/migrations/auto/serialisation.py

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from __future__ import annotations
2+
import builtins
23
from copy import deepcopy
34
from dataclasses import dataclass, field
45
import datetime
@@ -8,6 +9,7 @@
89
import typing as t
910
import uuid
1011

12+
from piccolo.columns import Column
1113
from piccolo.columns.defaults.base import Default
1214
from piccolo.columns.reference import LazyTableReference
1315
from piccolo.table import Table
@@ -17,7 +19,21 @@
1719

1820

1921
@dataclass
20-
class SerialisedClass:
22+
class SerialisedBuiltin:
23+
builtin: t.Any
24+
25+
def __hash__(self):
26+
return self.builtin.__name__
27+
28+
def __eq__(self, other):
29+
return self.__hash__() == other.__hash__()
30+
31+
def __repr__(self):
32+
return self.builtin.__name__
33+
34+
35+
@dataclass
36+
class SerialisedClassInstance:
2137
instance: object
2238

2339
def __hash__(self):
@@ -39,6 +55,30 @@ def __repr__(self):
3955
return f"{self.instance.__class__.__name__}({args})"
4056

4157

58+
@dataclass
59+
class SerialisedColumnInstance:
60+
instance: Column
61+
serialised_params: SerialisedParams
62+
63+
def __hash__(self):
64+
return self.instance.__hash__()
65+
66+
def __eq__(self, other):
67+
return self.__hash__() == other.__hash__()
68+
69+
def _serialise_value(self, value):
70+
return f"'{value}'" if isinstance(value, str) else value
71+
72+
def __repr__(self):
73+
args = ", ".join(
74+
[
75+
f"{key}={self._serialise_value(self.serialised_params.params.get(key))}" # noqa: E501
76+
for key in self.instance._meta.params.keys()
77+
]
78+
)
79+
return f"{self.instance.__class__.__name__}({args})"
80+
81+
4282
@dataclass
4383
class SerialisedTableType:
4484
table_type: t.Type[Table]
@@ -127,9 +167,40 @@ def serialise_params(params: t.Dict[str, t.Any]) -> SerialisedParams:
127167

128168
for key, value in params.items():
129169

170+
# Builtins, such as str, list and dict.
171+
if (
172+
hasattr(value, "__module__")
173+
and value.__module__ == builtins.__name__
174+
):
175+
params[key] = SerialisedBuiltin(builtin=value)
176+
continue
177+
178+
# Column instances, which are used by Array definitions.
179+
if isinstance(value, Column):
180+
column: Column = value
181+
serialised_params: SerialisedParams = serialise_params(
182+
params=column._meta.params
183+
)
184+
185+
# Include the extra imports and definitions required for the
186+
# column params.
187+
extra_imports.extend(serialised_params.extra_imports)
188+
extra_definitions.extend(serialised_params.extra_definitions)
189+
190+
extra_imports.append(
191+
Import(
192+
module=column.__class__.__module__,
193+
target=column.__class__.__name__,
194+
)
195+
)
196+
params[key] = SerialisedColumnInstance(
197+
instance=value, serialised_params=serialised_params
198+
)
199+
continue
200+
130201
# Class instances
131202
if isinstance(value, Default):
132-
params[key] = SerialisedClass(instance=value)
203+
params[key] = SerialisedClassInstance(instance=value)
133204
extra_imports.append(
134205
Import(
135206
module=value.__class__.__module__,
@@ -227,7 +298,7 @@ def deserialise_params(params: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]:
227298
if isinstance(value, str) and not isinstance(value, Enum):
228299
if value != "self":
229300
params[key] = deserialise_legacy_params(name=key, value=value)
230-
elif isinstance(value, SerialisedClass):
301+
elif isinstance(value, SerialisedClassInstance):
231302
params[key] = value.instance
232303
elif isinstance(value, SerialisedUUID):
233304
params[key] = value.instance

piccolo/columns/column_types.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,10 @@ def __init__(
13841384

13851385
self._validate_default(default, (list, None))
13861386

1387+
# Usually columns are given a name by the Table metaclass, but in this
1388+
# case we have to assign one manually.
1389+
base_column._meta._name = base_column.__class__.__name__
1390+
13871391
self.base_column = base_column
13881392
self.default = default
13891393
self.index: t.Optional[int] = None

0 commit comments

Comments
 (0)