piccolo 1.7.0__py3-none-any.whl → 1.8.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 CHANGED
@@ -1 +1 @@
1
- __VERSION__ = "1.7.0"
1
+ __VERSION__ = "1.8.0"
piccolo/columns/base.py CHANGED
@@ -201,6 +201,10 @@ class ColumnMeta:
201
201
  )
202
202
  return self._table
203
203
 
204
+ @table.setter
205
+ def table(self, value: t.Type[Table]):
206
+ self._table = value
207
+
204
208
  ###########################################################################
205
209
 
206
210
  # Used by Foreign Keys:
@@ -1,8 +1,10 @@
1
1
  from .aggregate import Avg, Count, Max, Min, Sum
2
2
  from .string import Length, Lower, Ltrim, Reverse, Rtrim, Upper
3
+ from .type_conversion import Cast
3
4
 
4
5
  __all__ = (
5
6
  "Avg",
7
+ "Cast",
6
8
  "Count",
7
9
  "Length",
8
10
  "Lower",
@@ -12,17 +12,17 @@ class Avg(Function):
12
12
 
13
13
  .. code-block:: python
14
14
 
15
- await Band.select(Avg(Band.popularity)).run()
15
+ await Band.select(Avg(Band.popularity))
16
16
 
17
17
  # We can use an alias. These two are equivalent:
18
18
 
19
19
  await Band.select(
20
20
  Avg(Band.popularity, alias="popularity_avg")
21
- ).run()
21
+ )
22
22
 
23
23
  await Band.select(
24
24
  Avg(Band.popularity).as_alias("popularity_avg")
25
- ).run()
25
+ )
26
26
 
27
27
  """
28
28
 
@@ -103,17 +103,17 @@ class Min(Function):
103
103
 
104
104
  .. code-block:: python
105
105
 
106
- await Band.select(Min(Band.popularity)).run()
106
+ await Band.select(Min(Band.popularity))
107
107
 
108
108
  # We can use an alias. These two are equivalent:
109
109
 
110
110
  await Band.select(
111
111
  Min(Band.popularity, alias="popularity_min")
112
- ).run()
112
+ )
113
113
 
114
114
  await Band.select(
115
115
  Min(Band.popularity).as_alias("popularity_min")
116
- ).run()
116
+ )
117
117
 
118
118
  """
119
119
 
@@ -128,17 +128,17 @@ class Max(Function):
128
128
 
129
129
  await Band.select(
130
130
  Max(Band.popularity)
131
- ).run()
131
+ )
132
132
 
133
133
  # We can use an alias. These two are equivalent:
134
134
 
135
135
  await Band.select(
136
136
  Max(Band.popularity, alias="popularity_max")
137
- ).run()
137
+ )
138
138
 
139
139
  await Band.select(
140
140
  Max(Band.popularity).as_alias("popularity_max")
141
- ).run()
141
+ )
142
142
 
143
143
  """
144
144
 
@@ -153,17 +153,17 @@ class Sum(Function):
153
153
 
154
154
  await Band.select(
155
155
  Sum(Band.popularity)
156
- ).run()
156
+ )
157
157
 
158
158
  # We can use an alias. These two are equivalent:
159
159
 
160
160
  await Band.select(
161
161
  Sum(Band.popularity, alias="popularity_sum")
162
- ).run()
162
+ )
163
163
 
164
164
  await Band.select(
165
165
  Sum(Band.popularity).as_alias("popularity_sum")
166
- ).run()
166
+ )
167
167
 
168
168
  """
169
169
 
