piccolo 1.28.0__py3-none-any.whl → 1.29.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/new.py +1 -1
- piccolo/apps/asgi/commands/templates/app/_blacksheep_app.py.jinja +57 -29
- piccolo/apps/asgi/commands/templates/app/_esmerald_app.py.jinja +48 -21
- piccolo/apps/asgi/commands/templates/app/_falcon_app.py.jinja +63 -8
- piccolo/apps/asgi/commands/templates/app/_fastapi_app.py.jinja +51 -24
- piccolo/apps/asgi/commands/templates/app/_litestar_app.py.jinja +34 -10
- piccolo/apps/asgi/commands/templates/app/_quart_app.py.jinja +38 -15
- piccolo/apps/asgi/commands/templates/app/_sanic_app.py.jinja +34 -11
- piccolo/apps/playground/commands/run.py +43 -0
- piccolo/columns/column_types.py +2 -2
- piccolo/table.py +14 -6
- piccolo/testing/model_builder.py +4 -2
- piccolo/testing/random_builder.py +12 -0
- {piccolo-1.28.0.dist-info → piccolo-1.29.0.dist-info}/METADATA +1 -1
- {piccolo-1.28.0.dist-info → piccolo-1.29.0.dist-info}/RECORD +26 -26
- tests/columns/m2m/base.py +18 -47
- tests/table/test_metaclass.py +7 -3
- tests/table/test_str.py +30 -22
- tests/table/test_update.py +15 -0
- tests/testing/test_random_builder.py +5 -0
- tests/utils/test_pydantic.py +116 -98
- {piccolo-1.28.0.dist-info → piccolo-1.29.0.dist-info}/WHEEL +0 -0
- {piccolo-1.28.0.dist-info → piccolo-1.29.0.dist-info}/entry_points.txt +0 -0
- {piccolo-1.28.0.dist-info → piccolo-1.29.0.dist-info}/licenses/LICENSE +0 -0
- {piccolo-1.28.0.dist-info → piccolo-1.29.0.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,10 @@
|
|
1
|
-
import
|
2
|
-
import typing as t
|
1
|
+
from typing import Any
|
3
2
|
|
4
3
|
from hypercorn.middleware import DispatcherMiddleware
|
5
4
|
from piccolo.engine import engine_finder
|
6
5
|
from piccolo_admin.endpoints import create_admin
|
7
6
|
from piccolo_api.crud.serializers import create_pydantic_model
|
8
|
-
from sanic import Request, Sanic, json
|
7
|
+
from sanic import NotFound, Request, Sanic, json
|
9
8
|
from sanic_ext import openapi
|
10
9
|
|
11
10
|
from home.endpoints import index
|
@@ -16,17 +15,24 @@ app = Sanic(__name__)
|
|
16
15
|
app.static("/static/", "static")
|
17
16
|
|
18
17
|
|
19
|
-
TaskModelIn:
|
18
|
+
TaskModelIn: Any = create_pydantic_model(
|
20
19
|
table=Task,
|
21
20
|
model_name="TaskModelIn",
|
22
21
|
)
|
23
|
-
TaskModelOut:
|
22
|
+
TaskModelOut: Any = create_pydantic_model(
|
24
23
|
table=Task,
|
25
24
|
include_default_columns=True,
|
26
25
|
model_name="TaskModelOut",
|
27
26
|
)
|
28
27
|
|
29
28
|
|
29
|
+
# Check if the record is None. Use for query callback
|
30
|
+
def check_record_not_found(result: dict[str, Any]) -> dict[str, Any]:
|
31
|
+
if result is None:
|
32
|
+
raise NotFound(message="Record not found")
|
33
|
+
return result
|
34
|
+
|
35
|
+
|
30
36
|
@app.get("/")
|
31
37
|
@openapi.exclude()
|
32
38
|
def home(request: Request):
|
@@ -43,6 +49,19 @@ async def tasks(request: Request):
|
|
43
49
|
)
|
44
50
|
|
45
51
|
|
52
|
+
@app.get("/tasks/<task_id:int>/")
|
53
|
+
@openapi.tag("Task")
|
54
|
+
@openapi.response(200, {"application/json": TaskModelOut.model_json_schema()})
|
55
|
+
async def single_task(request: Request, task_id: int):
|
56
|
+
task = (
|
57
|
+
await Task.select()
|
58
|
+
.where(Task._meta.primary_key == task_id)
|
59
|
+
.first()
|
60
|
+
.callback(check_record_not_found)
|
61
|
+
)
|
62
|
+
return json(task, status=200)
|
63
|
+
|
64
|
+
|
46
65
|
@app.post("/tasks/")
|
47
66
|
@openapi.definition(
|
48
67
|
body={"application/json": TaskModelIn.model_json_schema()},
|
@@ -62,9 +81,11 @@ async def create_task(request: Request):
|
|
62
81
|
)
|
63
82
|
@openapi.response(200, {"application/json": TaskModelOut.model_json_schema()})
|
64
83
|
async def update_task(request: Request, task_id: int):
|
65
|
-
task =
|
66
|
-
|
67
|
-
|
84
|
+
task = (
|
85
|
+
await Task.objects()
|
86
|
+
.get(Task._meta.primary_key == task_id)
|
87
|
+
.callback(check_record_not_found)
|
88
|
+
)
|
68
89
|
for key, value in request.json.items():
|
69
90
|
setattr(task, key, value)
|
70
91
|
|
@@ -75,9 +96,11 @@ async def update_task(request: Request, task_id: int):
|
|
75
96
|
@app.delete("/tasks/<task_id:int>/")
|
76
97
|
@openapi.tag("Task")
|
77
98
|
async def delete_task(request: Request, task_id: int):
|
78
|
-
task =
|
79
|
-
|
80
|
-
|
99
|
+
task = (
|
100
|
+
await Task.objects()
|
101
|
+
.get(Task._meta.primary_key == task_id)
|
102
|
+
.callback(check_record_not_found)
|
103
|
+
)
|
81
104
|
await task.remove()
|
82
105
|
return json({}, status=200)
|
83
106
|
|
@@ -12,6 +12,7 @@ from typing import Optional
|
|
12
12
|
|
13
13
|
from piccolo.columns import (
|
14
14
|
JSON,
|
15
|
+
M2M,
|
15
16
|
UUID,
|
16
17
|
Array,
|
17
18
|
Boolean,
|
@@ -19,6 +20,7 @@ from piccolo.columns import (
|
|
19
20
|
ForeignKey,
|
20
21
|
Integer,
|
21
22
|
Interval,
|
23
|
+
LazyTableReference,
|
22
24
|
Numeric,
|
23
25
|
Serial,
|
24
26
|
Text,
|
@@ -49,6 +51,7 @@ class Band(Table):
|
|
49
51
|
name = Varchar(length=50)
|
50
52
|
manager = ForeignKey(references=Manager, null=True)
|
51
53
|
popularity = Integer()
|
54
|
+
genres = M2M(LazyTableReference("GenreToBand", module_path=__name__))
|
52
55
|
|
53
56
|
@classmethod
|
54
57
|
def get_readable(cls) -> Readable:
|
@@ -161,6 +164,26 @@ class Album(Table):
|
|
161
164
|
)
|
162
165
|
|
163
166
|
|
167
|
+
class Genre(Table):
|
168
|
+
id: Serial
|
169
|
+
name = Varchar()
|
170
|
+
bands = M2M(LazyTableReference("GenreToBand", module_path=__name__))
|
171
|
+
|
172
|
+
@classmethod
|
173
|
+
def get_readable(cls) -> Readable:
|
174
|
+
return Readable(
|
175
|
+
template="%s",
|
176
|
+
columns=[cls.name],
|
177
|
+
)
|
178
|
+
|
179
|
+
|
180
|
+
class GenreToBand(Table):
|
181
|
+
id: Serial
|
182
|
+
band = ForeignKey(Band)
|
183
|
+
genre = ForeignKey(Genre)
|
184
|
+
reason = Text(null=True, default=None)
|
185
|
+
|
186
|
+
|
164
187
|
TABLES = (
|
165
188
|
Manager,
|
166
189
|
Band,
|
@@ -171,6 +194,8 @@ TABLES = (
|
|
171
194
|
DiscountCode,
|
172
195
|
RecordingStudio,
|
173
196
|
Album,
|
197
|
+
Genre,
|
198
|
+
GenreToBand,
|
174
199
|
)
|
175
200
|
|
176
201
|
|
@@ -282,6 +307,24 @@ def populate():
|
|
282
307
|
),
|
283
308
|
).run_sync()
|
284
309
|
|
310
|
+
genres = Genre.insert(
|
311
|
+
Genre(name="Rock"),
|
312
|
+
Genre(name="Classical"),
|
313
|
+
Genre(name="Folk"),
|
314
|
+
).run_sync()
|
315
|
+
|
316
|
+
GenreToBand.insert(
|
317
|
+
GenreToBand(
|
318
|
+
band=pythonistas.id,
|
319
|
+
genre=genres[0]["id"],
|
320
|
+
reason="Because they rock.",
|
321
|
+
),
|
322
|
+
GenreToBand(band=pythonistas.id, genre=genres[2]["id"]),
|
323
|
+
GenreToBand(band=rustaceans.id, genre=genres[2]["id"]),
|
324
|
+
GenreToBand(band=c_sharps.id, genre=genres[0]["id"]),
|
325
|
+
GenreToBand(band=c_sharps.id, genre=genres[1]["id"]),
|
326
|
+
).run_sync()
|
327
|
+
|
285
328
|
|
286
329
|
def run(
|
287
330
|
engine: str = "sqlite",
|
piccolo/columns/column_types.py
CHANGED
@@ -158,8 +158,8 @@ class MathDelegate:
|
|
158
158
|
raise ValueError(
|
159
159
|
"Adding values across joins isn't currently supported."
|
160
160
|
)
|
161
|
-
|
162
|
-
return QueryString(f"{column_name} {operator} {
|
161
|
+
other_column_name = value._meta.db_column_name
|
162
|
+
return QueryString(f"{column_name} {operator} {other_column_name}")
|
163
163
|
elif isinstance(value, (int, float)):
|
164
164
|
if reverse:
|
165
165
|
return QueryString(f"{{}} {operator} {column_name}", value)
|
piccolo/table.py
CHANGED
@@ -16,7 +16,6 @@ from piccolo.columns.column_types import (
|
|
16
16
|
Email,
|
17
17
|
ForeignKey,
|
18
18
|
ReferencedTable,
|
19
|
-
Secret,
|
20
19
|
Serial,
|
21
20
|
)
|
22
21
|
from piccolo.columns.defaults.base import Default
|
@@ -84,7 +83,7 @@ class TableMeta:
|
|
84
83
|
foreign_key_columns: list[ForeignKey] = field(default_factory=list)
|
85
84
|
primary_key: Column = field(default_factory=Column)
|
86
85
|
json_columns: list[Union[JSON, JSONB]] = field(default_factory=list)
|
87
|
-
secret_columns: list[
|
86
|
+
secret_columns: list[Column] = field(default_factory=list)
|
88
87
|
auto_update_columns: list[Column] = field(default_factory=list)
|
89
88
|
tags: list[str] = field(default_factory=list)
|
90
89
|
help_text: Optional[str] = None
|
@@ -274,7 +273,7 @@ class Table(metaclass=TableMetaclass):
|
|
274
273
|
non_default_columns: list[Column] = []
|
275
274
|
array_columns: list[Array] = []
|
276
275
|
foreign_key_columns: list[ForeignKey] = []
|
277
|
-
secret_columns: list[
|
276
|
+
secret_columns: list[Column] = []
|
278
277
|
json_columns: list[Union[JSON, JSONB]] = []
|
279
278
|
email_columns: list[Email] = []
|
280
279
|
auto_update_columns: list[Column] = []
|
@@ -315,15 +314,15 @@ class Table(metaclass=TableMetaclass):
|
|
315
314
|
if isinstance(column, Email):
|
316
315
|
email_columns.append(column)
|
317
316
|
|
318
|
-
if isinstance(column, Secret):
|
319
|
-
secret_columns.append(column)
|
320
|
-
|
321
317
|
if isinstance(column, ForeignKey):
|
322
318
|
foreign_key_columns.append(column)
|
323
319
|
|
324
320
|
if isinstance(column, (JSON, JSONB)):
|
325
321
|
json_columns.append(column)
|
326
322
|
|
323
|
+
if column._meta.secret:
|
324
|
+
secret_columns.append(column)
|
325
|
+
|
327
326
|
if column._meta.auto_update is not ...:
|
328
327
|
auto_update_columns.append(column)
|
329
328
|
|
@@ -1373,6 +1372,15 @@ class Table(metaclass=TableMetaclass):
|
|
1373
1372
|
columns.append(
|
1374
1373
|
f"{col._meta.name} = {col.__class__.__name__}({params_string})"
|
1375
1374
|
)
|
1375
|
+
|
1376
|
+
for m2m_relationship in cls._meta.m2m_relationships:
|
1377
|
+
joining_table_name = (
|
1378
|
+
m2m_relationship._meta.resolved_joining_table.__name__
|
1379
|
+
)
|
1380
|
+
columns.append(
|
1381
|
+
f"{m2m_relationship._meta.name} = M2M({joining_table_name})"
|
1382
|
+
)
|
1383
|
+
|
1376
1384
|
columns_string = spacer.join(columns)
|
1377
1385
|
tablename = repr(cls._meta.tablename)
|
1378
1386
|
|
piccolo/testing/model_builder.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import datetime
|
4
|
+
import decimal
|
4
5
|
import json
|
5
6
|
from collections.abc import Callable
|
6
7
|
from decimal import Decimal
|
@@ -20,6 +21,7 @@ class ModelBuilder:
|
|
20
21
|
datetime.date: RandomBuilder.next_date,
|
21
22
|
datetime.datetime: RandomBuilder.next_datetime,
|
22
23
|
float: RandomBuilder.next_float,
|
24
|
+
decimal.Decimal: RandomBuilder.next_decimal,
|
23
25
|
int: RandomBuilder.next_int,
|
24
26
|
str: RandomBuilder.next_str,
|
25
27
|
datetime.time: RandomBuilder.next_time,
|
@@ -163,8 +165,8 @@ class ModelBuilder:
|
|
163
165
|
random_value: Any
|
164
166
|
if column.value_type == Decimal:
|
165
167
|
precision, scale = column._meta.params["digits"] or (4, 2)
|
166
|
-
random_value = RandomBuilder.
|
167
|
-
|
168
|
+
random_value = RandomBuilder.next_decimal(
|
169
|
+
precision=precision, scale=scale
|
168
170
|
)
|
169
171
|
elif column.value_type == datetime.datetime:
|
170
172
|
tz_aware = getattr(column, "tz_aware", False)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import datetime
|
2
|
+
import decimal
|
2
3
|
import enum
|
3
4
|
import random
|
4
5
|
import string
|
@@ -43,6 +44,17 @@ class RandomBuilder:
|
|
43
44
|
def next_float(cls, minimum=0, maximum=2147483647, scale=5) -> float:
|
44
45
|
return round(random.uniform(minimum, maximum), scale)
|
45
46
|
|
47
|
+
@classmethod
|
48
|
+
def next_decimal(
|
49
|
+
cls, precision: int = 4, scale: int = 2
|
50
|
+
) -> decimal.Decimal:
|
51
|
+
# For precision 4 and scale 2, maximum needs to be 99.99.
|
52
|
+
maximum = (10 ** (precision - scale)) - (10 ** (-1 * scale))
|
53
|
+
float_number = cls.next_float(maximum=maximum, scale=scale)
|
54
|
+
# We convert float_number to a string first, otherwise the decimal
|
55
|
+
# value is slightly off due to floating point precision.
|
56
|
+
return decimal.Decimal(str(float_number))
|
57
|
+
|
46
58
|
@classmethod
|
47
59
|
def next_int(cls, minimum=0, maximum=2147483647) -> int:
|
48
60
|
return random.randint(minimum, maximum)
|
@@ -1,10 +1,10 @@
|
|
1
|
-
piccolo/__init__.py,sha256=
|
1
|
+
piccolo/__init__.py,sha256=C-iTYm1gDGgB27Giaf3CpBiC_O-eM1faeVO4P3hLU68,23
|
2
2
|
piccolo/custom_types.py,sha256=3ceuQZNMQTXVikZzACnJS4eIIgTpwubKg2kaKOshprw,1035
|
3
3
|
piccolo/main.py,sha256=1VsFV67FWTUikPTysp64Fmgd9QBVa_9wcwKfwj2UCEA,5117
|
4
4
|
piccolo/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
piccolo/querystring.py,sha256=nOSCh5sTng-dxHr5WdUqf7TwYTrKAgkEP5GcrBmcW9I,10011
|
6
6
|
piccolo/schema.py,sha256=2S5SlG9FfAuRKNLA6cADziNcFJ1PeNj5uhc_NJ-_g0I,7953
|
7
|
-
piccolo/table.py,sha256
|
7
|
+
piccolo/table.py,sha256=-i932n96luHZd2UJ0-qboky_DQaoM6xaRAvYt9HeXdE,50721
|
8
8
|
piccolo/table_reflection.py,sha256=q3Dp70SI0r8eNduOgVv4u4_W5NwN6A54oYB_2BnyaVY,7535
|
9
9
|
piccolo/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
piccolo/apps/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -17,16 +17,16 @@ piccolo/apps/app/commands/templates/tables.py.jinja,sha256=revzdrvDDwe78VedBKz0z
|
|
17
17
|
piccolo/apps/asgi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
18
|
piccolo/apps/asgi/piccolo_app.py,sha256=7VUvqQJbB-ScO0A62S6MiJmQL9F5DS-SdlqlDLbAblE,217
|
19
19
|
piccolo/apps/asgi/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
-
piccolo/apps/asgi/commands/new.py,sha256=
|
20
|
+
piccolo/apps/asgi/commands/new.py,sha256=DiwR49zIvTSfsByaCjqleWD38UjHsWUE8hIf2C7DICA,4320
|
21
21
|
piccolo/apps/asgi/commands/templates/app/README.md.jinja,sha256=As3gNEZt9qcRmTVkjCzNtXJ8r4-3g0fCSe7Q-P39ezI,214
|
22
|
-
piccolo/apps/asgi/commands/templates/app/_blacksheep_app.py.jinja,sha256=
|
23
|
-
piccolo/apps/asgi/commands/templates/app/_esmerald_app.py.jinja,sha256=
|
24
|
-
piccolo/apps/asgi/commands/templates/app/_falcon_app.py.jinja,sha256=
|
25
|
-
piccolo/apps/asgi/commands/templates/app/_fastapi_app.py.jinja,sha256=
|
22
|
+
piccolo/apps/asgi/commands/templates/app/_blacksheep_app.py.jinja,sha256=xumVDAcbnVoaAcslDyUyx8MQU2qghB7LnJR-8IJAhSc,3824
|
23
|
+
piccolo/apps/asgi/commands/templates/app/_esmerald_app.py.jinja,sha256=clKi85iqujPdP0M88QjocBme17zxKB4G5-Ay4SMzVbg,3433
|
24
|
+
piccolo/apps/asgi/commands/templates/app/_falcon_app.py.jinja,sha256=puFcf7-f9qR3HKWaRnBVgtpHZUiVFCo3MsGxx2nCQVQ,3241
|
25
|
+
piccolo/apps/asgi/commands/templates/app/_fastapi_app.py.jinja,sha256=NjKzww8-hvqVXdaXdjEF4kTm3tM2huOHUQRra_2LFJU,3355
|
26
26
|
piccolo/apps/asgi/commands/templates/app/_lilya_app.py.jinja,sha256=PUph5Jj_AXVpxXZmpUzzHXogUchU8vjKBL_7WvgrfCU,1260
|
27
|
-
piccolo/apps/asgi/commands/templates/app/_litestar_app.py.jinja,sha256=
|
28
|
-
piccolo/apps/asgi/commands/templates/app/_quart_app.py.jinja,sha256=
|
29
|
-
piccolo/apps/asgi/commands/templates/app/_sanic_app.py.jinja,sha256=
|
27
|
+
piccolo/apps/asgi/commands/templates/app/_litestar_app.py.jinja,sha256=dFcVfO150uj9OfdJ-3-MVZ-3RCoLIp9AOFdn1qSQzbE,3872
|
28
|
+
piccolo/apps/asgi/commands/templates/app/_quart_app.py.jinja,sha256=4CACs2sjHhDF3TpxM232F6hq744WD-ue8hxFMAUd45E,3468
|
29
|
+
piccolo/apps/asgi/commands/templates/app/_sanic_app.py.jinja,sha256=voq09eUymx4o7pMS7eoXlSrJYR8LY-HLW5Ufi4Utc2w,3781
|
30
30
|
piccolo/apps/asgi/commands/templates/app/_starlette_app.py.jinja,sha256=vHcAzsS9I3OevYoznwZp8zucI4OEyUjj-EOAtscmlSE,1443
|
31
31
|
piccolo/apps/asgi/commands/templates/app/app.py.jinja,sha256=n2KriWxCnq65vdEvX1USTqZPDbNkYXQqTJT5EmespT8,667
|
32
32
|
piccolo/apps/asgi/commands/templates/app/conftest.py.jinja,sha256=ZG1pRVMv3LhIfOsO3_08c_fF3EV4_EApuDHiIFFPJdk,497
|
@@ -83,7 +83,7 @@ piccolo/apps/migrations/commands/templates/migration.py.jinja,sha256=wMC8RTIcQj3
|
|
83
83
|
piccolo/apps/playground/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
84
84
|
piccolo/apps/playground/piccolo_app.py,sha256=zs6nGxt-lgUF8nEwI0uDTNZDKQqjZaNDH8le5RqrMNE,222
|
85
85
|
piccolo/apps/playground/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
86
|
-
piccolo/apps/playground/commands/run.py,sha256=
|
86
|
+
piccolo/apps/playground/commands/run.py,sha256=TOAHIEGwEB09ufoZvDztO8osSRzU6lE96tr2u9BxmWM,10811
|
87
87
|
piccolo/apps/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
88
88
|
piccolo/apps/project/piccolo_app.py,sha256=mT3O0m3QcCfS0oOr3jt0QZ9TX6gUavGPjJeNn2C_fdM,220
|
89
89
|
piccolo/apps/project/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -123,7 +123,7 @@ piccolo/apps/user/piccolo_migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeu
|
|
123
123
|
piccolo/columns/__init__.py,sha256=OYhO_n9anMiU9nL-K6ATq9FhAtm8RyMpqYQ7fTVbhxI,1120
|
124
124
|
piccolo/columns/base.py,sha256=66hsxdiPJQiJ-v0TRSwxUYx3Cbw4BUp84jr6EFaDoOc,33632
|
125
125
|
piccolo/columns/choices.py,sha256=ij5cMmslGr0WcFjcFelhdECX1E3n3R7Kl2Tn5bhu_Lc,725
|
126
|
-
piccolo/columns/column_types.py,sha256=
|
126
|
+
piccolo/columns/column_types.py,sha256=6Yg6F61u7VtAVchrokSO5Y5qYLR6FmPJ1ZBWzx27t7c,88251
|
127
127
|
piccolo/columns/combination.py,sha256=lTxbrmUCrk_mVsvBPSEV7v72_dPjMs-Y8-MmAJFAifY,7088
|
128
128
|
piccolo/columns/indexes.py,sha256=NfNok3v_791jgDlN28KmhP9ZCjl6031BXmjxV3ovXJk,372
|
129
129
|
piccolo/columns/m2m.py,sha256=FfMS9oBZSrFwHsWxp8lJDj4JD0ukphYa3RPyJDKYyLY,14587
|
@@ -183,8 +183,8 @@ piccolo/query/methods/update.py,sha256=sRSoHU3SMSQQUbScSam8M4lin0RTBA6LrGQA-d4HB
|
|
183
183
|
piccolo/query/operators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
184
184
|
piccolo/query/operators/json.py,sha256=GDLUrMDuHe6XKuzCmvYmkIUUqpQcM-8KMz-peSCLiX4,3182
|
185
185
|
piccolo/testing/__init__.py,sha256=pRFSqRInfx95AakOq54atmvqoB-ue073q2aR8u8zR40,83
|
186
|
-
piccolo/testing/model_builder.py,sha256=
|
187
|
-
piccolo/testing/random_builder.py,sha256=
|
186
|
+
piccolo/testing/model_builder.py,sha256=6JTL8CSpNTwF29wAzU6GEG33pp8tLk8viqRNfNLhu1s,6623
|
187
|
+
piccolo/testing/random_builder.py,sha256=N_aY1SDBDP6YHGAmYIw-mjTCCwbqt9fPBKW-V0KZ_-c,2650
|
188
188
|
piccolo/testing/test_case.py,sha256=VdC-1uclubtePTuxNQ-KOTF5ODaBdwzLbPuiYI5MD48,3280
|
189
189
|
piccolo/utils/__init__.py,sha256=SDFFraauI9Op8dCRkreQv1dwUcab8Mi1eC-n0EwlTy8,36
|
190
190
|
piccolo/utils/dictionary.py,sha256=mhyyhWwxTSxZcEUntgeQKsbrXD3f_KLdwa0NPzgI11k,1878
|
@@ -201,7 +201,7 @@ piccolo/utils/sync.py,sha256=oLBVx7K-KhxIOT9wRTAcfixQPMfMJTcnvlmBQM7lAzg,963
|
|
201
201
|
piccolo/utils/warnings.py,sha256=W00-Qb8s2bTc9Xk4g4E5Xqp_aBQROVfFEh-RVSozwZg,1226
|
202
202
|
piccolo/utils/graphlib/__init__.py,sha256=SUJ5Yh7LiRun3nkBuLUSVmGNHF6fANrxSoYan0mtYB0,200
|
203
203
|
piccolo/utils/graphlib/_graphlib.py,sha256=9FNGDSmTIEAk86FktniCe_J2yXjSE_sRZHDBAJJAUOw,9677
|
204
|
-
piccolo-1.
|
204
|
+
piccolo-1.29.0.dist-info/licenses/LICENSE,sha256=zFIpi-16uIJ420UMIG75NU0JbDBykvrdnXcj5U_EYBI,1059
|
205
205
|
profiling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
206
206
|
profiling/run_profile.py,sha256=264qsSFu93NTpExePnKQ9GkcN5fiuRBQ72WOSt0ZHck,829
|
207
207
|
tests/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -285,7 +285,7 @@ tests/columns/test_timestamptz.py,sha256=P7zblPC6Fjjdk6iOhVUGIKnFFzbbUPVNSY98qbu
|
|
285
285
|
tests/columns/test_uuid.py,sha256=taFYNvRZjQztMPbTQHYtwQutvcLnKPt6_aUxsf2o04Q,372
|
286
286
|
tests/columns/test_varchar.py,sha256=fbwBdimHoGaylfrqkFIgQ5m2q80umSoUNHIwofM6j_c,721
|
287
287
|
tests/columns/m2m/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
288
|
-
tests/columns/m2m/base.py,sha256=
|
288
|
+
tests/columns/m2m/base.py,sha256=_EB5j2jFnSYgvGDT_skdvvZL-L5kcQ6CZCDqpSEGVjY,14067
|
289
289
|
tests/columns/m2m/test_m2m.py,sha256=0ObmIHUJF6CZoNBznc5xXVr5_BbGBqOmWwtpg8IcPt4,13055
|
290
290
|
tests/columns/m2m/test_m2m_schema.py,sha256=oxu7eAjFFpDjnq9Eq-5OTNmlnsEIMFWx18OItfpVs-s,339
|
291
291
|
tests/conf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -346,7 +346,7 @@ tests/table/test_inheritance.py,sha256=AAkhEhhixVGweGe7ckzj-yypW-cj6D88Cca4-pjkw
|
|
346
346
|
tests/table/test_insert.py,sha256=c7hJ1SsTiW43l_Z5KHSN3894ICzttOAsTfWN9rUOl0k,13696
|
347
347
|
tests/table/test_join.py,sha256=Ukgvjc8NweBGHM7fVFytGQYG9P9thRaMeEvWXYs2Qes,15910
|
348
348
|
tests/table/test_join_on.py,sha256=cdAV39JwHi0kIas2p9cw7mcsUv6mKLZD--_SUA0zLfI,2771
|
349
|
-
tests/table/test_metaclass.py,sha256=
|
349
|
+
tests/table/test_metaclass.py,sha256=zIlUj0QfspHwnM3jb1DL_-7KTImBkHhjsJuShAvnuT8,4286
|
350
350
|
tests/table/test_objects.py,sha256=ptbeIICOfZ2-Fl6K_Llo1SKIyQ5ngUZ-rZtgll5cMWM,9047
|
351
351
|
tests/table/test_output.py,sha256=ZnpPbgVp79JcB6E_ooWQxOpOlhkwNUlMxC-1LSIEc2Y,4304
|
352
352
|
tests/table/test_raw.py,sha256=9PTvYngQi41nYd5lKzkJdTqsEcwrdOXcvZjq-W26CwQ,1683
|
@@ -354,9 +354,9 @@ tests/table/test_ref.py,sha256=eYNRnYHzNMXuMbV3B1ca5EidpIg4500q6hr1ccuVaso,269
|
|
354
354
|
tests/table/test_refresh.py,sha256=yn36LV6wXuY6YuIutLgHFE4hl-LIRuWqwCY4WB-wzJg,9253
|
355
355
|
tests/table/test_repr.py,sha256=uahz3_GffGQrf2mDE-4-Pu4AmSLBAyso6-9rbohCl58,446
|
356
356
|
tests/table/test_select.py,sha256=C-6S9HIZxMQ9cKWmmG8yDXPR37btdt6AUoZDbvcTYJs,43017
|
357
|
-
tests/table/test_str.py,sha256=
|
357
|
+
tests/table/test_str.py,sha256=QCmx9Xc-pUXfAtXz9mPzMfW_WCajjydgz_YT1cYsgvY,1528
|
358
358
|
tests/table/test_table_exists.py,sha256=upv2e9UD32V2QZOShzmcw0reMqRbYiX_jxWx57p25jg,1082
|
359
|
-
tests/table/test_update.py,sha256=
|
359
|
+
tests/table/test_update.py,sha256=M950plqKFYtew_4fqx91E0tIrwQL3zZeZh2CmvGy9yw,20979
|
360
360
|
tests/table/test_update_self.py,sha256=im6HcM-WLkEhZP0vTL42tYEJZyAZG6gDOxCnbikCBD4,907
|
361
361
|
tests/table/instance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
362
362
|
tests/table/instance/test_create.py,sha256=JD0l7L9dDK1FKPhUs6WC_B2bruPR1qQ8aIqXpEbfiUg,1105
|
@@ -368,7 +368,7 @@ tests/table/instance/test_save.py,sha256=ccdDz-bR3aYDa16_RGQP7JTXprgm1mT6-NpF1y3
|
|
368
368
|
tests/table/instance/test_to_dict.py,sha256=gkiYkmcI5qcy5E-ERWWmO-Q8uyVSFfcpJ8d53LlzCuI,3442
|
369
369
|
tests/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
370
370
|
tests/testing/test_model_builder.py,sha256=S0rT7IAmXfrQ6vRQxmkleTrAmsO5fi-tw0SF0l4jBLw,6185
|
371
|
-
tests/testing/test_random_builder.py,sha256=
|
371
|
+
tests/testing/test_random_builder.py,sha256=x2XOY2IAdIiC_hWWJ4iffLRiWOdn4CMvjiseeVvEYC8,1888
|
372
372
|
tests/testing/test_test_case.py,sha256=qyDWYT44EZNyuWhaZXgSOpX48RaRw5u4FgNi87FYt2k,1691
|
373
373
|
tests/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
374
374
|
tests/utils/test_dictionary.py,sha256=GdWujlYQy6t09p2aQHPibkkPNbBYwkFwomKrVnztJTo,1480
|
@@ -377,13 +377,13 @@ tests/utils/test_lazy_loader.py,sha256=wDWhlV2IR6RuTaYCI5eWesz465WqIscYEJjwWnPrh
|
|
377
377
|
tests/utils/test_list.py,sha256=25UoStmrYS_JDOKsXYqTDc3FUkOe3dUcy51r0I6grK0,769
|
378
378
|
tests/utils/test_naming.py,sha256=ncJdzkMHSVFo2YQLkRhY93WJ8_W_j2pW9tHHL_ZgQcs,661
|
379
379
|
tests/utils/test_printing.py,sha256=W8pQyWX2pEkLdMYWxtibFXJnI4MVsb6XMOTo3DZUuZc,668
|
380
|
-
tests/utils/test_pydantic.py,sha256=
|
380
|
+
tests/utils/test_pydantic.py,sha256=xjob1PgQphzbSdLQNNkzzZ5XUDdUpC4HAiEj1kHO4tw,27881
|
381
381
|
tests/utils/test_sql_values.py,sha256=vzxRmy16FfLZPH-sAQexBvsF9MXB8n4smr14qoEOS5E,2535
|
382
382
|
tests/utils/test_sync.py,sha256=9ytVo56y2vPQePvTeIi9lHIouEhWJbodl1TmzkGFrSo,799
|
383
383
|
tests/utils/test_table_reflection.py,sha256=bIlwIupyD6XLupf7KYZ1le4EPdft7Jp2ofwF2PHqn60,3771
|
384
384
|
tests/utils/test_warnings.py,sha256=NvSC_cvJ6uZcwAGf1m-hLzETXCqprXELL8zg3TNLVMw,269
|
385
|
-
piccolo-1.
|
386
|
-
piccolo-1.
|
387
|
-
piccolo-1.
|
388
|
-
piccolo-1.
|
389
|
-
piccolo-1.
|
385
|
+
piccolo-1.29.0.dist-info/METADATA,sha256=KgAnQBJETmXrcDB97hFPLSdD08sjQymkUifFBakE56Y,5531
|
386
|
+
piccolo-1.29.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
387
|
+
piccolo-1.29.0.dist-info/entry_points.txt,sha256=SJPHET4Fi1bN5F3WqcKkv9SClK3_F1I7m4eQjk6AFh0,46
|
388
|
+
piccolo-1.29.0.dist-info/top_level.txt,sha256=-SR74VGbk43VoPy1HH-mHm97yoGukLK87HE5kdBW6qM,24
|
389
|
+
piccolo-1.29.0.dist-info/RECORD,,
|
tests/columns/m2m/base.py
CHANGED
@@ -11,7 +11,7 @@ from piccolo.columns.m2m import M2M
|
|
11
11
|
from piccolo.engine.finder import engine_finder
|
12
12
|
from piccolo.schema import SchemaManager
|
13
13
|
from piccolo.table import Table, create_db_tables_sync, drop_db_tables_sync
|
14
|
-
from tests.base import
|
14
|
+
from tests.base import engines_skip
|
15
15
|
|
16
16
|
engine = engine_finder()
|
17
17
|
|
@@ -51,54 +51,25 @@ class M2MBase:
|
|
51
51
|
|
52
52
|
create_db_tables_sync(*self.all_tables, if_not_exists=True)
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
Band(name="C-Sharps"),
|
60
|
-
)
|
61
|
-
.returning(Band.id)
|
62
|
-
.run_sync()
|
63
|
-
)
|
64
|
-
|
65
|
-
genres = (
|
66
|
-
Genre.insert(
|
67
|
-
Genre(name="Rock"),
|
68
|
-
Genre(name="Folk"),
|
69
|
-
Genre(name="Classical"),
|
70
|
-
)
|
71
|
-
.returning(Genre.id)
|
72
|
-
.run_sync()
|
73
|
-
)
|
74
|
-
|
75
|
-
GenreToBand.insert(
|
76
|
-
GenreToBand(band=bands[0]["id"], genre=genres[0]["id"]),
|
77
|
-
GenreToBand(band=bands[0]["id"], genre=genres[1]["id"]),
|
78
|
-
GenreToBand(band=bands[1]["id"], genre=genres[1]["id"]),
|
79
|
-
GenreToBand(band=bands[2]["id"], genre=genres[0]["id"]),
|
80
|
-
GenreToBand(band=bands[2]["id"], genre=genres[2]["id"]),
|
81
|
-
).run_sync()
|
82
|
-
else:
|
83
|
-
Band.insert(
|
84
|
-
Band(name="Pythonistas"),
|
85
|
-
Band(name="Rustaceans"),
|
86
|
-
Band(name="C-Sharps"),
|
87
|
-
).run_sync()
|
54
|
+
bands = Band.insert(
|
55
|
+
Band(name="Pythonistas"),
|
56
|
+
Band(name="Rustaceans"),
|
57
|
+
Band(name="C-Sharps"),
|
58
|
+
).run_sync()
|
88
59
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
60
|
+
genres = Genre.insert(
|
61
|
+
Genre(name="Rock"),
|
62
|
+
Genre(name="Folk"),
|
63
|
+
Genre(name="Classical"),
|
64
|
+
).run_sync()
|
94
65
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
66
|
+
GenreToBand.insert(
|
67
|
+
GenreToBand(band=bands[0]["id"], genre=genres[0]["id"]),
|
68
|
+
GenreToBand(band=bands[0]["id"], genre=genres[1]["id"]),
|
69
|
+
GenreToBand(band=bands[1]["id"], genre=genres[1]["id"]),
|
70
|
+
GenreToBand(band=bands[2]["id"], genre=genres[0]["id"]),
|
71
|
+
GenreToBand(band=bands[2]["id"], genre=genres[2]["id"]),
|
72
|
+
).run_sync()
|
102
73
|
|
103
74
|
def tearDown(self):
|
104
75
|
drop_db_tables_sync(*self.all_tables)
|
tests/table/test_metaclass.py
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
from unittest import TestCase
|
2
2
|
from unittest.mock import MagicMock, patch
|
3
3
|
|
4
|
-
from piccolo.columns import Secret
|
5
4
|
from piccolo.columns.column_types import (
|
6
5
|
JSON,
|
7
6
|
JSONB,
|
8
7
|
Array,
|
9
8
|
Email,
|
10
9
|
ForeignKey,
|
10
|
+
Secret,
|
11
11
|
Varchar,
|
12
12
|
)
|
13
13
|
from piccolo.table import TABLENAME_WARNING, Table
|
@@ -99,14 +99,18 @@ class TestMetaClass(TestCase):
|
|
99
99
|
|
100
100
|
def test_secret_columns(self):
|
101
101
|
"""
|
102
|
-
Make sure TableMeta.secret_columns are setup correctly
|
102
|
+
Make sure TableMeta.secret_columns are setup correctly with the
|
103
|
+
``secret=True`` argument and ``Secret`` column type.
|
103
104
|
"""
|
104
105
|
|
105
106
|
class Classified(Table):
|
106
107
|
top_secret = Secret()
|
108
|
+
confidential = Varchar(secret=True)
|
109
|
+
public = Varchar()
|
107
110
|
|
108
111
|
self.assertEqual(
|
109
|
-
Classified._meta.secret_columns,
|
112
|
+
Classified._meta.secret_columns,
|
113
|
+
[Classified.top_secret, Classified.confidential],
|
110
114
|
)
|
111
115
|
|
112
116
|
def test_json_columns(self):
|
tests/table/test_str.py
CHANGED
@@ -1,30 +1,20 @@
|
|
1
1
|
from unittest import TestCase
|
2
2
|
|
3
|
-
from
|
4
|
-
from tests.example_apps.music.tables import Manager
|
3
|
+
from piccolo.apps.playground.commands.run import Genre, Manager
|
5
4
|
|
6
5
|
|
7
6
|
class TestTableStr(TestCase):
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
(
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
)
|
18
|
-
else:
|
19
|
-
self.assertEqual(
|
20
|
-
Manager._table_str(),
|
21
|
-
(
|
22
|
-
"class Manager(Table, tablename='manager'):\n"
|
23
|
-
" id = Serial(null=False, primary_key=True, unique=False, index=False, index_method=IndexMethod.btree, choices=None, db_column_name='id', secret=False)\n" # noqa: E501
|
24
|
-
" name = Varchar(length=50, default='', null=False, primary_key=False, unique=False, index=False, index_method=IndexMethod.btree, choices=None, db_column_name=None, secret=False)\n" # noqa: E501
|
25
|
-
),
|
26
|
-
)
|
7
|
+
def test_all_attributes(self):
|
8
|
+
self.assertEqual(
|
9
|
+
Manager._table_str(),
|
10
|
+
(
|
11
|
+
"class Manager(Table, tablename='manager'):\n"
|
12
|
+
" id = Serial(null=False, primary_key=True, unique=False, index=False, index_method=IndexMethod.btree, choices=None, db_column_name='id', secret=False)\n" # noqa: E501
|
13
|
+
" name = Varchar(length=50, default='', null=False, primary_key=False, unique=False, index=False, index_method=IndexMethod.btree, choices=None, db_column_name=None, secret=False)\n" # noqa: E501
|
14
|
+
),
|
15
|
+
)
|
27
16
|
|
17
|
+
def test_abbreviated(self):
|
28
18
|
self.assertEqual(
|
29
19
|
Manager._table_str(abbreviated=True),
|
30
20
|
(
|
@@ -34,5 +24,23 @@ class TestTableStr(TestCase):
|
|
34
24
|
),
|
35
25
|
)
|
36
26
|
|
37
|
-
|
27
|
+
def test_m2m(self):
|
28
|
+
"""
|
29
|
+
Make sure M2M relationships appear in the Table string.
|
30
|
+
"""
|
31
|
+
|
32
|
+
self.assertEqual(
|
33
|
+
Genre._table_str(abbreviated=True),
|
34
|
+
(
|
35
|
+
"class Genre(Table):\n"
|
36
|
+
" id = Serial()\n"
|
37
|
+
" name = Varchar()\n"
|
38
|
+
" bands = M2M(GenreToBand)\n"
|
39
|
+
),
|
40
|
+
)
|
41
|
+
|
42
|
+
def test_print(self):
|
43
|
+
"""
|
44
|
+
Make sure we can print it directly without any errors.
|
45
|
+
"""
|
38
46
|
print(Manager)
|
tests/table/test_update.py
CHANGED
@@ -158,6 +158,7 @@ class TestUpdate(DBTestCase):
|
|
158
158
|
|
159
159
|
class MyTable(Table):
|
160
160
|
integer = Integer(null=True)
|
161
|
+
other_integer = Integer(null=True, default=5)
|
161
162
|
timestamp = Timestamp(null=True)
|
162
163
|
timestamptz = Timestamptz(null=True)
|
163
164
|
date = Date(null=True)
|
@@ -295,6 +296,20 @@ TEST_CASES = [
|
|
295
296
|
querystring=2000 - MyTable.integer,
|
296
297
|
expected=1000,
|
297
298
|
),
|
299
|
+
OperatorTestCase(
|
300
|
+
description="Subtract Integer Columns",
|
301
|
+
column=MyTable.integer,
|
302
|
+
initial=1000,
|
303
|
+
querystring=MyTable.integer - MyTable.other_integer,
|
304
|
+
expected=995,
|
305
|
+
),
|
306
|
+
OperatorTestCase(
|
307
|
+
description="Add Integer Columns",
|
308
|
+
column=MyTable.integer,
|
309
|
+
initial=1000,
|
310
|
+
querystring=MyTable.integer + MyTable.other_integer,
|
311
|
+
expected=1005,
|
312
|
+
),
|
298
313
|
OperatorTestCase(
|
299
314
|
description="Multiply Integer",
|
300
315
|
column=MyTable.integer,
|