Skip to content

Commit 06e3ba3

Browse files
committed
added tests for Time columns in migrations
1 parent b70742b commit 06e3ba3

File tree

7 files changed

+67
-13
lines changed

7 files changed

+67
-13
lines changed

piccolo/apps/migrations/auto/serialisation.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from piccolo.columns.defaults.base import Default
1414
from piccolo.columns.reference import LazyTableReference
1515
from piccolo.table import Table
16+
from piccolo.utils.repr import repr_class_instance
1617
from .serialisation_legacy import deserialise_legacy_params
1718

1819
###############################################################################
@@ -43,13 +44,7 @@ def __eq__(self, other):
4344
return self.__hash__() == other.__hash__()
4445

4546
def __repr__(self):
46-
args = ", ".join(
47-
[
48-
f"{key}={value.__repr__()}"
49-
for key, value in self.instance.__dict__.items()
50-
]
51-
)
52-
return f"{self.instance.__class__.__name__}({args})"
47+
return repr_class_instance(self.instance)
5348

5449

5550
@dataclass
@@ -327,6 +322,13 @@ def serialise_params(params: t.Dict[str, t.Any]) -> SerialisedParams:
327322
)
328323
continue
329324

325+
if inspect.isclass(value) and not issubclass(value, Enum):
326+
params[key] = SerialisedCallable(callable_=value)
327+
extra_imports.append(
328+
Import(module=value.__module__, target=value.__name__)
329+
)
330+
continue
331+
330332
# All other types can remain as is.
331333

332334
return SerialisedParams(

piccolo/apps/migrations/commands/new.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,4 @@ async def new(app_name: str, auto: bool = False):
200200
await _create_new_migration(app_config=app_config, auto=auto)
201201
except NoChanges:
202202
print("No changes detected - exiting.")
203+
sys.exit(0)

piccolo/columns/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,8 @@ def get_sql_value(self, value: t.Any) -> t.Any:
541541
output = str(value).lower()
542542
elif isinstance(value, datetime.datetime):
543543
output = f"'{value.isoformat().replace('T', ' ')}'"
544+
elif isinstance(value, datetime.time):
545+
output = f"'{value.isoformat()}'"
544546
elif isinstance(value, bytes):
545547
output = f"'{value.hex()}'"
546548
elif isinstance(value, uuid.UUID):

piccolo/columns/defaults/base.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from abc import abstractmethod, abstractproperty, ABC
33
import typing as t
44

5+
from piccolo.utils.repr import repr_class_instance
6+
57

68
class Default(ABC):
79
@abstractproperty
@@ -50,11 +52,11 @@ def get_sqlite_interval_string(self, attributes: t.List[str]) -> str:
5052

5153
return ", ".join(interval_components)
5254

55+
def __repr__(self):
56+
return repr_class_instance(self)
57+
5358
def __str__(self):
54-
args_str = ", ".join(
55-
[f"{key}={value}" for key, value in self.__dict__.items()]
56-
)
57-
return f"{self.__class__.__name__}({args_str})"
59+
return self.__repr__()
5860

5961
def __eq__(self, other):
6062
return self.__hash__() == other.__hash__()

piccolo/columns/defaults/time.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ def __init__(self, hour: int, minute: int, second: int):
5757

5858
@property
5959
def postgres(self):
60-
return self.time.isostring()
60+
return f"'{self.time.isoformat()}'"
6161

6262
@property
6363
def sqlite(self):
64-
return self.time.isostring()
64+
return f"'{self.time.isoformat()}'"
6565

6666
def python(self):
6767
return self.time

piccolo/utils/repr.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import inspect
2+
3+
4+
def repr_class_instance(class_instance: object) -> str:
5+
"""
6+
Piccolo uses code generation for creating migrations. This function takes
7+
a class instance, and generates a string representation for it, which can
8+
be used in a migration file.
9+
"""
10+
init_arg_names = [
11+
i
12+
for i in inspect.signature(
13+
class_instance.__class__.__init__
14+
).parameters.keys()
15+
if i not in ("self", "args", "kwargs")
16+
]
17+
args_dict = {}
18+
for arg_name in init_arg_names:
19+
value = class_instance.__dict__.get(arg_name)
20+
args_dict[arg_name] = value
21+
22+
args_str = ", ".join(
23+
[f"{key}={value.__repr__()}" for key, value in args_dict.items()]
24+
)
25+
return f"{class_instance.__class__.__name__}({args_str})"

tests/apps/migrations/auto/integration/test_migrations.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
Integer,
1616
SmallInt,
1717
Text,
18+
Time,
1819
Timestamp,
1920
UUID,
2021
Varchar,
@@ -49,6 +50,10 @@ def datetime_default():
4950
return datetime.datetime.now()
5051

5152

53+
def time_default():
54+
return datetime.datetime.now().time()
55+
56+
5257
@postgres_only
5358
class TestMigrations(TestCase):
5459
def tearDown(self):
@@ -223,3 +228,20 @@ def test_timestamp_column(self):
223228
]
224229
]
225230
)
231+
232+
def test_time_column(self):
233+
self._test_migrations(
234+
table_classes=[
235+
self.table(column)
236+
for column in [
237+
Time(),
238+
Time(default=datetime.time(hour=12, minute=0)),
239+
Time(default=datetime.time),
240+
Time(default=time_default),
241+
Time(null=True, default=None),
242+
Time(null=False),
243+
Time(index=True),
244+
Time(index=False),
245+
]
246+
]
247+
)

0 commit comments

Comments
 (0)