@@ -0,0 +1,82 @@
1
+ import typing as t
2
+
3
+ from piccolo.columns.base import Column
4
+ from piccolo.querystring import QueryString
5
+
6
+
7
+ class Cast(QueryString):
8
+ def __init__(
9
+ self,
10
+ identifier: t.Union[Column, QueryString],
11
+ as_type: Column,
12
+ alias: t.Optional[str] = None,
13
+ ):
14
+ """
15
+ Cast a value to a different type. For example::
16
+
17
+ >>> from piccolo.query.functions import Cast
18
+
19
+ >>> await Concert.select(
20
+ ... Cast(Concert.starts, Time(), "start_time")
21
+ ... )
22
+ [{"start_time": datetime.time(19, 0)}]
23
+
24
+ :param identifier:
25
+ Identifies what is being converted (e.g. a column).
26
+ :param as_type:
27
+ The type to be converted to.
28
+
29
+ """
30
+ # Make sure the identifier is a supported type.
31
+
32
+ if not isinstance(identifier, (Column, QueryString)):
33
+ raise ValueError(
34
+ "The identifier is an unsupported type - only Column and "
35
+ "QueryString instances are allowed."
36
+ )
37
+
38
+ #######################################################################
39
+ # Convert `as_type` to a string which can be used in the query.
40
+
41
+ if not isinstance(as_type, Column):
42
+ raise ValueError("The `as_type` value must be a Column instance.")
43
+
44
+ # We need to give the column a reference to a table, and hence
45
+ # the database engine, as the column type is sometimes dependent
46
+ # on which database is being used.
47
+ from piccolo.table import Table, create_table_class
48
+
49
+ table: t.Optional[t.Type[Table]] = None
50
+
51
+ if isinstance(identifier, Column):
52
+ table = identifier._meta.table
53
+ elif isinstance(identifier, QueryString):
54
+ table = (
55
+ identifier.columns[0]._meta.table
56
+ if identifier.columns
57
+ else None
58
+ )
59
+
60
+ as_type._meta.table = table or create_table_class("Table")
61
+ as_type_string = as_type.column_type
62
+
63
+ #######################################################################
64
+ # Preserve the original alias from the column.
65
+
66
+ if isinstance(identifier, Column):
67
+ alias = (
68
+ alias
69
+ or identifier._alias
70
+ or identifier._meta.get_default_alias()
71
+ )
72
+
73
+ #######################################################################
74
+
75
+ super().__init__(
76
+ f"CAST({{}} AS {as_type_string})",
77
+ identifier,
78
+ alias=alias,
79
+ )
80
+
81
+
82
+ __all__ = ("Cast",)
piccolo/querystring.py CHANGED
@@ -270,6 +270,18 @@ class QueryString(Selectable):
270
270
  def __sub__(self, value) -> QueryString:
271
271
  return QueryString("{} - {}", self, value)
272
272
 
273
+ def __gt__(self, value) -> QueryString:
274
+ return QueryString("{} > {}", self, value)
275
+
276
+ def __ge__(self, value) -> QueryString:
277
+ return QueryString("{} >= {}", self, value)
278
+
279
+ def __lt__(self, value) -> QueryString:
280
+ return QueryString("{} < {}", self, value)
281
+
282
+ def __le__(self, value) -> QueryString:
283
+ return QueryString("{} <= {}", self, value)
284
+
273
285
  def is_in(self, value) -> QueryString:
274
286
  return QueryString("{} IN {}", self, value)
275
287
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: piccolo
3
- Version: 1.7.0
3
+ Version: 1.8.0
4
4
  Summary: A fast, user friendly ORM and query builder which supports asyncio.
5
5
  Home-page: https://github.com/piccolo-orm/piccolo
6
6
  Author: Daniel Townsend
@@ -1,8 +1,8 @@
1
- piccolo/__init__.py,sha256=h4xA2N06XGCcrqnSQbI2FfqW4dGycKVDmFXCAklesxA,22
1
+ piccolo/__init__.py,sha256=mRuIID3n4xkvLnANZAYlJEC5QgpM7rOXi2uxp1_jzHg,22
2
2
  piccolo/custom_types.py,sha256=7HMQAze-5mieNLfbQ5QgbRQgR2abR7ol0qehv2SqROY,604
