Skip to content

Commit 1f8b9eb

Browse files
authored
Merge pull request piccolo-orm#114 from piccolo-orm/choice_defaults
Choice defaults
2 parents 467a0b6 + 37b53c1 commit 1f8b9eb

File tree

2 files changed

+71
-6
lines changed

2 files changed

+71
-6
lines changed

piccolo/apps/migrations/auto/serialisation.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,20 @@ def __repr__(self):
7373
return f"{self.instance.__class__.__name__}({args})"
7474

7575

76+
@dataclass
77+
class SerialisedEnumInstance:
78+
instance: Enum
79+
80+
def __hash__(self):
81+
return hash(self.__repr__())
82+
83+
def __eq__(self, other):
84+
return self.__hash__() == other.__hash__()
85+
86+
def __repr__(self):
87+
return f"{self.instance.__class__.__name__}.{self.instance.name}"
88+
89+
7690
@dataclass
7791
class SerialisedTableType:
7892
table_type: t.Type[Table]
@@ -241,14 +255,29 @@ def serialise_params(params: t.Dict[str, t.Any]) -> SerialisedParams:
241255
extra_imports.append(Import(module="decimal", target="Decimal"))
242256
continue
243257

244-
# Enums
258+
# Enum instances
245259
if isinstance(value, Enum):
246-
# Enums already have a good __repr__.
247-
extra_imports.append(
248-
Import(
249-
module=value.__module__, target=value.__class__.__name__,
260+
if value.__module__.startswith("piccolo"):
261+
# It's an Enum defined within Piccolo, so we can safely import
262+
# it.
263+
params[key] = SerialisedEnumInstance(instance=value)
264+
extra_imports.append(
265+
Import(
266+
module=value.__module__,
267+
target=value.__class__.__name__,
268+
)
250269
)
251-
)
270+
else:
271+
# It's a user defined Enum, so we'll insert the raw value.
272+
enum_serialised_params: SerialisedParams = serialise_params(
273+
params={key: value.value}
274+
)
275+
params[key] = enum_serialised_params.params[key]
276+
extra_imports.extend(enum_serialised_params.extra_imports)
277+
extra_definitions.extend(
278+
enum_serialised_params.extra_definitions
279+
)
280+
252281
continue
253282

254283
# Enum types
@@ -329,5 +358,7 @@ def deserialise_params(params: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]:
329358
params[key] = value.table_type
330359
elif isinstance(value, SerialisedEnumType):
331360
params[key] = value.enum_type
361+
elif isinstance(value, SerialisedEnumInstance):
362+
params[key] = value.instance
332363

333364
return params

tests/apps/migrations/auto/test_serialisation.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from unittest import TestCase
33

44
from piccolo.apps.migrations.auto.serialisation import serialise_params
5+
from piccolo.columns.base import OnDelete
56
from piccolo.columns.choices import Choice
67
from piccolo.columns.column_types import Varchar
78
from piccolo.columns.defaults import DateNow, TimeNow, TimestampNow, UUID4
@@ -148,3 +149,36 @@ class Choices(Enum):
148149
"from enum import Enum",
149150
},
150151
)
152+
153+
def test_custom_enum_instance(self):
154+
"""
155+
Make sure custom Enum instances can be serialised properly. An example
156+
is when a user defines a choices Enum, and then sets the default to
157+
one of those choices.
158+
"""
159+
160+
class Choices(Enum):
161+
a = 1
162+
b = 2
163+
164+
serialised = serialise_params(params={"default": Choices.a})
165+
166+
self.assertEqual(serialised.params["default"], 1)
167+
self.assertEqual(serialised.extra_imports, [])
168+
self.assertEqual(serialised.extra_definitions, [])
169+
170+
def test_builtin_enum_instance(self):
171+
"""
172+
Make sure Enum instances defiend in Piccolo can be serialised properly
173+
- for example, with on_delete.
174+
"""
175+
serialised = serialise_params(params={"on_delete": OnDelete.cascade})
176+
177+
self.assertEqual(
178+
serialised.params["on_delete"].__repr__(), "OnDelete.cascade"
179+
)
180+
self.assertEqual(
181+
[i.__repr__() for i in serialised.extra_imports],
182+
["from piccolo.columns.base import OnDelete"],
183+
)
184+
self.assertEqual(serialised.extra_definitions, [])

0 commit comments

Comments
 (0)