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.
Files changed (42) hide show
  1. piccolo/__init__.py +1 -1
  2. piccolo/apps/asgi/commands/templates/app/_fastapi_app.py.jinja +35 -30
  3. piccolo/apps/asgi/commands/templates/app/_starlette_app.py.jinja +29 -21
  4. piccolo/apps/migrations/auto/migration_manager.py +1 -0
  5. piccolo/apps/migrations/commands/forwards.py +8 -7
  6. piccolo/apps/playground/commands/run.py +11 -0
  7. piccolo/columns/column_types.py +83 -35
  8. piccolo/query/functions/__init__.py +11 -1
  9. piccolo/query/functions/datetime.py +260 -0
  10. piccolo/query/functions/string.py +45 -0
  11. {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/METADATA +15 -15
  12. {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/RECORD +42 -40
  13. {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/WHEEL +1 -1
  14. tests/apps/migrations/commands/test_forwards_backwards.py +32 -1
  15. tests/columns/test_array.py +3 -7
  16. tests/columns/test_bigint.py +3 -9
  17. tests/columns/test_boolean.py +3 -7
  18. tests/columns/test_bytea.py +5 -14
  19. tests/columns/test_choices.py +5 -14
  20. tests/columns/test_date.py +5 -13
  21. tests/columns/test_double_precision.py +3 -8
  22. tests/columns/test_interval.py +5 -13
  23. tests/columns/test_json.py +9 -26
  24. tests/columns/test_jsonb.py +3 -11
  25. tests/columns/test_numeric.py +3 -7
  26. tests/columns/test_primary_key.py +11 -33
  27. tests/columns/test_readable.py +5 -7
  28. tests/columns/test_real.py +3 -8
  29. tests/columns/test_reserved_column_names.py +3 -8
  30. tests/columns/test_smallint.py +3 -8
  31. tests/columns/test_time.py +5 -14
  32. tests/columns/test_timestamp.py +5 -13
  33. tests/columns/test_timestamptz.py +5 -13
  34. tests/columns/test_uuid.py +3 -7
  35. tests/columns/test_varchar.py +3 -9
  36. tests/query/functions/base.py +2 -15
  37. tests/query/functions/test_datetime.py +112 -0
  38. tests/query/functions/test_math.py +2 -3
  39. tests/query/functions/test_string.py +34 -2
  40. {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/LICENSE +0 -0
  41. {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/entry_points.txt +0 -0
  42. {piccolo-1.10.0.dist-info → piccolo-1.12.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,260 @@
1
+ import typing as t
2
+
3
+ from piccolo.columns.base import Column
4
+ from piccolo.columns.column_types import (
5
+ Date,
6
+ Integer,
7
+ Time,
8
+ Timestamp,
9
+ Timestamptz,
10
+ )
11
+ from piccolo.querystring import QueryString
12
+
13
+ from .type_conversion import Cast
14
+
15
+ ###############################################################################
16
+ # Postgres / Cockroach
17
+
18
+ ExtractComponent = t.Literal[
19
+ "century",
20
+ "day",
21
+ "decade",
22
+ "dow",
23
+ "doy",
24
+ "epoch",
25
+ "hour",
26
+ "isodow",
27
+ "isoyear",
28
+ "julian",
29
+ "microseconds",
30
+ "millennium",
31
+ "milliseconds",
32
+ "minute",
33
+ "month",
34
+ "quarter",
35
+ "second",
36
+ "timezone",
37
+ "timezone_hour",
38
+ "timezone_minute",
39
+ "week",
40
+ "year",
41
+ ]
42
+
43
+
44
+ class Extract(QueryString):
45
+ def __init__(
46
+ self,
47
+ identifier: t.Union[Date, Time, Timestamp, Timestamptz, QueryString],
48
+ datetime_component: ExtractComponent,
49
+ alias: t.Optional[str] = None,
50
+ ):
51
+ """
52
+ .. note:: This is for Postgres / Cockroach only.
53
+
54
+ Extract a date or time component from a ``Date`` / ``Time`` /
55
+ ``Timestamp`` / ``Timestamptz`` column. For example, getting the month
56
+ from a timestamp:
57
+
58
+ .. code-block:: python
59
+
60
+ >>> from piccolo.query.functions import Extract
61
+ >>> await Concert.select(
62
+ ... Extract(Concert.starts, "month", alias="start_month")
63
+ ... )
64
+ [{"start_month": 12}]
65
+
66
+ :param identifier:
67
+ Identifies the column.
68
+ :param datetime_component:
69
+ The date or time component to extract from the column.
70
+
71
+ """
72
+ if datetime_component.lower() not in t.get_args(ExtractComponent):
73
+ raise ValueError("The date time component isn't recognised.")
74
+
75
+ super().__init__(
76
+ f"EXTRACT({datetime_component} FROM {{}})",
77
+ identifier,
78
+ alias=alias,
79
+ )
80
+
81
+
82
+ ###############################################################################
83
+ # SQLite
84
+
85
+
86
+ class Strftime(QueryString):
87
+ def __init__(
88
+ self,
89
+ identifier: t.Union[Date, Time, Timestamp, Timestamptz, QueryString],
90
+ datetime_format: str,
91
+ alias: t.Optional[str] = None,
92
+ ):
93
+ """
94
+ .. note:: This is for SQLite only.
95
+
96
+ Format a datetime value. For example:
97
+
98
+ .. code-block:: python
99
+
100
+ >>> from piccolo.query.functions import Strftime
101
+ >>> await Concert.select(
102
+ ... Strftime(Concert.starts, "%Y", alias="start_year")
103
+ ... )
104
+ [{"start_month": "2024"}]
105
+
106
+ :param identifier:
107
+ Identifies the column.
108
+ :param datetime_format:
109
+ A string describing the output format (see SQLite's
110
+ `documentation <https://www.sqlite.org/lang_datefunc.html>`_
111
+ for more info).
112
+
113
+ """
114
+ super().__init__(
115
+ f"strftime('{datetime_format}', {{}})",
116
+ identifier,
117
+ alias=alias,
118
+ )
119
+
120
+
121
+ ###############################################################################
122
+ # Database agnostic
123
+
124
+
125
+ def _get_engine_type(identifier: t.Union[Column, QueryString]) -> str:
126
+ if isinstance(identifier, Column):
127
+ return identifier._meta.engine_type
128
+ elif isinstance(identifier, QueryString) and (
129
+ columns := identifier.columns
130
+ ):
131
+ return columns[0]._meta.engine_type
132
+ else:
133
+ raise ValueError("Unable to determine the engine type")
134
+
135
+
136
+ def _extract_component(
137
+ identifier: t.Union[Date, Time, Timestamp, Timestamptz, QueryString],
138
+ sqlite_format: str,
139
+ postgres_format: ExtractComponent,
140
+ alias: t.Optional[str],
141
+ ) -> QueryString:
142
+ engine_type = _get_engine_type(identifier=identifier)
143
+
144
+ return Cast(
145
+ (
146
+ Strftime(
147
+ identifier=identifier,
148
+ datetime_format=sqlite_format,
149
+ )
150
+ if engine_type == "sqlite"
151
+ else Extract(
152
+ identifier=identifier,
153
+ datetime_component=postgres_format,
154
+ )
155
+ ),
156
+ Integer(),
157
+ alias=alias,
158
+ )
159
+
160
+
161
+ def Year(
162
+ identifier: t.Union[Date, Timestamp, Timestamptz, QueryString],
163
+ alias: t.Optional[str] = None,
164
+ ) -> QueryString:
165
+ """
166
+ Extract the year as an integer.
167
+ """
168
+ return _extract_component(
169
+ identifier=identifier,
170
+ sqlite_format="%Y",
171
+ postgres_format="year",
172
+ alias=alias,
173
+ )
174
+
175
+
176
+ def Month(
177
+ identifier: t.Union[Date, Timestamp, Timestamptz, QueryString],
178
+ alias: t.Optional[str] = None,
179
+ ) -> QueryString:
180
+ """
181
+ Extract the month as an integer.
182
+ """
183
+ return _extract_component(
184
+ identifier=identifier,
185
+ sqlite_format="%m",
186
+ postgres_format="month",
187
+ alias=alias,
188
+ )
189
+
190
+
191
+ def Day(
192
+ identifier: t.Union[Date, Timestamp, Timestamptz, QueryString],
193
+ alias: t.Optional[str] = None,
194
+ ) -> QueryString:
195
+ """
196
+ Extract the day as an integer.
197
+ """
198
+ return _extract_component(
199
+ identifier=identifier,
200
+ sqlite_format="%d",
201
+ postgres_format="day",
202
+ alias=alias,
203
+ )
204
+
205
+
206
+ def Hour(
207
+ identifier: t.Union[Time, Timestamp, Timestamptz, QueryString],
208
+ alias: t.Optional[str] = None,
209
+ ) -> QueryString:
210
+ """
211
+ Extract the hour as an integer.
212
+ """
213
+ return _extract_component(
214
+ identifier=identifier,
215
+ sqlite_format="%H",
216
+ postgres_format="hour",
217
+ alias=alias,
218
+ )
219
+
220
+
221
+ def Minute(
222
+ identifier: t.Union[Time, Timestamp, Timestamptz, QueryString],
223
+ alias: t.Optional[str] = None,
224
+ ) -> QueryString:
225
+ """
226
+ Extract the minute as an integer.
227
+ """
228
+ return _extract_component(
229
+ identifier=identifier,
230
+ sqlite_format="%M",
231
+ postgres_format="minute",
232
+ alias=alias,
233
+ )
234
+
235
+
236
+ def Second(
237
+ identifier: t.Union[Time, Timestamp, Timestamptz, QueryString],
238
+ alias: t.Optional[str] = None,
239
+ ) -> QueryString:
240
+ """
241
+ Extract the second as an integer.
242
+ """
243
+ return _extract_component(
244
+ identifier=identifier,
245
+ sqlite_format="%S",
246
+ postgres_format="second",
247
+ alias=alias,
248
+ )
249
+
250
+
251
+ __all__ = (
252
+ "Extract",
253
+ "Strftime",
254
+ "Year",
255
+ "Month",
256
+ "Day",
257
+ "Hour",
258
+ "Minute",
259
+ "Second",
260
+ )
@@ -5,6 +5,12 @@ https://www.postgresql.org/docs/current/functions-string.html
5
5
 
6
6
  """
7
7
 
8
+ import typing as t
9
+
10
+ from piccolo.columns.base import Column
11
+ from piccolo.columns.column_types import Text, Varchar
12
+ from piccolo.querystring import QueryString
13
+
8
14
  from .base import Function
9
15
 
10
16
 
@@ -63,6 +69,44 @@ class Upper(Function):
63
69
  function_name = "UPPER"
64
70
 
65
71
 
72
+ class Concat(QueryString):
73
+ def __init__(
74
+ self,
75
+ *args: t.Union[Column, QueryString, str],
76
+ alias: t.Optional[str] = None,
77
+ ):
78
+ """
79
+ Concatenate multiple values into a single string.
80
+
81
+ .. note::
82
+ Null values are ignored, so ``null + '!!!'`` returns ``!!!``,
83
+ not ``null``.
84
+
85
+ .. warning::
86
+ For SQLite, this is only available in version 3.44.0 and above.
87
+
88
+ """
89
+ if len(args) < 2:
90
+ raise ValueError("At least two values must be passed in.")
91
+
92
+ placeholders = ", ".join("{}" for _ in args)
93
+
94
+ processed_args: t.List[t.Union[QueryString, Column]] = []
95
+
96
+ for arg in args:
97
+ if isinstance(arg, str) or (
98
+ isinstance(arg, Column)
99
+ and not isinstance(arg, (Varchar, Text))
100
+ ):
101
+ processed_args.append(QueryString("CAST({} AS TEXT)", arg))
102
+ else:
103
+ processed_args.append(arg)
104
+
105
+ super().__init__(
106
+ f"CONCAT({placeholders})", *processed_args, alias=alias
107
+ )
108
+
109
+
66
110
  __all__ = (
67
111
  "Length",
68
112
  "Lower",
@@ -70,4 +114,5 @@ __all__ = (
70
114
  "Reverse",
71
115
  "Rtrim",
72
116
  "Upper",
117
+ "Concat",
73
118
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: piccolo
3
- Version: 1.10.0
3
+ Version: 1.12.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
@@ -25,28 +25,28 @@ Requires-Python: >=3.8.0
25
25
  Description-Content-Type: text/markdown
26
26
  License-File: LICENSE
27
27
  Requires-Dist: black
28
- Requires-Dist: colorama (>=0.4.0)
29
- Requires-Dist: Jinja2 (>=2.11.0)
30
- Requires-Dist: targ (>=0.3.7)
31
- Requires-Dist: inflection (>=0.5.1)
32
- Requires-Dist: typing-extensions (>=4.3.0)
33
- Requires-Dist: pydantic[email] (==2.*)
28
+ Requires-Dist: colorama >=0.4.0
29
+ Requires-Dist: Jinja2 >=2.11.0
30
+ Requires-Dist: targ >=0.3.7
31
+ Requires-Dist: inflection >=0.5.1
32
+ Requires-Dist: typing-extensions >=4.3.0
33
+ Requires-Dist: pydantic[email] ==2.*
34
34
  Provides-Extra: all
35
- Requires-Dist: orjson (>=3.5.1) ; extra == 'all'
35
+ Requires-Dist: orjson >=3.5.1 ; extra == 'all'
36
36
  Requires-Dist: ipython ; extra == 'all'
37
- Requires-Dist: asyncpg (>=0.21.0) ; extra == 'all'
38
- Requires-Dist: aiosqlite (>=0.16.0) ; extra == 'all'
39
- Requires-Dist: uvloop (>=0.12.0) ; (sys_platform != "win32") and extra == 'all'
37
+ Requires-Dist: asyncpg >=0.21.0 ; extra == 'all'
38
+ Requires-Dist: aiosqlite >=0.16.0 ; extra == 'all'
39
+ Requires-Dist: uvloop >=0.12.0 ; (sys_platform != "win32") and extra == 'all'
40
40
  Provides-Extra: orjson
41
- Requires-Dist: orjson (>=3.5.1) ; extra == 'orjson'
41
+ Requires-Dist: orjson >=3.5.1 ; extra == 'orjson'
42
42
  Provides-Extra: playground
43
43
  Requires-Dist: ipython ; extra == 'playground'
44
44
  Provides-Extra: postgres
45
- Requires-Dist: asyncpg (>=0.21.0) ; extra == 'postgres'
45
+ Requires-Dist: asyncpg >=0.21.0 ; extra == 'postgres'
46
46
  Provides-Extra: sqlite
47
- Requires-Dist: aiosqlite (>=0.16.0) ; extra == 'sqlite'
47
+ Requires-Dist: aiosqlite >=0.16.0 ; extra == 'sqlite'
48
48
  Provides-Extra: uvloop
49
- Requires-Dist: uvloop (>=0.12.0) ; (sys_platform != "win32") and extra == 'uvloop'
49
+ Requires-Dist: uvloop >=0.12.0 ; (sys_platform != "win32") and extra == 'uvloop'
50
50
 
51
51
  ![Logo](https://raw.githubusercontent.com/piccolo-orm/piccolo/master/docs/logo_hero.png "Piccolo Logo")
52
52
 
@@ -1,4 +1,4 @@
1
- piccolo/__init__.py,sha256=PUFn6Nk_mmFhCKTk02g04j8puY3N7KoIIwdxhzTnVRU,23
1
+ piccolo/__init__.py,sha256=VUvL_fuJC_-uD36JTR5DMXk6zqaYLgxYWHSlIeRP_aQ,23
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
@@ -21,10 +21,10 @@ piccolo/apps/asgi/commands/new.py,sha256=ZyYgwpBXb0t-0KQraeja6Y9ANjGEdZCXpu9bmm7
21
21
  piccolo/apps/asgi/commands/templates/app/README.md.jinja,sha256=As3gNEZt9qcRmTVkjCzNtXJ8r4-3g0fCSe7Q-P39ezI,214
22
22
  piccolo/apps/asgi/commands/templates/app/_blacksheep_app.py.jinja,sha256=bgAGe0a9nWk0LAqK3VNDhPcKGqg0z8V-eIX2YmMoZLk,3117
23
23
  piccolo/apps/asgi/commands/templates/app/_esmerald_app.py.jinja,sha256=S-oYY6OFhwJA8PEYnrklQUkqtot3aXTmd7QGrW8Ufn4,2670
24
- piccolo/apps/asgi/commands/templates/app/_fastapi_app.py.jinja,sha256=cCmRVAN8gw6zfHBcLI_NxapwN7LGM5QSXM7K94imDh8,2436
24
+ piccolo/apps/asgi/commands/templates/app/_fastapi_app.py.jinja,sha256=mKnYfUOnYyWJA1jFoRLCUOGQlK6imaxx_1qaauGjeeQ,2627
25
25
  piccolo/apps/asgi/commands/templates/app/_lilya_app.py.jinja,sha256=8rV1p-POGHkFIqvHvlE5wWwWPZweuSnMJhwreLMgLo8,1259
26
26
  piccolo/apps/asgi/commands/templates/app/_litestar_app.py.jinja,sha256=oMH5KXoEYhf9qgXNj2Kepc6prps1MQECufdUduaiwe4,2815
27
- piccolo/apps/asgi/commands/templates/app/_starlette_app.py.jinja,sha256=YvNUlJuTd4mj-pm3WQKbQq3w3x3VfDb_Wz6aQLUsORo,1271
27
+ piccolo/apps/asgi/commands/templates/app/_starlette_app.py.jinja,sha256=vHcAzsS9I3OevYoznwZp8zucI4OEyUjj-EOAtscmlSE,1443
28
28
  piccolo/apps/asgi/commands/templates/app/app.py.jinja,sha256=gROY-LbHl8NtHDM_ntkI7Rjcbtg2ypDZ1FunBvpdjE4,458
29
29
  piccolo/apps/asgi/commands/templates/app/conftest.py.jinja,sha256=ZG1pRVMv3LhIfOsO3_08c_fF3EV4_EApuDHiIFFPJdk,497
30
30
  piccolo/apps/asgi/commands/templates/app/main.py.jinja,sha256=azwXyWZGkrIbZv5bZF_4Tvbly7AXkw5yFWGCHYImGeo,421
@@ -60,7 +60,7 @@ piccolo/apps/migrations/piccolo_app.py,sha256=1EcS2ComBPCaMCC2C3WaPR_GqLwt3XiIJN
60
60
  piccolo/apps/migrations/tables.py,sha256=jqBnK-Rk545v1Eu6GaLHTVz7-uwBTUnz2m58OA-mxTc,799
61
61
  piccolo/apps/migrations/auto/__init__.py,sha256=eYb1rZQaalumv_bhbcEe6x3dUglmpFtw7Egg6k7597U,316
62
62
  piccolo/apps/migrations/auto/diffable_table.py,sha256=FJ_D7FvL_vaThgIY-zFyW_kFmReOI12saM3DFcaAvfw,7058
63
- piccolo/apps/migrations/auto/migration_manager.py,sha256=3RuQPjnBfAfETkBdDPAVAXK3Bx-GW-37WL7uYNJ_sxI,35127
63
+ piccolo/apps/migrations/auto/migration_manager.py,sha256=kzkIbC9Ow2VoxI5uMcCDG-qVZbTHBtluvdawp-tIi20,35150
64
64
  piccolo/apps/migrations/auto/operations.py,sha256=169IrCLR3FtTRxHsEHNg6dTG45lcEM7Aoyy3SwgX_hU,1329
65
65
  piccolo/apps/migrations/auto/schema_differ.py,sha256=VA1rK-_wNSdyZZgfA3ZOlpVGJCcvLyouKtT9k2YKhiA,26266
66
66
  piccolo/apps/migrations/auto/schema_snapshot.py,sha256=ZqUg4NpChOeoACKF2gkhqsz1BW3wOWFnzJCccq-CNNQ,4719
@@ -71,13 +71,13 @@ piccolo/apps/migrations/commands/backwards.py,sha256=sBLotsdbwX11dji4H7YWgbaonlu
71
71
  piccolo/apps/migrations/commands/base.py,sha256=iuF5-PppAVt6eOo0EOtISKuVGsfR3VVcyXCzRYNOcj4,4484
72
72
  piccolo/apps/migrations/commands/check.py,sha256=JbzKAR_SFEs5dYvW0J_X4jgIpJDAHLIRz364JIZT6eQ,3991
73
73
  piccolo/apps/migrations/commands/clean.py,sha256=JYs9VwvGN45tXM2iiaqGj3UQFZhJETrWahT0tcpGvBk,2864
74
- piccolo/apps/migrations/commands/forwards.py,sha256=Xb_QqkGH3RNaJ256jjLBH8TSykNsnblSw4OPANzmXVA,5413
74
+ piccolo/apps/migrations/commands/forwards.py,sha256=03zGZIG4csf5jFrvl3dos6u0AmNTUkh4q0bf9Zt1Yz8,5427
75
75
  piccolo/apps/migrations/commands/new.py,sha256=k1cXGeydfrr3_kscwtahv7QdJW_DtTlUNHk7WW4Kfr8,7924
76
76
  piccolo/apps/migrations/commands/templates/migration.py.jinja,sha256=wMC8RTIcQj3mjZh3FhuxuIfsqftZ5ivraO9fg-H6fbI,681
77
77
  piccolo/apps/playground/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
78
  piccolo/apps/playground/piccolo_app.py,sha256=zs6nGxt-lgUF8nEwI0uDTNZDKQqjZaNDH8le5RqrMNE,222
79
79
  piccolo/apps/playground/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
- piccolo/apps/playground/commands/run.py,sha256=RhuxsnQj8m7iE2ww_de7Jz-dT25gbqMdx1MWeHQ2mCg,8401
80
+ piccolo/apps/playground/commands/run.py,sha256=S8osLV4s_mWdvvVYGn-49wel-d1SFRB17fO3ZtMcv8Y,8629
81
81
  piccolo/apps/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
82
  piccolo/apps/project/piccolo_app.py,sha256=mT3O0m3QcCfS0oOr3jt0QZ9TX6gUavGPjJeNn2C_fdM,220
83
83
  piccolo/apps/project/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -117,7 +117,7 @@ piccolo/apps/user/piccolo_migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeu
117
117
  piccolo/columns/__init__.py,sha256=OYhO_n9anMiU9nL-K6ATq9FhAtm8RyMpqYQ7fTVbhxI,1120
118
118
  piccolo/columns/base.py,sha256=sgMiBvq-xLW6_W86g6XZTMc_3cskyeoMF6yIvIlnXsA,32487
119
119
  piccolo/columns/choices.py,sha256=-HNQuk9vMmVZIPZ5PMeXGTfr23o4nzKPSAkvcG1k0y8,723
120
- piccolo/columns/column_types.py,sha256=YmltgnWhGLpmuMRimPPVQFmzF5hRDB7K1LaAjcI4Lmc,82364
120
+ piccolo/columns/column_types.py,sha256=82JmKDrZ0bh1Jal0HOeu-Q9HzZaWs4liUoyJa9OoJFQ,83533
121
121
  piccolo/columns/combination.py,sha256=vMXC2dfY7pvnCFhsT71XFVyb4gdQzfRsCMaiduu04Ss,6900
122
122
  piccolo/columns/indexes.py,sha256=NfNok3v_791jgDlN28KmhP9ZCjl6031BXmjxV3ovXJk,372
123
123
  piccolo/columns/m2m.py,sha256=17NY0wU7ta2rUTHYUkeA2HQhTDlJ_lyv9FxqvJiiUbY,14602
@@ -149,11 +149,12 @@ piccolo/query/__init__.py,sha256=bcsMV4813rMRAIqGv4DxI4eyO4FmpXkDv9dfTk5pt3A,699
149
149
  piccolo/query/base.py,sha256=G8Mwz0GcHY4Xs5Co9ubCNMI-3orfOsDdRDOnFRws7TU,15212
150
150
  piccolo/query/mixins.py,sha256=EFEFb9It4y1mR6_JXLn139h5M9KgeP750STYy5M4MLs,21951
151
151
  piccolo/query/proxy.py,sha256=Yq4jNc7IWJvdeO3u7_7iPyRy2WhVj8KsIUcIYHBIi9Q,1839
152
- piccolo/query/functions/__init__.py,sha256=e-BEHlGR3JhE2efWG_rmXdURKL4Fa8tjdGmPsvH4kWo,403
152
+ piccolo/query/functions/__init__.py,sha256=pZkzOIh7Sg9HPNOeegOwAS46Oxt31ATlSVmwn-lxCbc,605
153
153
  piccolo/query/functions/aggregate.py,sha256=OdjDjr_zyD4S9UbrZ2C3V5mz4OT2sIfAFAdTGr4WL54,4248
154
154
  piccolo/query/functions/base.py,sha256=Go2bg2r7GaVoyyX-wTb80WEQmtiU4OFYWQlq9eQ6Zcc,478
155
+ piccolo/query/functions/datetime.py,sha256=6YSpc_MiZK_019KUhCo01Ss_1AjXJ31M61R9-zKmoZs,6251
155
156
  piccolo/query/functions/math.py,sha256=2Wapq0lpXZh77z0uzXUhnOfmUkbkM0xjQ4tiyuCsbiE,661
156
- piccolo/query/functions/string.py,sha256=srxsQJFS6L4gPvFjvuAFQj7QtnCF7X6YoJNKARR2XP0,1236
157
+ piccolo/query/functions/string.py,sha256=X3g_4qomJJCkYOcKcK-zZEqC6qJBrS4VTogPp9Xw4Cs,2506
157
158
  piccolo/query/functions/type_conversion.py,sha256=OYbZc6TEk6b5yTwCMw2rmZ-UiQiUiWZOyxwMLzUjXwE,2583
158
159
  piccolo/query/methods/__init__.py,sha256=tm4gLeV_obDqpgnouVjFbGubbaoJcqm_cbNd4LPo48Q,622
159
160
  piccolo/query/methods/alter.py,sha256=AI9YkJeip2EitrWJN_TDExXhA8HGAG3XuDz1NR-KirQ,16728
@@ -220,7 +221,7 @@ tests/apps/migrations/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
220
221
  tests/apps/migrations/commands/test_base.py,sha256=NgHgVjNd3Hil9eODvW7Ic2D9muTa_grNaH3YpRFfR8I,1829
221
222
  tests/apps/migrations/commands/test_check.py,sha256=hOX_sVk1nfCRfbQ8tJoFEUBFhih9O4QuQLHTp5TQaiY,630
222
223
  tests/apps/migrations/commands/test_clean.py,sha256=lPzLLXhoUyyffY3EQIiyRj-QfP07UVNTha21cEZivfY,1124
223
- tests/apps/migrations/commands/test_forwards_backwards.py,sha256=-rwQ3r61eq6lfoMdM-fajK09SAftPn5cri_gSkF2lMk,7107
224
+ tests/apps/migrations/commands/test_forwards_backwards.py,sha256=VklO8Af6F_ASYWFmSS829ls-mKdwBgdeGG_FFIaYtng,8133
224
225
  tests/apps/migrations/commands/test_new.py,sha256=dKXOuU6t_6zziHHLvX_JdM_Oiee2Lc7FEuADZsMlNQA,4249
225
226
  tests/apps/migrations/commands/test_migrations/2020-03-31T20-38-22.py,sha256=9pYiFNDi-7TJy5TZ3MeNThttjjcUg6cEQ4J5Yv9wQQ8,601
226
227
  tests/apps/migrations/commands/test_migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -243,33 +244,33 @@ tests/apps/user/commands/test_change_permissions.py,sha256=uVKEiT1EKot3VA2TDETdQ
243
244
  tests/apps/user/commands/test_create.py,sha256=iJ3Tti62rHwvdcTwNXrc5JPam6vR1qxKRdMN456vm3o,2250
244
245
  tests/apps/user/commands/test_list.py,sha256=ipPfGdW6fH7q-Jc7JcYUvlioGmH9GQU0WImZGC2m-XQ,2840
245
246
  tests/columns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
246
- tests/columns/test_array.py,sha256=sHYL2hEMwinoGz2u72Db9P3GxNuuH3oPUwzzKWmzX9s,11691
247
+ tests/columns/test_array.py,sha256=QixxML6vRq-PUliqbZSKd_LE5T4fEj5nq5e1NpOhng0,11590
247
248
  tests/columns/test_base.py,sha256=CTqCNcrqAJTjLXe3MCZgTczrmB3jcVRcOpU4FilpLoQ,3918
248
- tests/columns/test_bigint.py,sha256=a0B4y1H02ww5qaW574X2lyenbY6o29ztOhiaqybPC0c,1149
249
- tests/columns/test_boolean.py,sha256=kDESp6FnRtSZhuqIu0dBRwKMSpS5TFbbs3sz2MyZSs8,1720
250
- tests/columns/test_bytea.py,sha256=ji-_GuvpOO4FKjKbhNsxuZTDprjO3y5Oo2BkwxHiTVI,1596
251
- tests/columns/test_choices.py,sha256=5fi5cqiQDbErR3-1JaI_UrUhf6QpdMUO3dhKk1_cfyw,4269
249
+ tests/columns/test_bigint.py,sha256=KqIw6UP3vGs3cyL1I1An8RfXMmjZvfSIuKYhgkqX5zI,1021
250
+ tests/columns/test_boolean.py,sha256=dFqyUnzXU8JSflI511Vt3Gxk62lpIVgH37vnDEz0E2M,1611
251
+ tests/columns/test_bytea.py,sha256=-XCXTKboPSfowhU7nceRnkhVCJ60Kus52b3f67xAlAo,1367
252
+ tests/columns/test_choices.py,sha256=xDWgcguCH4pu8w3JpIcSyurpghPsbc4OQmzjup2iTIw,4029
252
253
  tests/columns/test_combination.py,sha256=BuBwR7k5X1EkOWraZpjqU6gvtb6ow_k-7N1KQBiW2RA,1681
253
- tests/columns/test_date.py,sha256=lz3AF64CkQzulfniGs0fxuvbH2grR3pF2sxipXiyvHU,1243
254
+ tests/columns/test_date.py,sha256=WnwtCS81mYsDpwDrMnZRDjHA7ag-bxMPundRxtTlv1A,1015
254
255
  tests/columns/test_db_column_name.py,sha256=v0QFOQp_atqzMB1n40simVwHeBDi5nyN1N2bSPX5k6w,7670
255
256
  tests/columns/test_defaults.py,sha256=rwlU1fXt3cCl7C51eLlZXqgWkE-K5W0pHvTrwkAKyCo,2896
256
- tests/columns/test_double_precision.py,sha256=CuobfnQnuwqAIuuOPoh2mKHnY9A7gZosoMIGpY-ubfE,639
257
+ tests/columns/test_double_precision.py,sha256=Nx1vgmQqwn1PgBC6KcPO9yHKe9v8lCQXrEA1GcUJIn4,529
257
258
  tests/columns/test_get_sql_value.py,sha256=mKgsInN374jzV99y9mg_ZiG-AvnJgz36SZi89xL7RZM,1768
258
- tests/columns/test_interval.py,sha256=SbeRgTBWPBL5_LYQUdaP3qyN6eTNtTJtu8JXWollhQw,2993
259
- tests/columns/test_json.py,sha256=ErGytVqMVO86YiqGmQIcqb2zUcAUY_ya-cY9tSKKXhQ,3920
260
- tests/columns/test_jsonb.py,sha256=7MeH0h2SJt_uCUL6D5-6DLTBPlaz6qKSJcnyhuwvzHg,6914
261
- tests/columns/test_numeric.py,sha256=ukh7rW3uAOQmLV9m36uyHcwC9te1SLKwUrh4KDXIEbc,845
262
- tests/columns/test_primary_key.py,sha256=6kKYs5qxIe0dJ7FQIFa-7c4LAsPQtiZbBviUiVoaTd0,5572
263
- tests/columns/test_readable.py,sha256=kMuge5X_PfVeE1PjStwEHY-W0zwrxVBXV0CiW2Gw7kE,802
264
- tests/columns/test_real.py,sha256=iM49DhFS2HaDX88NgelJumT-FPqqnVP84Z2m_KfnnQQ,606
259
+ tests/columns/test_interval.py,sha256=R3fyC7IX35neiu64XR7KX58ylpPzeU2zSEbaKdbW4I4,2765
260
+ tests/columns/test_json.py,sha256=nbNXo0CISU8w3CjIF7nxBmRfEdenGFmc0o9YfhMvpKg,3467
261
+ tests/columns/test_jsonb.py,sha256=Np3FZf3AspTGRWCCMrTYEsw6uTJPI8u3SZkOvH5ERRg,6690
262
+ tests/columns/test_numeric.py,sha256=WrilQrWc-_g8DGLUvmllSBL01xqYqDORt3ypplnRizA,736
263
+ tests/columns/test_primary_key.py,sha256=hXnTF-kFgrFNjawvJstmR3YQCM59qJ4NWkMD9vRY8FI,4871
264
+ tests/columns/test_readable.py,sha256=OFK2n_k-eqRLdjEg1X2aOFPNwhtGDPNBli4DAh3i6vw,743
265
+ tests/columns/test_real.py,sha256=bSjACkbnJzrN9dEWVb0UdWqSDfxdGz5HMWc8PUsJUl4,496
265
266
  tests/columns/test_reference.py,sha256=I_gjICtJ7bE2cBrmCv-kz25AvI922A3pizRVIhHpzSE,1508
266
- tests/columns/test_reserved_column_names.py,sha256=NxkrZevxb1GV2fYoWKUVPscCBP39qgpiTyqfBxc8wag,1514
267
- tests/columns/test_smallint.py,sha256=5pknplEbg6o03xJyrcYBRuV5qarOp3TAfR3OKobiaqw,1115
268
- tests/columns/test_time.py,sha256=PfN-1x0eIPu2ULljbhIVJdyrcGXLOUQww_NOSHZXdZI,1810
269
- tests/columns/test_timestamp.py,sha256=3f6-cKTZYWMJK-eLl4z-4eR6ODdAhED2Y6keoXtwQbc,1899
270
- tests/columns/test_timestamptz.py,sha256=CLVoya-2cA8WQWD6DyBI1jhq5iXlF0hwbOT8kmRU1UU,2843
271
- tests/columns/test_uuid.py,sha256=HDh_qvznN7nUjCaJ-TJwRcPjMTYMLhrO_oOHtW9MAAc,466
272
- tests/columns/test_varchar.py,sha256=5IY9J5m1Hmuq1vZ78aApwPYI7J-XZFVtZVHPhlKGn8Y,813
267
+ tests/columns/test_reserved_column_names.py,sha256=BpqN49n_AaiPjaaJ43hLhFXQHb8NV6ig8nvgKvN0Smc,1404
268
+ tests/columns/test_smallint.py,sha256=t-LNX7XXy-k5_lhGXwELyC0LB9Iq4WrBVQdvEYf5EaQ,984
269
+ tests/columns/test_time.py,sha256=qyG4jjSO_B2DfkjQo3nIff2T201c75EI7M6CYspK5QM,1560
270
+ tests/columns/test_timestamp.py,sha256=lkb1pQW41kQ_c7zLjPfls7EgnIMnvG9AK3ePb5izJU0,1671
271
+ tests/columns/test_timestamptz.py,sha256=Py27sx45-xQElhuLVxNtZjBxz3t6VJUbyUGW3H4W7eU,2615
272
+ tests/columns/test_uuid.py,sha256=ifCyIrO6usYO33WM0FgwuPPhYzs4zVKD3MViIT61J7c,357
273
+ tests/columns/test_varchar.py,sha256=Oyt8t7msCfIiZdU9B23zjlV6atFv4sX3iMSDJc565Oc,681
273
274
  tests/columns/m2m/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
274
275
  tests/columns/m2m/base.py,sha256=uH92ECQuY5AjpQXPySwrlruZPZzB4LH2V2FUSXmHRLQ,14563
275
276
  tests/columns/m2m/test_m2m.py,sha256=LtNsHQ8xAzBFLiZVZhWEB56zu25FnaWtzJ62FZH3heI,12647
@@ -302,10 +303,11 @@ tests/query/test_gather.py,sha256=okWANrBoh0Ut1RomWoffiWNpFqiITF6qti-Aa3uYtRk,73
302
303
  tests/query/test_querystring.py,sha256=QrqyjwUlFlf5LrsJ7DgjCruq811I0UvrDFPud6rfZNI,5019
303
304
  tests/query/test_slots.py,sha256=I9ZjAYqAJNSFAWg9UyAqy7bm-Z52KiyQ2C_yHk2qqqI,1010
304
305
  tests/query/functions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
305
- tests/query/functions/base.py,sha256=RLCzLT7iN_Z5DtIFZqVESTJGES2JKb8VDU25sv5OtN4,811
306
+ tests/query/functions/base.py,sha256=sCIolQlvOMlnrLJJBAfJV-Tg8dCzkGnCs83JqRQpKkk,500
307
+ tests/query/functions/test_datetime.py,sha256=247Vpbyuq0s-SU-883t6W5ghF8xiz44LzdHd2nJ0mZ4,2963
306
308
  tests/query/functions/test_functions.py,sha256=510fqRrOrAZ9NyFoZtlF6lIdiiLriWhZ7vvveWZ8rsc,1984
307
- tests/query/functions/test_math.py,sha256=Qw2MXqgY_y7vGd0bLtPhWW7HB3tJkot1o-Rh9nCmmBk,1273
308
- tests/query/functions/test_string.py,sha256=7yNkpWNBaIowzXTP_qbmQg-mJZLWrTk0lx2mgY1NIfA,825
309
+ tests/query/functions/test_math.py,sha256=nrHrThxurZIvbqlN4mjfxtKqLdBxOrWoeIZ_QCRJuTs,1271
310
+ tests/query/functions/test_string.py,sha256=RMojkBUzw1Ikrb3nTa7VjJ4FsKfrjpuHUyxQDA-F5Cs,1800
309
311
  tests/query/functions/test_type_conversion.py,sha256=WeYR9UfJnbidle07-akQ1g9hFCd93qT8xUhDF3c58n4,3235
310
312
  tests/query/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
311
313
  tests/query/mixins/test_columns_delegate.py,sha256=Zw9uaqOEb7kpPQzzO9yz0jhQEeCfoPSjsy-BCLg_8XU,2032
@@ -363,9 +365,9 @@ tests/utils/test_sql_values.py,sha256=vzxRmy16FfLZPH-sAQexBvsF9MXB8n4smr14qoEOS5
363
365
  tests/utils/test_sync.py,sha256=9ytVo56y2vPQePvTeIi9lHIouEhWJbodl1TmzkGFrSo,799
364
366
  tests/utils/test_table_reflection.py,sha256=SIzuat-IpcVj1GCFyOWKShI8YkhdOPPFH7qVrvfyPNE,3794
365
367
  tests/utils/test_warnings.py,sha256=NvSC_cvJ6uZcwAGf1m-hLzETXCqprXELL8zg3TNLVMw,269
366
- piccolo-1.10.0.dist-info/LICENSE,sha256=zFIpi-16uIJ420UMIG75NU0JbDBykvrdnXcj5U_EYBI,1059
367
- piccolo-1.10.0.dist-info/METADATA,sha256=iOzLZbrVstdxKNx_ifn_M7voMrX0KkQsBcPB39vw0VE,5178
368
- piccolo-1.10.0.dist-info/WHEEL,sha256=00yskusixUoUt5ob_CiUp6LsnN5lqzTJpoqOFg_FVIc,92
369
- piccolo-1.10.0.dist-info/entry_points.txt,sha256=SJPHET4Fi1bN5F3WqcKkv9SClK3_F1I7m4eQjk6AFh0,46
370
- piccolo-1.10.0.dist-info/top_level.txt,sha256=-SR74VGbk43VoPy1HH-mHm97yoGukLK87HE5kdBW6qM,24
371
- piccolo-1.10.0.dist-info/RECORD,,
368
+ piccolo-1.12.0.dist-info/LICENSE,sha256=zFIpi-16uIJ420UMIG75NU0JbDBykvrdnXcj5U_EYBI,1059
369
+ piccolo-1.12.0.dist-info/METADATA,sha256=255a7LoWzwC58EKwF0kgMAONG47eqD5AuHdwt8rtEUs,5150
370
+ piccolo-1.12.0.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
371
+ piccolo-1.12.0.dist-info/entry_points.txt,sha256=SJPHET4Fi1bN5F3WqcKkv9SClK3_F1I7m4eQjk6AFh0,46
372
+ piccolo-1.12.0.dist-info/top_level.txt,sha256=-SR74VGbk43VoPy1HH-mHm97yoGukLK87HE5kdBW6qM,24
373
+ piccolo-1.12.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.38.1)
2
+ Generator: setuptools (70.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -192,7 +192,7 @@ class TestForwardsBackwards(TestCase):
192
192
  @engines_only("postgres")
193
193
  def test_forwards_fake(self):
194
194
  """
195
- Test running the migrations if they've already run.
195
+ Make sure migrations can be faked on the command line.
196
196
  """
197
197
  run_sync(forwards(app_name="music", migration_id="all", fake=True))
198
198
 
@@ -214,9 +214,40 @@ class TestForwardsBackwards(TestCase):
214
214
  "2021-09-06T13:58:23:024723",
215
215
  "2021-11-13T14:01:46:114725",
216
216
  "2024-05-28T23:15:41:018844",
217
+ "2024-06-19T18:11:05:793132",
217
218
  ],
218
219
  )
219
220
 
221
+ @engines_only("postgres")
222
+ @patch("piccolo.apps.migrations.commands.forwards.print")
223
+ def test_hardcoded_fake_migrations(self, print_: MagicMock):
224
+ """
225
+ Make sure that migrations that have been hardcoded as fake aren't
226
+ executed, even without the ``--fake`` command line flag.
227
+
228
+ See tests/example_apps/music/piccolo_migrations/music_2024_06_19t18_11_05_793132.py
229
+
230
+ """ # noqa: E501
231
+ run_sync(forwards(app_name="music", migration_id="all"))
232
+
233
+ # The migration which is hardcoded as fake:
234
+ migration_name = "2024-06-19T18:11:05:793132"
235
+
236
+ self.assertTrue(
237
+ Migration.exists()
238
+ .where(Migration.name == migration_name)
239
+ .run_sync()
240
+ )
241
+
242
+ self.assertNotIn(
243
+ call("Running fake migration"),
244
+ print_.mock_calls,
245
+ )
246
+ self.assertIn(
247
+ call(f"- {migration_name}: faked! ⏭️"),
248
+ print_.mock_calls,
249
+ )
250
+
220
251
  def tearDown(self):
221
252
  for table_class in TABLE_CLASSES + [Migration]:
222
253
  table_class.alter().drop_table(
@@ -14,7 +14,7 @@ from piccolo.columns.column_types import (
14
14
  )
15
15
  from piccolo.querystring import QueryString
16
16
  from piccolo.table import Table
17
- from tests.base import engines_only, engines_skip, sqlite_only
17
+ from tests.base import TableTest, engines_only, engines_skip, sqlite_only
18
18
 
19
19
 
20
20
  class MyTable(Table):
@@ -32,16 +32,12 @@ class TestArrayDefault(TestCase):
32
32
  self.assertTrue(column.default is list)
33
33
 
34
34
 
35
- class TestArray(TestCase):
35
+ class TestArray(TableTest):
36
36
  """
37
37
  Make sure an Array column can be created, and works correctly.
38
38
  """
39
39
 
40
- def setUp(self):
41
- MyTable.create_table().run_sync()
42
-
43
- def tearDown(self):
44
- MyTable.alter().drop_table().run_sync()
40
+ tables = [MyTable]
45
41
 
46
42
  @pytest.mark.cockroach_array_slow
47
43
  def test_storage(self):
@@ -1,10 +1,8 @@
1
1
  import os
2
- from unittest import TestCase
3
2
 
4
3
  from piccolo.columns.column_types import BigInt
5
4
  from piccolo.table import Table
6
-
7
- from ..base import engines_only
5
+ from tests.base import TableTest, engines_only
8
6
 
9
7
 
10
8
  class MyTable(Table):
@@ -12,16 +10,12 @@ class MyTable(Table):
12
10
 
13
11
 
14
12
  @engines_only("postgres", "cockroach")
15
- class TestBigIntPostgres(TestCase):
13
+ class TestBigIntPostgres(TableTest):
16
14
  """
17
15
  Make sure a BigInt column in Postgres can store a large number.
18
16
  """
19
17
 
20
- def setUp(self):
21
- MyTable.create_table().run_sync()
22
-
23
- def tearDown(self):
24
- MyTable.alter().drop_table().run_sync()
18
+ tables = [MyTable]
25
19
 
26
20
  def _test_length(self):
27
21
  # Can store 8 bytes, but split between positive and negative values.