3
3
  piccolo/main.py,sha256=1VsFV67FWTUikPTysp64Fmgd9QBVa_9wcwKfwj2UCEA,5117
4
4
  piccolo/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- piccolo/querystring.py,sha256=6uxfoCk7sj6bs_mDNV8W4ScgdG-h5wl1Y9HMlVW2abM,8671
5
+ piccolo/querystring.py,sha256=Mn00hb4HGOe9MIR7WOhJ3qO1uNex21zj0m2heOeDvZk,9057
6
6
  piccolo/schema.py,sha256=aWPuZxEulgBRD5NTqKN-RAZchxu-PoIrn0iFrWGZuq4,7731
7
7
  piccolo/table.py,sha256=DJT8jTgirPpzkydjSzaCgcG0DiC75XRtW_xtFqTyg80,49457
8
8
  piccolo/table_reflection.py,sha256=jrN1nHerDJ4tU09GtNN3hz7ap-7rXnSUjljFO6LB2H0,7094
@@ -115,7 +115,7 @@ piccolo/apps/user/piccolo_migrations/2020-06-11T21-38-55.py,sha256=JG_LFPrEljnSE
115
115
  piccolo/apps/user/piccolo_migrations/2021-04-30T16-14-15.py,sha256=Y_Dj4ROSxjnPsRDqcnpWeyk8UpF8c80T08_O2uq-GoA,1219
116
116
  piccolo/apps/user/piccolo_migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
117
117
  piccolo/columns/__init__.py,sha256=OYhO_n9anMiU9nL-K6ATq9FhAtm8RyMpqYQ7fTVbhxI,1120
118
- piccolo/columns/base.py,sha256=XUhhx-wNc6nBPd39VIYuNfFERTaFzow9SHGfZjJ2YC0,31288
118
+ piccolo/columns/base.py,sha256=FuMLSplFuNoK919nkas2Fn4kZjmPLMmutc4cRtmLhyY,31378
119
119
  piccolo/columns/choices.py,sha256=-HNQuk9vMmVZIPZ5PMeXGTfr23o4nzKPSAkvcG1k0y8,723
120
120
  piccolo/columns/column_types.py,sha256=CzbNnP_VWvz6_r4aaRcMHiHZOaWHeq5IGaN8WJ7JGPA,81685
121
121
  piccolo/columns/combination.py,sha256=vMXC2dfY7pvnCFhsT71XFVyb4gdQzfRsCMaiduu04Ss,6900
@@ -149,10 +149,11 @@ piccolo/query/__init__.py,sha256=bcsMV4813rMRAIqGv4DxI4eyO4FmpXkDv9dfTk5pt3A,699
149
149
  piccolo/query/base.py,sha256=G8Mwz0GcHY4Xs5Co9ubCNMI-3orfOsDdRDOnFRws7TU,15212
150
150
  piccolo/query/mixins.py,sha256=1RyhORDRwTZF9m_2uEgc6sOSd2uViXivBAaFN8geq5g,21982
151
151
  piccolo/query/proxy.py,sha256=Yq4jNc7IWJvdeO3u7_7iPyRy2WhVj8KsIUcIYHBIi9Q,1839
152
- piccolo/query/functions/__init__.py,sha256=O_uuMZbwMVAe-ebr-COdc9QZtvUSQFomPa29me6cscs,266
153
- piccolo/query/functions/aggregate.py,sha256=qSDb-2Of9FYXUKsdCsvaoPjGOefyhoxawWpA5oG3fQQ,4320
152
+ piccolo/query/functions/__init__.py,sha256=9ikQo6qPkCBaWSiuimEACWbYRk9KHoLboRsEC1VcSVw,312
153
+ piccolo/query/functions/aggregate.py,sha256=OdjDjr_zyD4S9UbrZ2C3V5mz4OT2sIfAFAdTGr4WL54,4248
154
154
  piccolo/query/functions/base.py,sha256=Go2bg2r7GaVoyyX-wTb80WEQmtiU4OFYWQlq9eQ6Zcc,478
