piccolo 1.7.0__py3-none-any.whl → 1.9.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/columns/base.py +59 -29
- piccolo/columns/defaults/base.py +5 -3
- piccolo/query/functions/__init__.py +7 -0
- piccolo/query/functions/aggregate.py +12 -12
- piccolo/query/functions/math.py +48 -0
- piccolo/query/functions/type_conversion.py +82 -0
- piccolo/querystring.py +30 -0
- piccolo/schema.py +2 -1
- {piccolo-1.7.0.dist-info → piccolo-1.9.0.dist-info}/METADATA +1 -1
- {piccolo-1.7.0.dist-info → piccolo-1.9.0.dist-info}/RECORD +26 -18
- tests/apps/migrations/auto/integration/test_migrations.py +28 -5
- tests/apps/migrations/auto/test_migration_manager.py +15 -15
- tests/columns/test_array.py +63 -19
- tests/columns/test_get_sql_value.py +66 -0
- tests/query/functions/__init__.py +0 -0
- tests/query/functions/base.py +34 -0
- tests/query/{test_functions.py → functions/test_functions.py} +5 -43
- tests/query/functions/test_math.py +39 -0
- tests/query/functions/test_string.py +25 -0
- tests/query/functions/test_type_conversion.py +134 -0
- tests/query/test_querystring.py +136 -0
- {piccolo-1.7.0.dist-info → piccolo-1.9.0.dist-info}/LICENSE +0 -0
- {piccolo-1.7.0.dist-info → piccolo-1.9.0.dist-info}/WHEEL +0 -0
- {piccolo-1.7.0.dist-info → piccolo-1.9.0.dist-info}/entry_points.txt +0 -0
- {piccolo-1.7.0.dist-info → piccolo-1.9.0.dist-info}/top_level.txt +0 -0
@@ -768,15 +768,15 @@ class TestMigrationManager(DBTestCase):
|
|
768
768
|
)
|
769
769
|
|
770
770
|
asyncio.run(manager.run())
|
771
|
-
self.
|
772
|
-
self._get_column_default(),
|
773
|
-
[
|
771
|
+
self.assertIn(
|
772
|
+
self._get_column_default()[0]["column_default"],
|
773
|
+
["'Unknown'", "'Unknown':::STRING"],
|
774
774
|
)
|
775
775
|
|
776
776
|
asyncio.run(manager.run(backwards=True))
|
777
|
-
self.
|
778
|
-
self._get_column_default(),
|
779
|
-
[
|
777
|
+
self.assertIn(
|
778
|
+
self._get_column_default()[0]["column_default"],
|
779
|
+
["''", "'':::STRING"],
|
780
780
|
)
|
781
781
|
|
782
782
|
@engines_only("postgres")
|
@@ -856,9 +856,9 @@ class TestMigrationManager(DBTestCase):
|
|
856
856
|
old_params={"default": None},
|
857
857
|
)
|
858
858
|
asyncio.run(manager_1.run())
|
859
|
-
self.
|
860
|
-
self._get_column_default(),
|
861
|
-
[
|
859
|
+
self.assertIn(
|
860
|
+
self._get_column_default()[0]["column_default"],
|
861
|
+
["'Mr Manager'", "'Mr Manager':::STRING"],
|
862
862
|
)
|
863
863
|
|
864
864
|
# Drop the default.
|
@@ -879,9 +879,9 @@ class TestMigrationManager(DBTestCase):
|
|
879
879
|
# And add it back once more to be sure.
|
880
880
|
manager_3 = manager_1
|
881
881
|
asyncio.run(manager_3.run())
|
882
|
-
self.
|
883
|
-
self._get_column_default(),
|
884
|
-
[
|
882
|
+
self.assertIn(
|
883
|
+
self._get_column_default()[0]["column_default"],
|
884
|
+
["'Mr Manager'", "'Mr Manager':::STRING"],
|
885
885
|
)
|
886
886
|
|
887
887
|
# Run them all backwards
|
@@ -892,9 +892,9 @@ class TestMigrationManager(DBTestCase):
|
|
892
892
|
)
|
893
893
|
|
894
894
|
asyncio.run(manager_2.run(backwards=True))
|
895
|
-
self.
|
896
|
-
self._get_column_default(),
|
897
|
-
[
|
895
|
+
self.assertIn(
|
896
|
+
self._get_column_default()[0]["column_default"],
|
897
|
+
["'Mr Manager'", "'Mr Manager':::STRING"],
|
898
898
|
)
|
899
899
|
|
900
900
|
asyncio.run(manager_1.run(backwards=True))
|
tests/columns/test_array.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
import datetime
|
2
2
|
from unittest import TestCase
|
3
3
|
|
4
|
+
import pytest
|
5
|
+
|
4
6
|
from piccolo.columns.column_types import (
|
5
7
|
Array,
|
6
8
|
BigInt,
|
@@ -10,8 +12,9 @@ from piccolo.columns.column_types import (
|
|
10
12
|
Timestamp,
|
11
13
|
Timestamptz,
|
12
14
|
)
|
15
|
+
from piccolo.querystring import QueryString
|
13
16
|
from piccolo.table import Table
|
14
|
-
from tests.base import engines_only, sqlite_only
|
17
|
+
from tests.base import engines_only, engines_skip, sqlite_only
|
15
18
|
|
16
19
|
|
17
20
|
class MyTable(Table):
|
@@ -40,12 +43,18 @@ class TestArray(TestCase):
|
|
40
43
|
def tearDown(self):
|
41
44
|
MyTable.alter().drop_table().run_sync()
|
42
45
|
|
43
|
-
@
|
46
|
+
@pytest.mark.cockroach_array_slow
|
44
47
|
def test_storage(self):
|
45
48
|
"""
|
46
49
|
Make sure data can be stored and retrieved.
|
47
50
|
|
48
|
-
|
51
|
+
In CockroachDB <= v22.2.0 we had this error:
|
52
|
+
|
53
|
+
* https://github.com/cockroachdb/cockroach/issues/71908 "could not decorrelate subquery" error under asyncpg
|
54
|
+
|
55
|
+
In newer CockroachDB versions, it runs but is very slow:
|
56
|
+
|
57
|
+
* https://github.com/piccolo-orm/piccolo/issues/1005
|
49
58
|
|
50
59
|
""" # noqa: E501
|
51
60
|
MyTable(value=[1, 2, 3]).save().run_sync()
|
@@ -54,12 +63,19 @@ class TestArray(TestCase):
|
|
54
63
|
assert row is not None
|
55
64
|
self.assertEqual(row.value, [1, 2, 3])
|
56
65
|
|
57
|
-
@
|
66
|
+
@engines_skip("sqlite")
|
67
|
+
@pytest.mark.cockroach_array_slow
|
58
68
|
def test_index(self):
|
59
69
|
"""
|
60
70
|
Indexes should allow individual array elements to be queried.
|
61
71
|
|
62
|
-
|
72
|
+
In CockroachDB <= v22.2.0 we had this error:
|
73
|
+
|
74
|
+
* https://github.com/cockroachdb/cockroach/issues/71908 "could not decorrelate subquery" error under asyncpg
|
75
|
+
|
76
|
+
In newer CockroachDB versions, it runs but is very slow:
|
77
|
+
|
78
|
+
* https://github.com/piccolo-orm/piccolo/issues/1005
|
63
79
|
|
64
80
|
""" # noqa: E501
|
65
81
|
MyTable(value=[1, 2, 3]).save().run_sync()
|
@@ -68,66 +84,92 @@ class TestArray(TestCase):
|
|
68
84
|
MyTable.select(MyTable.value[0]).first().run_sync(), {"value": 1}
|
69
85
|
)
|
70
86
|
|
71
|
-
@
|
87
|
+
@engines_skip("sqlite")
|
88
|
+
@pytest.mark.cockroach_array_slow
|
72
89
|
def test_all(self):
|
73
90
|
"""
|
74
91
|
Make sure rows can be retrieved where all items in an array match a
|
75
92
|
given value.
|
76
93
|
|
77
|
-
|
94
|
+
In CockroachDB <= v22.2.0 we had this error:
|
95
|
+
|
96
|
+
* https://github.com/cockroachdb/cockroach/issues/71908 "could not decorrelate subquery" error under asyncpg
|
97
|
+
|
98
|
+
In newer CockroachDB versions, it runs but is very slow:
|
99
|
+
|
100
|
+
* https://github.com/piccolo-orm/piccolo/issues/1005
|
78
101
|
|
79
102
|
""" # noqa: E501
|
80
103
|
MyTable(value=[1, 1, 1]).save().run_sync()
|
81
104
|
|
105
|
+
# We have to explicitly specify the type, so CockroachDB works.
|
82
106
|
self.assertEqual(
|
83
107
|
MyTable.select(MyTable.value)
|
84
|
-
.where(MyTable.value.all(1))
|
108
|
+
.where(MyTable.value.all(QueryString("{}::INTEGER", 1)))
|
85
109
|
.first()
|
86
110
|
.run_sync(),
|
87
111
|
{"value": [1, 1, 1]},
|
88
112
|
)
|
89
113
|
|
114
|
+
# We have to explicitly specify the type, so CockroachDB works.
|
90
115
|
self.assertEqual(
|
91
116
|
MyTable.select(MyTable.value)
|
92
|
-
.where(MyTable.value.all(0))
|
117
|
+
.where(MyTable.value.all(QueryString("{}::INTEGER", 0)))
|
93
118
|
.first()
|
94
119
|
.run_sync(),
|
95
120
|
None,
|
96
121
|
)
|
97
122
|
|
98
|
-
@
|
123
|
+
@engines_skip("sqlite")
|
124
|
+
@pytest.mark.cockroach_array_slow
|
99
125
|
def test_any(self):
|
100
126
|
"""
|
101
127
|
Make sure rows can be retrieved where any items in an array match a
|
102
128
|
given value.
|
103
129
|
|
104
|
-
|
130
|
+
In CockroachDB <= v22.2.0 we had this error:
|
131
|
+
|
132
|
+
* https://github.com/cockroachdb/cockroach/issues/71908 "could not decorrelate subquery" error under asyncpg
|
133
|
+
|
134
|
+
In newer CockroachDB versions, it runs but is very slow:
|
135
|
+
|
136
|
+
* https://github.com/piccolo-orm/piccolo/issues/1005
|
105
137
|
|
106
138
|
""" # noqa: E501
|
139
|
+
|
107
140
|
MyTable(value=[1, 2, 3]).save().run_sync()
|
108
141
|
|
142
|
+
# We have to explicitly specify the type, so CockroachDB works.
|
109
143
|
self.assertEqual(
|
110
144
|
MyTable.select(MyTable.value)
|
111
|
-
.where(MyTable.value.any(1))
|
145
|
+
.where(MyTable.value.any(QueryString("{}::INTEGER", 1)))
|
112
146
|
.first()
|
113
147
|
.run_sync(),
|
114
148
|
{"value": [1, 2, 3]},
|
115
149
|
)
|
116
150
|
|
151
|
+
# We have to explicitly specify the type, so CockroachDB works.
|
117
152
|
self.assertEqual(
|
118
153
|
MyTable.select(MyTable.value)
|
119
|
-
.where(MyTable.value.any(0))
|
154
|
+
.where(MyTable.value.any(QueryString("{}::INTEGER", 0)))
|
120
155
|
.first()
|
121
156
|
.run_sync(),
|
122
157
|
None,
|
123
158
|
)
|
124
159
|
|
125
|
-
@
|
160
|
+
@engines_skip("sqlite")
|
161
|
+
@pytest.mark.cockroach_array_slow
|
126
162
|
def test_cat(self):
|
127
163
|
"""
|
128
164
|
Make sure values can be appended to an array.
|
129
165
|
|
130
|
-
|
166
|
+
In CockroachDB <= v22.2.0 we had this error:
|
167
|
+
|
168
|
+
* https://github.com/cockroachdb/cockroach/issues/71908 "could not decorrelate subquery" error under asyncpg
|
169
|
+
|
170
|
+
In newer CockroachDB versions, it runs but is very slow:
|
171
|
+
|
172
|
+
* https://github.com/piccolo-orm/piccolo/issues/1005
|
131
173
|
|
132
174
|
""" # noqa: E501
|
133
175
|
MyTable(value=[1, 1, 1]).save().run_sync()
|
@@ -137,7 +179,8 @@ class TestArray(TestCase):
|
|
137
179
|
).run_sync()
|
138
180
|
|
139
181
|
self.assertEqual(
|
140
|
-
MyTable.select().run_sync(),
|
182
|
+
MyTable.select(MyTable.value).run_sync(),
|
183
|
+
[{"value": [1, 1, 1, 2]}],
|
141
184
|
)
|
142
185
|
|
143
186
|
# Try plus symbol
|
@@ -147,7 +190,8 @@ class TestArray(TestCase):
|
|
147
190
|
).run_sync()
|
148
191
|
|
149
192
|
self.assertEqual(
|
150
|
-
MyTable.select().run_sync(),
|
193
|
+
MyTable.select(MyTable.value).run_sync(),
|
194
|
+
[{"value": [1, 1, 1, 2, 3]}],
|
151
195
|
)
|
152
196
|
|
153
197
|
# Make sure non-list values work
|
@@ -157,8 +201,8 @@ class TestArray(TestCase):
|
|
157
201
|
).run_sync()
|
158
202
|
|
159
203
|
self.assertEqual(
|
160
|
-
MyTable.select().run_sync(),
|
161
|
-
[{"
|
204
|
+
MyTable.select(MyTable.value).run_sync(),
|
205
|
+
[{"value": [1, 1, 1, 2, 3, 4]}],
|
162
206
|
)
|
163
207
|
|
164
208
|
@sqlite_only
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import datetime
|
2
|
+
from unittest import TestCase
|
3
|
+
|
4
|
+
from tests.base import engines_only
|
5
|
+
from tests.example_apps.music.tables import Band
|
6
|
+
|
7
|
+
|
8
|
+
@engines_only("postgres", "cockroach")
|
9
|
+
class TestArrayPostgres(TestCase):
|
10
|
+
|
11
|
+
def test_string(self):
|
12
|
+
self.assertEqual(
|
13
|
+
Band.name.get_sql_value(["a", "b", "c"]),
|
14
|
+
'\'{"a","b","c"}\'',
|
15
|
+
)
|
16
|
+
|
17
|
+
def test_int(self):
|
18
|
+
self.assertEqual(
|
19
|
+
Band.name.get_sql_value([1, 2, 3]),
|
20
|
+
"'{1,2,3}'",
|
21
|
+
)
|
22
|
+
|
23
|
+
def test_nested(self):
|
24
|
+
self.assertEqual(
|
25
|
+
Band.name.get_sql_value([1, 2, 3, [4, 5, 6]]),
|
26
|
+
"'{1,2,3,{4,5,6}}'",
|
27
|
+
)
|
28
|
+
|
29
|
+
def test_time(self):
|
30
|
+
self.assertEqual(
|
31
|
+
Band.name.get_sql_value([datetime.time(hour=8, minute=0)]),
|
32
|
+
"'{\"08:00:00\"}'",
|
33
|
+
)
|
34
|
+
|
35
|
+
|
36
|
+
@engines_only("sqlite")
|
37
|
+
class TestArraySQLite(TestCase):
|
38
|
+
"""
|
39
|
+
Note, we use ``.replace(" ", "")`` because we serialise arrays using
|
40
|
+
Python's json library, and there is inconsistency between Python versions
|
41
|
+
(some output ``["a", "b", "c"]``, and others ``["a","b","c"]``).
|
42
|
+
"""
|
43
|
+
|
44
|
+
def test_string(self):
|
45
|
+
self.assertEqual(
|
46
|
+
Band.name.get_sql_value(["a", "b", "c"]).replace(" ", ""),
|
47
|
+
'\'["a","b","c"]\'',
|
48
|
+
)
|
49
|
+
|
50
|
+
def test_int(self):
|
51
|
+
self.assertEqual(
|
52
|
+
Band.name.get_sql_value([1, 2, 3]).replace(" ", ""),
|
53
|
+
"'[1,2,3]'",
|
54
|
+
)
|
55
|
+
|
56
|
+
def test_nested(self):
|
57
|
+
self.assertEqual(
|
58
|
+
Band.name.get_sql_value([1, 2, 3, [4, 5, 6]]).replace(" ", ""),
|
59
|
+
"'[1,2,3,[4,5,6]]'",
|
60
|
+
)
|
61
|
+
|
62
|
+
def test_time(self):
|
63
|
+
self.assertEqual(
|
64
|
+
Band.name.get_sql_value([datetime.time(hour=8, minute=0)]),
|
65
|
+
"'[\"08:00:00\"]'",
|
66
|
+
)
|
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import typing as t
|
2
|
+
from unittest import TestCase
|
3
|
+
|
4
|
+
from piccolo.table import Table, create_db_tables_sync, drop_db_tables_sync
|
5
|
+
from tests.example_apps.music.tables import Band, Manager
|
6
|
+
|
7
|
+
|
8
|
+
class FunctionTest(TestCase):
|
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):
|
19
|
+
tables = [Band, Manager]
|
20
|
+
|
21
|
+
def setUp(self) -> None:
|
22
|
+
super().setUp()
|
23
|
+
|
24
|
+
manager = Manager({Manager.name: "Guido"})
|
25
|
+
manager.save().run_sync()
|
26
|
+
|
27
|
+
band = Band(
|
28
|
+
{
|
29
|
+
Band.name: "Pythonistas",
|
30
|
+
Band.manager: manager,
|
31
|
+
Band.popularity: 1000,
|
32
|
+
}
|
33
|
+
)
|
34
|
+
band.save().run_sync()
|
@@ -1,51 +1,13 @@
|
|
1
|
-
from
|
2
|
-
|
3
|
-
from piccolo.query.functions.string import Reverse, Upper
|
1
|
+
from piccolo.query.functions import Reverse, Upper
|
4
2
|
from piccolo.querystring import QueryString
|
5
|
-
from piccolo.table import create_db_tables_sync, drop_db_tables_sync
|
6
3
|
from tests.base import engines_skip
|
7
|
-
from tests.example_apps.music.tables import Band
|
8
|
-
|
9
|
-
|
10
|
-
class FunctionTest(TestCase):
|
11
|
-
tables = (Band, Manager)
|
12
|
-
|
13
|
-
def setUp(self) -> None:
|
14
|
-
create_db_tables_sync(*self.tables)
|
15
|
-
|
16
|
-
manager = Manager({Manager.name: "Guido"})
|
17
|
-
manager.save().run_sync()
|
18
|
-
|
19
|
-
band = Band({Band.name: "Pythonistas", Band.manager: manager})
|
20
|
-
band.save().run_sync()
|
21
|
-
|
22
|
-
def tearDown(self) -> None:
|
23
|
-
drop_db_tables_sync(*self.tables)
|
24
|
-
|
4
|
+
from tests.example_apps.music.tables import Band
|
25
5
|
|
26
|
-
|
27
|
-
|
28
|
-
def test_column(self):
|
29
|
-
"""
|
30
|
-
Make sure we can uppercase a column's value.
|
31
|
-
"""
|
32
|
-
response = Band.select(Upper(Band.name)).run_sync()
|
33
|
-
self.assertListEqual(response, [{"upper": "PYTHONISTAS"}])
|
34
|
-
|
35
|
-
def test_alias(self):
|
36
|
-
response = Band.select(Upper(Band.name, alias="name")).run_sync()
|
37
|
-
self.assertListEqual(response, [{"name": "PYTHONISTAS"}])
|
38
|
-
|
39
|
-
def test_joined_column(self):
|
40
|
-
"""
|
41
|
-
Make sure we can uppercase a column's value from a joined table.
|
42
|
-
"""
|
43
|
-
response = Band.select(Upper(Band.manager._.name)).run_sync()
|
44
|
-
self.assertListEqual(response, [{"upper": "GUIDO"}])
|
6
|
+
from .base import BandTest
|
45
7
|
|
46
8
|
|
47
9
|
@engines_skip("sqlite")
|
48
|
-
class TestNested(
|
10
|
+
class TestNested(BandTest):
|
49
11
|
"""
|
50
12
|
Skip the the test for SQLite, as it doesn't support ``Reverse``.
|
51
13
|
"""
|
@@ -76,7 +38,7 @@ class TestNested(FunctionTest):
|
|
76
38
|
self.assertListEqual(response, [{"concat": "GUIDO!"}])
|
77
39
|
|
78
40
|
|
79
|
-
class TestWhereClause(
|
41
|
+
class TestWhereClause(BandTest):
|
80
42
|
|
81
43
|
def test_where(self):
|
82
44
|
"""
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import decimal
|
2
|
+
|
3
|
+
from piccolo.columns import Numeric
|
4
|
+
from piccolo.query.functions.math import Abs, Ceil, Floor, Round
|
5
|
+
from piccolo.table import Table
|
6
|
+
|
7
|
+
from .base import FunctionTest
|
8
|
+
|
9
|
+
|
10
|
+
class Ticket(Table):
|
11
|
+
price = Numeric(digits=(5, 2))
|
12
|
+
|
13
|
+
|
14
|
+
class TestMath(FunctionTest):
|
15
|
+
|
16
|
+
tables = [Ticket]
|
17
|
+
|
18
|
+
def setUp(self):
|
19
|
+
super().setUp()
|
20
|
+
self.ticket = Ticket({Ticket.price: decimal.Decimal("36.50")})
|
21
|
+
self.ticket.save().run_sync()
|
22
|
+
|
23
|
+
def test_floor(self):
|
24
|
+
response = Ticket.select(Floor(Ticket.price, alias="price")).run_sync()
|
25
|
+
self.assertListEqual(response, [{"price": decimal.Decimal("36.00")}])
|
26
|
+
|
27
|
+
def test_ceil(self):
|
28
|
+
response = Ticket.select(Ceil(Ticket.price, alias="price")).run_sync()
|
29
|
+
self.assertListEqual(response, [{"price": decimal.Decimal("37.00")}])
|
30
|
+
|
31
|
+
def test_abs(self):
|
32
|
+
self.ticket.price = decimal.Decimal("-1.50")
|
33
|
+
self.ticket.save().run_sync()
|
34
|
+
response = Ticket.select(Abs(Ticket.price, alias="price")).run_sync()
|
35
|
+
self.assertListEqual(response, [{"price": decimal.Decimal("1.50")}])
|
36
|
+
|
37
|
+
def test_round(self):
|
38
|
+
response = Ticket.select(Round(Ticket.price, alias="price")).run_sync()
|
39
|
+
self.assertListEqual(response, [{"price": decimal.Decimal("37.00")}])
|
@@ -0,0 +1,25 @@
|
|
1
|
+
from piccolo.query.functions.string import Upper
|
2
|
+
from tests.example_apps.music.tables import Band
|
3
|
+
|
4
|
+
from .base import BandTest
|
5
|
+
|
6
|
+
|
7
|
+
class TestUpperFunction(BandTest):
|
8
|
+
|
9
|
+
def test_column(self):
|
10
|
+
"""
|
11
|
+
Make sure we can uppercase a column's value.
|
12
|
+
"""
|
13
|
+
response = Band.select(Upper(Band.name)).run_sync()
|
14
|
+
self.assertListEqual(response, [{"upper": "PYTHONISTAS"}])
|
15
|
+
|
16
|
+
def test_alias(self):
|
17
|
+
response = Band.select(Upper(Band.name, alias="name")).run_sync()
|
18
|
+
self.assertListEqual(response, [{"name": "PYTHONISTAS"}])
|
19
|
+
|
20
|
+
def test_joined_column(self):
|
21
|
+
"""
|
22
|
+
Make sure we can uppercase a column's value from a joined table.
|
23
|
+
"""
|
24
|
+
response = Band.select(Upper(Band.manager._.name)).run_sync()
|
25
|
+
self.assertListEqual(response, [{"upper": "GUIDO"}])
|
@@ -0,0 +1,134 @@
|
|
1
|
+
from piccolo.columns import Integer, Text, Varchar
|
2
|
+
from piccolo.query.functions import Cast, Length
|
3
|
+
from tests.example_apps.music.tables import Band, Manager
|
4
|
+
|
5
|
+
from .base import BandTest
|
6
|
+
|
7
|
+
|
8
|
+
class TestCast(BandTest):
|
9
|
+
def test_varchar(self):
|
10
|
+
"""
|
11
|
+
Make sure that casting to ``Varchar`` works.
|
12
|
+
"""
|
13
|
+
response = Band.select(
|
14
|
+
Cast(
|
15
|
+
Band.popularity,
|
16
|
+
as_type=Varchar(),
|
17
|
+
)
|
18
|
+
).run_sync()
|
19
|
+
|
20
|
+
self.assertListEqual(
|
21
|
+
response,
|
22
|
+
[{"popularity": "1000"}],
|
23
|
+
)
|
24
|
+
|
25
|
+
def test_text(self):
|
26
|
+
"""
|
27
|
+
Make sure that casting to ``Text`` works.
|
28
|
+
"""
|
29
|
+
response = Band.select(
|
30
|
+
Cast(
|
31
|
+
Band.popularity,
|
32
|
+
as_type=Text(),
|
33
|
+
)
|
34
|
+
).run_sync()
|
35
|
+
|
36
|
+
self.assertListEqual(
|
37
|
+
response,
|
38
|
+
[{"popularity": "1000"}],
|
39
|
+
)
|
40
|
+
|
41
|
+
def test_integer(self):
|
42
|
+
"""
|
43
|
+
Make sure that casting to ``Integer`` works.
|
44
|
+
"""
|
45
|
+
Band.update({Band.name: "1111"}, force=True).run_sync()
|
46
|
+
|
47
|
+
response = Band.select(
|
48
|
+
Cast(
|
49
|
+
Band.name,
|
50
|
+
as_type=Integer(),
|
51
|
+
)
|
52
|
+
).run_sync()
|
53
|
+
|
54
|
+
self.assertListEqual(
|
55
|
+
response,
|
56
|
+
[{"name": 1111}],
|
57
|
+
)
|
58
|
+
|
59
|
+
def test_join(self):
|
60
|
+
"""
|
61
|
+
Make sure that casting works with joins.
|
62
|
+
"""
|
63
|
+
Manager.update({Manager.name: "1111"}, force=True).run_sync()
|
64
|
+
|
65
|
+
response = Band.select(
|
66
|
+
Band.name,
|
67
|
+
Cast(
|
68
|
+
Band.manager.name,
|
69
|
+
as_type=Integer(),
|
70
|
+
),
|
71
|
+
).run_sync()
|
72
|
+
|
73
|
+
self.assertListEqual(
|
74
|
+
response,
|
75
|
+
[
|
76
|
+
{
|
77
|
+
"name": "Pythonistas",
|
78
|
+
"manager.name": 1111,
|
79
|
+
}
|
80
|
+
],
|
81
|
+
)
|
82
|
+
|
83
|
+
def test_nested_inner(self):
|
84
|
+
"""
|
85
|
+
Make sure ``Cast`` can be passed into other functions.
|
86
|
+
"""
|
87
|
+
Band.update({Band.name: "1111"}, force=True).run_sync()
|
88
|
+
|
89
|
+
response = Band.select(
|
90
|
+
Length(
|
91
|
+
Cast(
|
92
|
+
Band.popularity,
|
93
|
+
as_type=Varchar(),
|
94
|
+
)
|
95
|
+
)
|
96
|
+
).run_sync()
|
97
|
+
|
98
|
+
self.assertListEqual(
|
99
|
+
response,
|
100
|
+
[{"length": 4}],
|
101
|
+
)
|
102
|
+
|
103
|
+
def test_nested_outer(self):
|
104
|
+
"""
|
105
|
+
Make sure a querystring can be passed into ``Cast`` (meaning it can be
|
106
|
+
nested).
|
107
|
+
"""
|
108
|
+
response = Band.select(
|
109
|
+
Cast(
|
110
|
+
Length(Band.name),
|
111
|
+
as_type=Varchar(),
|
112
|
+
alias="length",
|
113
|
+
)
|
114
|
+
).run_sync()
|
115
|
+
|
116
|
+
self.assertListEqual(
|
117
|
+
response,
|
118
|
+
[{"length": str(len("Pythonistas"))}],
|
119
|
+
)
|
120
|
+
|
121
|
+
def test_where_clause(self):
|
122
|
+
"""
|
123
|
+
Make sure ``Cast`` works in a where clause.
|
124
|
+
"""
|
125
|
+
response = (
|
126
|
+
Band.select(Band.name, Band.popularity)
|
127
|
+
.where(Cast(Band.popularity, Varchar()) == "1000")
|
128
|
+
.run_sync()
|
129
|
+
)
|
130
|
+
|
131
|
+
self.assertListEqual(
|
132
|
+
response,
|
133
|
+
[{"name": "Pythonistas", "popularity": 1000}],
|
134
|
+
)
|