piccolo 1.10.0__py3-none-any.whl → 1.12.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/asgi/commands/templates/app/_fastapi_app.py.jinja +35 -30
- piccolo/apps/asgi/commands/templates/app/_starlette_app.py.jinja +29 -21
- piccolo/apps/migrations/auto/migration_manager.py +1 -0
- piccolo/apps/migrations/commands/forwards.py +8 -7
- piccolo/apps/playground/commands/run.py +11 -0
- piccolo/columns/column_types.py +83 -35
- piccolo/query/functions/__init__.py +11 -1
- piccolo/query/functions/datetime.py +260 -0
- piccolo/query/functions/string.py +45 -0
- {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/METADATA +15 -15
- {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/RECORD +42 -40
- {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/WHEEL +1 -1
- tests/apps/migrations/commands/test_forwards_backwards.py +32 -1
- tests/columns/test_array.py +3 -7
- tests/columns/test_bigint.py +3 -9
- tests/columns/test_boolean.py +3 -7
- tests/columns/test_bytea.py +5 -14
- tests/columns/test_choices.py +5 -14
- tests/columns/test_date.py +5 -13
- tests/columns/test_double_precision.py +3 -8
- tests/columns/test_interval.py +5 -13
- tests/columns/test_json.py +9 -26
- tests/columns/test_jsonb.py +3 -11
- tests/columns/test_numeric.py +3 -7
- tests/columns/test_primary_key.py +11 -33
- tests/columns/test_readable.py +5 -7
- tests/columns/test_real.py +3 -8
- tests/columns/test_reserved_column_names.py +3 -8
- tests/columns/test_smallint.py +3 -8
- tests/columns/test_time.py +5 -14
- tests/columns/test_timestamp.py +5 -13
- tests/columns/test_timestamptz.py +5 -13
- tests/columns/test_uuid.py +3 -7
- tests/columns/test_varchar.py +3 -9
- tests/query/functions/base.py +2 -15
- tests/query/functions/test_datetime.py +112 -0
- tests/query/functions/test_math.py +2 -3
- tests/query/functions/test_string.py +34 -2
- {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/LICENSE +0 -0
- {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/entry_points.txt +0 -0
- {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/top_level.txt +0 -0
tests/columns/test_varchar.py
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
from unittest import TestCase
|
2
|
-
|
3
1
|
from piccolo.columns.column_types import Varchar
|
4
2
|
from piccolo.table import Table
|
5
3
|
|
6
|
-
from ..base import engines_only
|
4
|
+
from ..base import TableTest, engines_only
|
7
5
|
|
8
6
|
|
9
7
|
class MyTable(Table):
|
@@ -11,7 +9,7 @@ class MyTable(Table):
|
|
11
9
|
|
12
10
|
|
13
11
|
@engines_only("postgres", "cockroach")
|
14
|
-
class TestVarchar(
|
12
|
+
class TestVarchar(TableTest):
|
15
13
|
"""
|
16
14
|
SQLite doesn't enforce any constraints on max character length.
|
17
15
|
|
@@ -20,11 +18,7 @@ class TestVarchar(TestCase):
|
|
20
18
|
Might consider enforcing this at the ORM level instead in the future.
|
21
19
|
"""
|
22
20
|
|
23
|
-
|
24
|
-
MyTable.create_table().run_sync()
|
25
|
-
|
26
|
-
def tearDown(self):
|
27
|
-
MyTable.alter().drop_table().run_sync()
|
21
|
+
tables = [MyTable]
|
28
22
|
|
29
23
|
def test_length(self):
|
30
24
|
row = MyTable(name="bob")
|
tests/query/functions/base.py
CHANGED
@@ -1,21 +1,8 @@
|
|
1
|
-
|
2
|
-
from unittest import TestCase
|
3
|
-
|
4
|
-
from piccolo.table import Table, create_db_tables_sync, drop_db_tables_sync
|
1
|
+
from tests.base import TableTest
|
5
2
|
from tests.example_apps.music.tables import Band, Manager
|
6
3
|
|
7
4
|
|
8
|
-
class
|
9
|
-
tables: t.List[t.Type[Table]]
|
10
|
-
|
11
|
-
def setUp(self) -> None:
|
12
|
-
create_db_tables_sync(*self.tables)
|
13
|
-
|
14
|
-
def tearDown(self) -> None:
|
15
|
-
drop_db_tables_sync(*self.tables)
|
16
|
-
|
17
|
-
|
18
|
-
class BandTest(FunctionTest):
|
5
|
+
class BandTest(TableTest):
|
19
6
|
tables = [Band, Manager]
|
20
7
|
|
21
8
|
def setUp(self) -> None:
|
@@ -0,0 +1,112 @@
|
|
1
|
+
import datetime
|
2
|
+
|
3
|
+
from piccolo.columns import Timestamp
|
4
|
+
from piccolo.query.functions.datetime import (
|
5
|
+
Day,
|
6
|
+
Extract,
|
7
|
+
Hour,
|
8
|
+
Minute,
|
9
|
+
Month,
|
10
|
+
Second,
|
11
|
+
Strftime,
|
12
|
+
Year,
|
13
|
+
)
|
14
|
+
from piccolo.table import Table
|
15
|
+
from tests.base import TableTest, engines_only, sqlite_only
|
16
|
+
|
17
|
+
|
18
|
+
class Concert(Table):
|
19
|
+
starts = Timestamp()
|
20
|
+
|
21
|
+
|
22
|
+
class DatetimeTest(TableTest):
|
23
|
+
tables = [Concert]
|
24
|
+
|
25
|
+
def setUp(self) -> None:
|
26
|
+
super().setUp()
|
27
|
+
self.concert = Concert(
|
28
|
+
{
|
29
|
+
Concert.starts: datetime.datetime(
|
30
|
+
year=2024, month=6, day=14, hour=23, minute=46, second=10
|
31
|
+
)
|
32
|
+
}
|
33
|
+
)
|
34
|
+
self.concert.save().run_sync()
|
35
|
+
|
36
|
+
|
37
|
+
@engines_only("postgres", "cockroach")
|
38
|
+
class TestExtract(DatetimeTest):
|
39
|
+
def test_extract(self):
|
40
|
+
self.assertEqual(
|
41
|
+
Concert.select(
|
42
|
+
Extract(Concert.starts, "year", alias="starts_year")
|
43
|
+
).run_sync(),
|
44
|
+
[{"starts_year": self.concert.starts.year}],
|
45
|
+
)
|
46
|
+
|
47
|
+
def test_invalid_format(self):
|
48
|
+
with self.assertRaises(ValueError):
|
49
|
+
Extract(
|
50
|
+
Concert.starts,
|
51
|
+
"abc123", # type: ignore
|
52
|
+
alias="starts_year",
|
53
|
+
)
|
54
|
+
|
55
|
+
|
56
|
+
@sqlite_only
|
57
|
+
class TestStrftime(DatetimeTest):
|
58
|
+
def test_strftime(self):
|
59
|
+
self.assertEqual(
|
60
|
+
Concert.select(
|
61
|
+
Strftime(Concert.starts, "%Y", alias="starts_year")
|
62
|
+
).run_sync(),
|
63
|
+
[{"starts_year": str(self.concert.starts.year)}],
|
64
|
+
)
|
65
|
+
|
66
|
+
|
67
|
+
class TestDatabaseAgnostic(DatetimeTest):
|
68
|
+
def test_year(self):
|
69
|
+
self.assertEqual(
|
70
|
+
Concert.select(
|
71
|
+
Year(Concert.starts, alias="starts_year")
|
72
|
+
).run_sync(),
|
73
|
+
[{"starts_year": self.concert.starts.year}],
|
74
|
+
)
|
75
|
+
|
76
|
+
def test_month(self):
|
77
|
+
self.assertEqual(
|
78
|
+
Concert.select(
|
79
|
+
Month(Concert.starts, alias="starts_month")
|
80
|
+
).run_sync(),
|
81
|
+
[{"starts_month": self.concert.starts.month}],
|
82
|
+
)
|
83
|
+
|
84
|
+
def test_day(self):
|
85
|
+
self.assertEqual(
|
86
|
+
Concert.select(Day(Concert.starts, alias="starts_day")).run_sync(),
|
87
|
+
[{"starts_day": self.concert.starts.day}],
|
88
|
+
)
|
89
|
+
|
90
|
+
def test_hour(self):
|
91
|
+
self.assertEqual(
|
92
|
+
Concert.select(
|
93
|
+
Hour(Concert.starts, alias="starts_hour")
|
94
|
+
).run_sync(),
|
95
|
+
[{"starts_hour": self.concert.starts.hour}],
|
96
|
+
)
|
97
|
+
|
98
|
+
def test_minute(self):
|
99
|
+
self.assertEqual(
|
100
|
+
Concert.select(
|
101
|
+
Minute(Concert.starts, alias="starts_minute")
|
102
|
+
).run_sync(),
|
103
|
+
[{"starts_minute": self.concert.starts.minute}],
|
104
|
+
)
|
105
|
+
|
106
|
+
def test_second(self):
|
107
|
+
self.assertEqual(
|
108
|
+
Concert.select(
|
109
|
+
Second(Concert.starts, alias="starts_second")
|
110
|
+
).run_sync(),
|
111
|
+
[{"starts_second": self.concert.starts.second}],
|
112
|
+
)
|
@@ -3,15 +3,14 @@ import decimal
|
|
3
3
|
from piccolo.columns import Numeric
|
4
4
|
from piccolo.query.functions.math import Abs, Ceil, Floor, Round
|
5
5
|
from piccolo.table import Table
|
6
|
-
|
7
|
-
from .base import FunctionTest
|
6
|
+
from tests.base import TableTest
|
8
7
|
|
9
8
|
|
10
9
|
class Ticket(Table):
|
11
10
|
price = Numeric(digits=(5, 2))
|
12
11
|
|
13
12
|
|
14
|
-
class TestMath(
|
13
|
+
class TestMath(TableTest):
|
15
14
|
|
16
15
|
tables = [Ticket]
|
17
16
|
|
@@ -1,10 +1,13 @@
|
|
1
|
-
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from piccolo.query.functions.string import Concat, Upper
|
4
|
+
from tests.base import engine_version_lt, is_running_sqlite
|
2
5
|
from tests.example_apps.music.tables import Band
|
3
6
|
|
4
7
|
from .base import BandTest
|
5
8
|
|
6
9
|
|
7
|
-
class
|
10
|
+
class TestUpper(BandTest):
|
8
11
|
|
9
12
|
def test_column(self):
|
10
13
|
"""
|
@@ -23,3 +26,32 @@ class TestUpperFunction(BandTest):
|
|
23
26
|
"""
|
24
27
|
response = Band.select(Upper(Band.manager._.name)).run_sync()
|
25
28
|
self.assertListEqual(response, [{"upper": "GUIDO"}])
|
29
|
+
|
30
|
+
|
31
|
+
@pytest.mark.skipif(
|
32
|
+
is_running_sqlite() and engine_version_lt(3.44),
|
33
|
+
reason="SQLite version not supported",
|
34
|
+
)
|
35
|
+
class TestConcat(BandTest):
|
36
|
+
|
37
|
+
def test_column_and_string(self):
|
38
|
+
response = Band.select(
|
39
|
+
Concat(Band.name, "!!!", alias="name")
|
40
|
+
).run_sync()
|
41
|
+
self.assertListEqual(response, [{"name": "Pythonistas!!!"}])
|
42
|
+
|
43
|
+
def test_column_and_column(self):
|
44
|
+
response = Band.select(
|
45
|
+
Concat(Band.name, Band.popularity, alias="name")
|
46
|
+
).run_sync()
|
47
|
+
self.assertListEqual(response, [{"name": "Pythonistas1000"}])
|
48
|
+
|
49
|
+
def test_join(self):
|
50
|
+
response = Band.select(
|
51
|
+
Concat(Band.name, "-", Band.manager._.name, alias="name")
|
52
|
+
).run_sync()
|
53
|
+
self.assertListEqual(response, [{"name": "Pythonistas-Guido"}])
|
54
|
+
|
55
|
+
def test_min_args(self):
|
56
|
+
with self.assertRaises(ValueError):
|
57
|
+
Concat()
|
File without changes
|
File without changes
|
File without changes
|