155
155
  piccolo/query/functions/string.py,sha256=srxsQJFS6L4gPvFjvuAFQj7QtnCF7X6YoJNKARR2XP0,1236
156
+ piccolo/query/functions/type_conversion.py,sha256=OYbZc6TEk6b5yTwCMw2rmZ-UiQiUiWZOyxwMLzUjXwE,2583
156
157
  piccolo/query/methods/__init__.py,sha256=tm4gLeV_obDqpgnouVjFbGubbaoJcqm_cbNd4LPo48Q,622
157
158
  piccolo/query/methods/alter.py,sha256=AI9YkJeip2EitrWJN_TDExXhA8HGAG3XuDz1NR-KirQ,16728
158
159
  piccolo/query/methods/count.py,sha256=Vxn_7Ry-rleC6OGRxh-cLbuEMsy1DNjAZJThGED-_do,1748
@@ -208,12 +209,12 @@ tests/apps/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
208
209
  tests/apps/migrations/test_migration.py,sha256=JmPLtf2BCWX3Yofe0GQe40m8I_yWa_-3vk1lDfFDfIo,308
209
210
  tests/apps/migrations/auto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
210
211
  tests/apps/migrations/auto/test_diffable_table.py,sha256=bok3G9pwEYnE3AL6UG4iEHrVBZJQ_ovYCdKC3we5JVQ,2932
211
- tests/apps/migrations/auto/test_migration_manager.py,sha256=XXdHHiimsyeNN6sILGQxN5RDLdR9MH_NlTC0PumLu3c,34741
212
+ tests/apps/migrations/auto/test_migration_manager.py,sha256=NTNx4y5B0bMVLUR9BybX3zS4jxFI3_weLej8zOn3BkI,34798
212
213
  tests/apps/migrations/auto/test_schema_differ.py,sha256=UdsaZisA02j15wr1bXkXD6Cqu3p0A23NwFQLXsJdQL4,19391
213
214
  tests/apps/migrations/auto/test_schema_snapshot.py,sha256=ZyvGZqn3N3cwd-3S-FME5AJ8buDSHesw7yPIvY6mE5k,6196
214
215
  tests/apps/migrations/auto/test_serialisation.py,sha256=EFkhES1w9h51UCamWrhxs3mf4I718ggeP7Yl5J_UID4,13548
215
216
  tests/apps/migrations/auto/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
216
- tests/apps/migrations/auto/integration/test_migrations.py,sha256=G3iqDlNCC6S3N9pm7w0bf5YelDWDi1vz7OE0A2IEokk,46131
217
+ tests/apps/migrations/auto/integration/test_migrations.py,sha256=7rmATPGZNuchabUb2y5C9QMmv6XFChn5EHlYoRVChd4,46744
217
218
  tests/apps/migrations/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
218
219
  tests/apps/migrations/commands/test_base.py,sha256=NgHgVjNd3Hil9eODvW7Ic2D9muTa_grNaH3YpRFfR8I,1829
219
220
  tests/apps/migrations/commands/test_check.py,sha256=hOX_sVk1nfCRfbQ8tJoFEUBFhih9O4QuQLHTp5TQaiY,630
@@ -295,7 +296,7 @@ tests/query/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
295
296
  tests/query/test_await.py,sha256=imGazmG0l4qilveNPwsxvYQogFJtos4YB8N9iggPEFU,412
296
297
  tests/query/test_camelcase.py,sha256=AcL2gZera1GfpVJNpuKuh5ZBosNCY_ezPWh6-duU5vU,1765
297
298
  tests/query/test_freeze.py,sha256=p3iXqHzgV39YWlqzXtZvaDa7iKZaaaelOGX3UZ8CMf0,3887
298
- tests/query/test_functions.py,sha256=_dYGLqsrYkWMxjb3MIlpsCbY1nC9n39IiRsrGhhrYJs,3182
299
+ tests/query/test_functions.py,sha256=B_M-giOf1xGvdCaYgJdKWLSoV8vtTiRQtEyvL4-7eCY,6401
299
300
  tests/query/test_gather.py,sha256=okWANrBoh0Ut1RomWoffiWNpFqiITF6qti-Aa3uYtRk,730
300
301
  tests/query/test_querystring.py,sha256=hHljfdnOTlwIMs-7Q2yP5YekYXTT2It-Q-3mP6T9e58,880
301
302
  tests/query/test_slots.py,sha256=I9ZjAYqAJNSFAWg9UyAqy7bm-Z52KiyQ2C_yHk2qqqI,1010
@@ -355,9 +356,9 @@ tests/utils/test_sql_values.py,sha256=vzxRmy16FfLZPH-sAQexBvsF9MXB8n4smr14qoEOS5
355
356
  tests/utils/test_sync.py,sha256=9ytVo56y2vPQePvTeIi9lHIouEhWJbodl1TmzkGFrSo,799
356
357
  tests/utils/test_table_reflection.py,sha256=SIzuat-IpcVj1GCFyOWKShI8YkhdOPPFH7qVrvfyPNE,3794
357
358
  tests/utils/test_warnings.py,sha256=NvSC_cvJ6uZcwAGf1m-hLzETXCqprXELL8zg3TNLVMw,269
358
- piccolo-1.7.0.dist-info/LICENSE,sha256=zFIpi-16uIJ420UMIG75NU0JbDBykvrdnXcj5U_EYBI,1059
359
- piccolo-1.7.0.dist-info/METADATA,sha256=AIBs_jqCxL694qW6TwjwE0C4_LF_RqzaVCZ_-6Ag6po,5177
360
- piccolo-1.7.0.dist-info/WHEEL,sha256=00yskusixUoUt5ob_CiUp6LsnN5lqzTJpoqOFg_FVIc,92
361
- piccolo-1.7.0.dist-info/entry_points.txt,sha256=SJPHET4Fi1bN5F3WqcKkv9SClK3_F1I7m4eQjk6AFh0,46
362
- piccolo-1.7.0.dist-info/top_level.txt,sha256=-SR74VGbk43VoPy1HH-mHm97yoGukLK87HE5kdBW6qM,24
363
- piccolo-1.7.0.dist-info/RECORD,,
359
+ piccolo-1.8.0.dist-info/LICENSE,sha256=zFIpi-16uIJ420UMIG75NU0JbDBykvrdnXcj5U_EYBI,1059
360
+ piccolo-1.8.0.dist-info/METADATA,sha256=Uoe1LLvND5fOBdQKOSgFI1T047qzIlbICmwXV1zg7e4,5177
361
+ piccolo-1.8.0.dist-info/WHEEL,sha256=00yskusixUoUt5ob_CiUp6LsnN5lqzTJpoqOFg_FVIc,92
362
+ piccolo-1.8.0.dist-info/entry_points.txt,sha256=SJPHET4Fi1bN5F3WqcKkv9SClK3_F1I7m4eQjk6AFh0,46
363
+ piccolo-1.8.0.dist-info/top_level.txt,sha256=-SR74VGbk43VoPy1HH-mHm97yoGukLK87HE5kdBW6qM,24
364
+ piccolo-1.8.0.dist-info/RECORD,,
@@ -288,7 +288,12 @@ class TestMigrations(MigrationTestCase):
288
288
  [
289
289
  x.data_type == "text",
290
290
  x.is_nullable == "NO",
291
- x.column_default in ("''::text", "'':::STRING"),
291
+ x.column_default
292
+ in (
293
+ "''",
294
+ "''::text",
295
+ "'':::STRING",
296
+ ),
292
297
  ]
293
298
  ),
294
299
  )
@@ -461,6 +466,7 @@ class TestMigrations(MigrationTestCase):
461
466
  in (
462
467
  "now()",
463
468
  "CURRENT_TIMESTAMP",
469
+ "current_timestamp()::TIMESTAMP",
464
470
  "current_timestamp():::TIMESTAMPTZ::TIMESTAMP",
465
471
  ),
466
472
  ]
@@ -541,7 +547,11 @@ class TestMigrations(MigrationTestCase):
541
547
  x.data_type == "interval",
542
548
  x.is_nullable == "NO",
543
549
  x.column_default
544
- in ("'00:00:00'::interval", "'00:00:00':::INTERVAL"),
550
+ in (
551
+ "'00:00:00'",
552
+ "'00:00:00'::interval",
553
+ "'00:00:00':::INTERVAL",
554
+ ),
545
555
  ]
546
556
  ),
547
557
  )
@@ -743,7 +753,12 @@ class TestMigrations(MigrationTestCase):
743
753
  [
744
754
  x.data_type == "jsonb",
745
755
  x.is_nullable == "NO",
746
- x.column_default in ("'{}'::jsonb", "'{}':::JSONB"),
756
+ x.column_default
757
+ in (
758
+ "'{}'",
759
+ "'{}'::jsonb",
760
+ "'{}':::JSONB",
761
+ ),
747
762
  ]
748
763
  ),
749
764
  )
@@ -766,7 +781,11 @@ class TestMigrations(MigrationTestCase):
766
781
  x.data_type == "character varying",
767
782
  x.is_nullable == "NO",
768
783
  x.column_default
769
- in ("''::character varying", "'':::STRING"),
784
+ in (
785
+ "''",
786
+ "''::character varying",
787
+ "'':::STRING",
788
+ ),
770
789
  ]
771
790
  ),
772
791
  )
@@ -788,7 +807,11 @@ class TestMigrations(MigrationTestCase):
788
807
  x.data_type == "character varying",
789
808
  x.is_nullable == "NO",
790
809
  x.column_default
791
- in ("''::character varying", "'':::STRING"),
810
+ in (
811
+ "''",
812
+ "''::character varying",
813
+ "'':::STRING",
814
+ ),
792
815
  ]
793
816
  ),
794
817
  )
@@ -768,15 +768,15 @@ class TestMigrationManager(DBTestCase):
768
768
  )
769
769
 
770
770
  asyncio.run(manager.run())
771
- self.assertEqual(
772
- self._get_column_default(),
773
- [{"column_default": "'Unknown':::STRING"}],
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.assertEqual(
778
- self._get_column_default(),
779
- [{"column_default": "'':::STRING"}],
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.assertEqual(
860
- self._get_column_default(),
861
- [{"column_default": "'Mr Manager':::STRING"}],
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.assertEqual(
883
- self._get_column_default(),
884
- [{"column_default": "'Mr Manager':::STRING"}],
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.assertEqual(
896
- self._get_column_default(),
897
- [{"column_default": "'Mr Manager':::STRING"}],
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))
@@ -1,6 +1,7 @@
1
1
  from unittest import TestCase
2
2
 
3
- from piccolo.query.functions.string import Reverse, Upper
3
+ from piccolo.columns import Integer, Text, Varchar
4
+ from piccolo.query.functions import Cast, Length, Reverse, Upper
4
5
  from piccolo.querystring import QueryString
5
6
  from piccolo.table import create_db_tables_sync, drop_db_tables_sync
6
7
  from tests.base import engines_skip
@@ -16,7 +17,13 @@ class FunctionTest(TestCase):
16
17
  manager = Manager({Manager.name: "Guido"})
17
18
  manager.save().run_sync()
18
19
 
19
- band = Band({Band.name: "Pythonistas", Band.manager: manager})
20
+ band = Band(
21
+ {
22
+ Band.name: "Pythonistas",
23
+ Band.manager: manager,
24
+ Band.popularity: 1000,
25
+ }
26
+ )
20
27
  band.save().run_sync()
21
28
 
22
29
  def tearDown(self) -> None:
@@ -100,3 +107,132 @@ class TestWhereClause(FunctionTest):
100
107
  .run_sync()
101
108
  )
102
109
  self.assertListEqual(response, [{"name": "Pythonistas"}])
110
+
111
+
112
+ class TestCast(FunctionTest):
113
+ def test_varchar(self):
114
+ """
115
+ Make sure that casting to ``Varchar`` works.
116
+ """
117
+ response = Band.select(
118
+ Cast(
119
+ Band.popularity,
120
+ as_type=Varchar(),
121
+ )
122
+ ).run_sync()
123
+
124
+ self.assertListEqual(
125
+ response,
126
+ [{"popularity": "1000"}],
127
+ )
128
+
129
+ def test_text(self):
130
+ """
131
+ Make sure that casting to ``Text`` works.
132
+ """
133
+ response = Band.select(
134
+ Cast(
135
+ Band.popularity,
136
+ as_type=Text(),
137
+ )
138
+ ).run_sync()
139
+
140
+ self.assertListEqual(
141
+ response,
142
+ [{"popularity": "1000"}],
143
+ )
144
+
145
+ def test_integer(self):
146
+ """
147
+ Make sure that casting to ``Integer`` works.
148
+ """
149
+ Band.update({Band.name: "1111"}, force=True).run_sync()
150
+
151
+ response = Band.select(
152
+ Cast(
153
+ Band.name,
154
+ as_type=Integer(),
155
+ )
156
+ ).run_sync()
157
+
158
+ self.assertListEqual(
159
+ response,
160
+ [{"name": 1111}],
161
+ )
162
+
163
+ def test_join(self):
164
+ """
165
+ Make sure that casting works with joins.
166
+ """
167
+ Manager.update({Manager.name: "1111"}, force=True).run_sync()
168
+
169
+ response = Band.select(
170
+ Band.name,
171
+ Cast(
172
+ Band.manager.name,
173
+ as_type=Integer(),
174
+ ),
175
+ ).run_sync()
176
+
177
+ self.assertListEqual(
178
+ response,
179
+ [
180
+ {
181
+ "name": "Pythonistas",
182
+ "manager.name": 1111,
183
+ }
184
+ ],
185
+ )
186
+
187
+ def test_nested_inner(self):
188
+ """
189
+ Make sure ``Cast`` can be passed into other functions.
190
+ """
191
+ Band.update({Band.name: "1111"}, force=True).run_sync()
192
+
193
+ response = Band.select(
194
+ Length(
195
+ Cast(
196
+ Band.popularity,
197
+ as_type=Varchar(),
198
+ )
199
+ )
200
+ ).run_sync()
201
+
202
+ self.assertListEqual(
203
+ response,
204
+ [{"length": 4}],
205
+ )
206
+
207
+ def test_nested_outer(self):
208
+ """
209
+ Make sure a querystring can be passed into ``Cast`` (meaning it can be
210
+ nested).
211
+ """
212
+ response = Band.select(
213
+ Cast(
214
+ Length(Band.name),
215
+ as_type=Varchar(),
216
+ alias="length",
217
+ )
218
+ ).run_sync()
219
+
220
+ self.assertListEqual(
221
+ response,
222
+ [{"length": str(len("Pythonistas"))}],
223
+ )
224
+
225
+ def test_where_clause(self):
226
+ """
227
+ Make sure ``Cast`` works in a where clause.
228
+ """
229
+ response = (
230
+ Band.select(Band.name, Band.popularity)
231
+ .where(Cast(Band.popularity, Varchar()) == "1000")
232
+ .run_sync()
233
+ )
234
+
235
+ self.assertListEqual(
236
+ response,
237
+ [{"name": "Pythonistas", "popularity": 1000}],
238
+ )