piccolo 1.27.1__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/app/commands/new.py +3 -3
- piccolo/apps/asgi/commands/new.py +2 -3
- 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/fixtures/commands/dump.py +8 -8
- piccolo/apps/fixtures/commands/load.py +5 -5
- piccolo/apps/fixtures/commands/shared.py +9 -9
- piccolo/apps/migrations/auto/diffable_table.py +12 -12
- piccolo/apps/migrations/auto/migration_manager.py +59 -66
- piccolo/apps/migrations/auto/operations.py +14 -14
- piccolo/apps/migrations/auto/schema_differ.py +35 -34
- piccolo/apps/migrations/auto/schema_snapshot.py +3 -4
- piccolo/apps/migrations/auto/serialisation.py +27 -24
- piccolo/apps/migrations/auto/serialisation_legacy.py +2 -2
- piccolo/apps/migrations/commands/backwards.py +1 -2
- piccolo/apps/migrations/commands/base.py +12 -12
- piccolo/apps/migrations/commands/check.py +2 -3
- piccolo/apps/migrations/commands/clean.py +3 -3
- piccolo/apps/migrations/commands/forwards.py +1 -2
- piccolo/apps/migrations/commands/new.py +6 -6
- piccolo/apps/migrations/tables.py +3 -3
- piccolo/apps/playground/commands/run.py +72 -13
- piccolo/apps/schema/commands/generate.py +49 -49
- piccolo/apps/schema/commands/graph.py +5 -5
- piccolo/apps/shell/commands/run.py +1 -2
- piccolo/apps/sql_shell/commands/run.py +4 -4
- piccolo/apps/tester/commands/run.py +3 -3
- piccolo/apps/user/commands/change_permissions.py +6 -6
- piccolo/apps/user/commands/create.py +7 -7
- piccolo/apps/user/commands/list.py +2 -2
- piccolo/apps/user/tables.py +8 -8
- piccolo/columns/base.py +84 -52
- piccolo/columns/choices.py +2 -2
- piccolo/columns/column_types.py +299 -177
- piccolo/columns/combination.py +15 -12
- piccolo/columns/defaults/base.py +4 -4
- piccolo/columns/defaults/date.py +4 -3
- piccolo/columns/defaults/interval.py +4 -3
- piccolo/columns/defaults/time.py +4 -3
- piccolo/columns/defaults/timestamp.py +4 -3
- piccolo/columns/defaults/timestamptz.py +4 -3
- piccolo/columns/defaults/uuid.py +3 -2
- piccolo/columns/m2m.py +28 -35
- piccolo/columns/readable.py +4 -3
- piccolo/columns/reference.py +9 -9
- piccolo/conf/apps.py +53 -54
- piccolo/custom_types.py +28 -6
- piccolo/engine/base.py +14 -14
- piccolo/engine/cockroach.py +5 -4
- piccolo/engine/finder.py +2 -2
- piccolo/engine/postgres.py +20 -19
- piccolo/engine/sqlite.py +23 -22
- piccolo/query/base.py +30 -29
- piccolo/query/functions/__init__.py +12 -0
- piccolo/query/functions/aggregate.py +4 -3
- piccolo/query/functions/array.py +151 -0
- piccolo/query/functions/base.py +3 -3
- piccolo/query/functions/datetime.py +22 -22
- piccolo/query/functions/string.py +4 -4
- piccolo/query/functions/type_conversion.py +30 -15
- piccolo/query/methods/alter.py +47 -46
- piccolo/query/methods/count.py +11 -10
- piccolo/query/methods/create.py +6 -5
- piccolo/query/methods/create_index.py +9 -8
- piccolo/query/methods/delete.py +7 -6
- piccolo/query/methods/drop_index.py +7 -6
- piccolo/query/methods/exists.py +6 -5
- piccolo/query/methods/indexes.py +4 -4
- piccolo/query/methods/insert.py +21 -14
- piccolo/query/methods/objects.py +60 -50
- piccolo/query/methods/raw.py +7 -6
- piccolo/query/methods/refresh.py +8 -7
- piccolo/query/methods/select.py +56 -49
- piccolo/query/methods/table_exists.py +5 -5
- piccolo/query/methods/update.py +8 -7
- piccolo/query/mixins.py +56 -61
- piccolo/query/operators/json.py +11 -11
- piccolo/query/proxy.py +8 -9
- piccolo/querystring.py +14 -15
- piccolo/schema.py +10 -10
- piccolo/table.py +105 -98
- piccolo/table_reflection.py +9 -9
- piccolo/testing/model_builder.py +16 -13
- piccolo/testing/random_builder.py +14 -2
- piccolo/testing/test_case.py +4 -4
- piccolo/utils/dictionary.py +3 -3
- piccolo/utils/encoding.py +5 -5
- piccolo/utils/lazy_loader.py +3 -3
- piccolo/utils/list.py +7 -8
- piccolo/utils/objects.py +4 -6
- piccolo/utils/pydantic.py +21 -24
- piccolo/utils/sql_values.py +3 -3
- piccolo/utils/sync.py +4 -3
- piccolo/utils/warnings.py +1 -2
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/METADATA +1 -1
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/RECORD +132 -131
- tests/apps/fixtures/commands/test_dump_load.py +1 -2
- tests/apps/migrations/auto/integration/test_migrations.py +32 -7
- tests/apps/migrations/auto/test_migration_manager.py +2 -2
- tests/apps/migrations/auto/test_schema_differ.py +22 -23
- tests/apps/migrations/commands/test_forwards_backwards.py +3 -3
- tests/columns/m2m/base.py +20 -49
- tests/columns/test_array.py +176 -10
- tests/columns/test_boolean.py +2 -4
- tests/columns/test_combination.py +29 -1
- tests/columns/test_db_column_name.py +2 -2
- tests/engine/test_extra_nodes.py +2 -2
- tests/engine/test_pool.py +3 -3
- tests/engine/test_transaction.py +4 -4
- tests/query/test_freeze.py +4 -4
- tests/table/instance/test_get_related.py +2 -2
- tests/table/test_alter.py +4 -4
- tests/table/test_indexes.py +1 -2
- tests/table/test_metaclass.py +7 -3
- tests/table/test_refresh.py +2 -2
- tests/table/test_select.py +58 -0
- tests/table/test_str.py +30 -22
- tests/table/test_update.py +18 -3
- tests/testing/test_model_builder.py +1 -2
- tests/testing/test_random_builder.py +5 -0
- tests/utils/test_pydantic.py +152 -134
- tests/utils/test_table_reflection.py +1 -2
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/WHEEL +0 -0
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/entry_points.txt +0 -0
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/licenses/LICENSE +0 -0
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/top_level.txt +0 -0
@@ -1,20 +1,21 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
|
3
|
+
from collections.abc import Sequence
|
4
|
+
from typing import TYPE_CHECKING, Union
|
4
5
|
|
5
6
|
from piccolo.columns.base import Column
|
6
7
|
from piccolo.query.base import Query
|
7
8
|
from piccolo.querystring import QueryString
|
8
9
|
|
9
|
-
if
|
10
|
+
if TYPE_CHECKING: # pragma: no cover
|
10
11
|
from piccolo.table import Table
|
11
12
|
|
12
13
|
|
13
14
|
class DropIndex(Query):
|
14
15
|
def __init__(
|
15
16
|
self,
|
16
|
-
table:
|
17
|
-
columns:
|
17
|
+
table: type[Table],
|
18
|
+
columns: Union[list[Column], list[str]],
|
18
19
|
if_exists: bool = True,
|
19
20
|
**kwargs,
|
20
21
|
):
|
@@ -23,13 +24,13 @@ class DropIndex(Query):
|
|
23
24
|
super().__init__(table, **kwargs)
|
24
25
|
|
25
26
|
@property
|
26
|
-
def column_names(self) ->
|
27
|
+
def column_names(self) -> list[str]:
|
27
28
|
return [
|
28
29
|
i._meta.name if isinstance(i, Column) else i for i in self.columns
|
29
30
|
]
|
30
31
|
|
31
32
|
@property
|
32
|
-
def default_querystrings(self) ->
|
33
|
+
def default_querystrings(self) -> Sequence[QueryString]:
|
33
34
|
column_names = self.column_names
|
34
35
|
index_name = self.table._get_index_name(column_names)
|
35
36
|
query = "DROP INDEX"
|
piccolo/query/methods/exists.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
|
3
|
+
from collections.abc import Sequence
|
4
|
+
from typing import TypeVar, Union
|
4
5
|
|
5
6
|
from piccolo.custom_types import Combinable, TableInstance
|
6
7
|
from piccolo.query.base import Query
|
@@ -12,11 +13,11 @@ from piccolo.querystring import QueryString
|
|
12
13
|
class Exists(Query[TableInstance, bool]):
|
13
14
|
__slots__ = ("where_delegate",)
|
14
15
|
|
15
|
-
def __init__(self, table:
|
16
|
+
def __init__(self, table: type[TableInstance], **kwargs):
|
16
17
|
super().__init__(table, **kwargs)
|
17
18
|
self.where_delegate = WhereDelegate()
|
18
19
|
|
19
|
-
def where(self: Self, *where:
|
20
|
+
def where(self: Self, *where: Union[Combinable, QueryString]) -> Self:
|
20
21
|
self.where_delegate.where(*where)
|
21
22
|
return self
|
22
23
|
|
@@ -25,7 +26,7 @@ class Exists(Query[TableInstance, bool]):
|
|
25
26
|
return bool(response[0]["exists"])
|
26
27
|
|
27
28
|
@property
|
28
|
-
def default_querystrings(self) ->
|
29
|
+
def default_querystrings(self) -> Sequence[QueryString]:
|
29
30
|
select = Select(table=self.table)
|
30
31
|
select.where_delegate._where = self.where_delegate._where
|
31
32
|
return [
|
@@ -35,4 +36,4 @@ class Exists(Query[TableInstance, bool]):
|
|
35
36
|
]
|
36
37
|
|
37
38
|
|
38
|
-
Self =
|
39
|
+
Self = TypeVar("Self", bound=Exists)
|
piccolo/query/methods/indexes.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
|
3
|
+
from collections.abc import Sequence
|
4
4
|
|
5
5
|
from piccolo.query.base import Query
|
6
6
|
from piccolo.querystring import QueryString
|
@@ -12,7 +12,7 @@ class Indexes(Query):
|
|
12
12
|
"""
|
13
13
|
|
14
14
|
@property
|
15
|
-
def postgres_querystrings(self) ->
|
15
|
+
def postgres_querystrings(self) -> Sequence[QueryString]:
|
16
16
|
return [
|
17
17
|
QueryString(
|
18
18
|
"SELECT indexname AS name FROM pg_indexes "
|
@@ -22,11 +22,11 @@ class Indexes(Query):
|
|
22
22
|
]
|
23
23
|
|
24
24
|
@property
|
25
|
-
def cockroach_querystrings(self) ->
|
25
|
+
def cockroach_querystrings(self) -> Sequence[QueryString]:
|
26
26
|
return self.postgres_querystrings
|
27
27
|
|
28
28
|
@property
|
29
|
-
def sqlite_querystrings(self) ->
|
29
|
+
def sqlite_querystrings(self) -> Sequence[QueryString]:
|
30
30
|
tablename = self.table._meta.tablename
|
31
31
|
return [QueryString(f"PRAGMA index_list({tablename})")]
|
32
32
|
|
piccolo/query/methods/insert.py
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
|
3
|
+
from collections.abc import Sequence
|
4
|
+
from typing import (
|
5
|
+
TYPE_CHECKING,
|
6
|
+
Any,
|
7
|
+
Generic,
|
8
|
+
Literal,
|
9
|
+
Optional,
|
10
|
+
TypeVar,
|
11
|
+
Union,
|
12
|
+
)
|
4
13
|
|
5
14
|
from piccolo.custom_types import Combinable, TableInstance
|
6
15
|
from piccolo.query.base import Query
|
@@ -12,18 +21,18 @@ from piccolo.query.mixins import (
|
|
12
21
|
)
|
13
22
|
from piccolo.querystring import QueryString
|
14
23
|
|
15
|
-
if
|
24
|
+
if TYPE_CHECKING: # pragma: no cover
|
16
25
|
from piccolo.columns.base import Column
|
17
26
|
from piccolo.table import Table
|
18
27
|
|
19
28
|
|
20
29
|
class Insert(
|
21
|
-
|
30
|
+
Generic[TableInstance], Query[TableInstance, list[dict[str, Any]]]
|
22
31
|
):
|
23
32
|
__slots__ = ("add_delegate", "on_conflict_delegate", "returning_delegate")
|
24
33
|
|
25
34
|
def __init__(
|
26
|
-
self, table:
|
35
|
+
self, table: type[TableInstance], *instances: TableInstance, **kwargs
|
27
36
|
):
|
28
37
|
super().__init__(table, **kwargs)
|
29
38
|
self.add_delegate = AddDelegate()
|
@@ -44,14 +53,12 @@ class Insert(
|
|
44
53
|
|
45
54
|
def on_conflict(
|
46
55
|
self: Self,
|
47
|
-
target:
|
48
|
-
action:
|
49
|
-
OnConflictAction,
|
56
|
+
target: Optional[Union[str, Column, tuple[Column, ...]]] = None,
|
57
|
+
action: Union[
|
58
|
+
OnConflictAction, Literal["DO NOTHING", "DO UPDATE"]
|
50
59
|
] = OnConflictAction.do_nothing,
|
51
|
-
values:
|
52
|
-
|
53
|
-
] = None,
|
54
|
-
where: t.Optional[Combinable] = None,
|
60
|
+
values: Optional[Sequence[Union[Column, tuple[Column, Any]]]] = None,
|
61
|
+
where: Optional[Combinable] = None,
|
55
62
|
) -> Self:
|
56
63
|
if (
|
57
64
|
self.engine_type == "sqlite"
|
@@ -81,7 +88,7 @@ class Insert(
|
|
81
88
|
|
82
89
|
###########################################################################
|
83
90
|
|
84
|
-
def _raw_response_callback(self, results:
|
91
|
+
def _raw_response_callback(self, results: list):
|
85
92
|
"""
|
86
93
|
Assign the ids of the created rows to the model instances.
|
87
94
|
"""
|
@@ -97,7 +104,7 @@ class Insert(
|
|
97
104
|
table_instance._exists_in_db = True
|
98
105
|
|
99
106
|
@property
|
100
|
-
def default_querystrings(self) ->
|
107
|
+
def default_querystrings(self) -> Sequence[QueryString]:
|
101
108
|
base = f"INSERT INTO {self.table._meta.get_formatted_tablename()}"
|
102
109
|
columns = ",".join(
|
103
110
|
f'"{i._meta.db_column_name}"' for i in self.table._meta.columns
|
@@ -142,4 +149,4 @@ class Insert(
|
|
142
149
|
return [querystring]
|
143
150
|
|
144
151
|
|
145
|
-
Self =
|
152
|
+
Self = TypeVar("Self", bound=Insert)
|
piccolo/query/methods/objects.py
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import
|
3
|
+
from collections.abc import Callable, Generator, Sequence
|
4
|
+
from typing import (
|
5
|
+
TYPE_CHECKING,
|
6
|
+
Any,
|
7
|
+
Generic,
|
8
|
+
Literal,
|
9
|
+
Optional,
|
10
|
+
TypeVar,
|
11
|
+
Union,
|
12
|
+
cast,
|
13
|
+
)
|
4
14
|
|
5
15
|
from piccolo.columns.column_types import ForeignKey, ReferencedTable
|
6
16
|
from piccolo.columns.combination import And, Where
|
@@ -27,7 +37,7 @@ from piccolo.querystring import QueryString
|
|
27
37
|
from piccolo.utils.dictionary import make_nested
|
28
38
|
from piccolo.utils.sync import run_sync
|
29
39
|
|
30
|
-
if
|
40
|
+
if TYPE_CHECKING: # pragma: no cover
|
31
41
|
from piccolo.columns import Column
|
32
42
|
from piccolo.table import Table
|
33
43
|
|
@@ -36,14 +46,14 @@ if t.TYPE_CHECKING: # pragma: no cover
|
|
36
46
|
|
37
47
|
|
38
48
|
class GetOrCreate(
|
39
|
-
Proxy["Objects[TableInstance]", TableInstance],
|
49
|
+
Proxy["Objects[TableInstance]", TableInstance], Generic[TableInstance]
|
40
50
|
):
|
41
51
|
def __init__(
|
42
52
|
self,
|
43
53
|
query: Objects[TableInstance],
|
44
|
-
table_class:
|
54
|
+
table_class: type[TableInstance],
|
45
55
|
where: Combinable,
|
46
|
-
defaults:
|
56
|
+
defaults: dict[Column, Any],
|
47
57
|
):
|
48
58
|
self.query = query
|
49
59
|
self.table_class = table_class
|
@@ -51,7 +61,7 @@ class GetOrCreate(
|
|
51
61
|
self.defaults = defaults
|
52
62
|
|
53
63
|
async def run(
|
54
|
-
self, node:
|
64
|
+
self, node: Optional[str] = None, in_pool: bool = True
|
55
65
|
) -> TableInstance:
|
56
66
|
"""
|
57
67
|
:raises ValueError:
|
@@ -100,32 +110,32 @@ class GetOrCreate(
|
|
100
110
|
.run()
|
101
111
|
)
|
102
112
|
|
103
|
-
instance =
|
113
|
+
instance = cast(TableInstance, instance)
|
104
114
|
instance._was_created = True
|
105
115
|
return instance
|
106
116
|
|
107
117
|
|
108
118
|
class Get(
|
109
|
-
Proxy["First[TableInstance]",
|
110
|
-
|
119
|
+
Proxy["First[TableInstance]", Optional[TableInstance]],
|
120
|
+
Generic[TableInstance],
|
111
121
|
):
|
112
122
|
pass
|
113
123
|
|
114
124
|
|
115
125
|
class First(
|
116
|
-
Proxy["Objects[TableInstance]",
|
117
|
-
|
126
|
+
Proxy["Objects[TableInstance]", Optional[TableInstance]],
|
127
|
+
Generic[TableInstance],
|
118
128
|
):
|
119
129
|
async def run(
|
120
|
-
self, node:
|
121
|
-
) ->
|
130
|
+
self, node: Optional[str] = None, in_pool: bool = True
|
131
|
+
) -> Optional[TableInstance]:
|
122
132
|
objects = await self.query.run(
|
123
133
|
node=node, in_pool=in_pool, use_callbacks=False
|
124
134
|
)
|
125
135
|
|
126
136
|
results = objects[0] if objects else None
|
127
137
|
|
128
|
-
modified_response:
|
138
|
+
modified_response: Optional[TableInstance] = (
|
129
139
|
await self.query.callback_delegate.invoke(
|
130
140
|
results=results, kind=CallbackType.success
|
131
141
|
)
|
@@ -133,7 +143,7 @@ class First(
|
|
133
143
|
return modified_response
|
134
144
|
|
135
145
|
|
136
|
-
class Create(
|
146
|
+
class Create(Generic[TableInstance]):
|
137
147
|
"""
|
138
148
|
This is provided as a simple convenience. Rather than running::
|
139
149
|
|
@@ -148,22 +158,22 @@ class Create(t.Generic[TableInstance]):
|
|
148
158
|
|
149
159
|
def __init__(
|
150
160
|
self,
|
151
|
-
table_class:
|
152
|
-
columns:
|
161
|
+
table_class: type[TableInstance],
|
162
|
+
columns: dict[str, Any],
|
153
163
|
):
|
154
164
|
self.table_class = table_class
|
155
165
|
self.columns = columns
|
156
166
|
|
157
167
|
async def run(
|
158
168
|
self,
|
159
|
-
node:
|
169
|
+
node: Optional[str] = None,
|
160
170
|
in_pool: bool = True,
|
161
171
|
) -> TableInstance:
|
162
172
|
instance = self.table_class(**self.columns)
|
163
173
|
await instance.save().run(node=node, in_pool=in_pool)
|
164
174
|
return instance
|
165
175
|
|
166
|
-
def __await__(self) ->
|
176
|
+
def __await__(self) -> Generator[None, None, TableInstance]:
|
167
177
|
"""
|
168
178
|
If the user doesn't explicity call .run(), proxy to it as a
|
169
179
|
convenience.
|
@@ -179,14 +189,14 @@ class UpdateSelf:
|
|
179
189
|
def __init__(
|
180
190
|
self,
|
181
191
|
row: Table,
|
182
|
-
values:
|
192
|
+
values: dict[Union[Column, str], Any],
|
183
193
|
):
|
184
194
|
self.row = row
|
185
195
|
self.values = values
|
186
196
|
|
187
197
|
async def run(
|
188
198
|
self,
|
189
|
-
node:
|
199
|
+
node: Optional[str] = None,
|
190
200
|
in_pool: bool = True,
|
191
201
|
) -> None:
|
192
202
|
if not self.row._exists_in_db:
|
@@ -218,7 +228,7 @@ class UpdateSelf:
|
|
218
228
|
for key, value in response[0].items():
|
219
229
|
setattr(self.row, key, value)
|
220
230
|
|
221
|
-
def __await__(self) ->
|
231
|
+
def __await__(self) -> Generator[None, None, None]:
|
222
232
|
"""
|
223
233
|
If the user doesn't explicity call .run(), proxy to it as a
|
224
234
|
convenience.
|
@@ -229,7 +239,7 @@ class UpdateSelf:
|
|
229
239
|
return run_sync(self.run(*args, **kwargs))
|
230
240
|
|
231
241
|
|
232
|
-
class GetRelated(
|
242
|
+
class GetRelated(Generic[ReferencedTable]):
|
233
243
|
|
234
244
|
def __init__(self, row: Table, foreign_key: ForeignKey[ReferencedTable]):
|
235
245
|
self.row = row
|
@@ -237,9 +247,9 @@ class GetRelated(t.Generic[ReferencedTable]):
|
|
237
247
|
|
238
248
|
async def run(
|
239
249
|
self,
|
240
|
-
node:
|
250
|
+
node: Optional[str] = None,
|
241
251
|
in_pool: bool = True,
|
242
|
-
) ->
|
252
|
+
) -> Optional[ReferencedTable]:
|
243
253
|
if not self.row._exists_in_db:
|
244
254
|
raise ValueError("The object doesn't exist in the database.")
|
245
255
|
|
@@ -264,8 +274,8 @@ class GetRelated(t.Generic[ReferencedTable]):
|
|
264
274
|
if data is None or not any(data.values()):
|
265
275
|
return None
|
266
276
|
|
267
|
-
references =
|
268
|
-
|
277
|
+
references = cast(
|
278
|
+
type[ReferencedTable],
|
269
279
|
self.foreign_key._foreign_key_meta.resolved_references,
|
270
280
|
)
|
271
281
|
|
@@ -275,14 +285,14 @@ class GetRelated(t.Generic[ReferencedTable]):
|
|
275
285
|
|
276
286
|
def __await__(
|
277
287
|
self,
|
278
|
-
) ->
|
288
|
+
) -> Generator[None, None, Optional[ReferencedTable]]:
|
279
289
|
"""
|
280
290
|
If the user doesn't explicity call .run(), proxy to it as a
|
281
291
|
convenience.
|
282
292
|
"""
|
283
293
|
return self.run().__await__()
|
284
294
|
|
285
|
-
def run_sync(self, *args, **kwargs) ->
|
295
|
+
def run_sync(self, *args, **kwargs) -> Optional[ReferencedTable]:
|
286
296
|
return run_sync(self.run(*args, **kwargs))
|
287
297
|
|
288
298
|
|
@@ -290,7 +300,7 @@ class GetRelated(t.Generic[ReferencedTable]):
|
|
290
300
|
|
291
301
|
|
292
302
|
class Objects(
|
293
|
-
Query[TableInstance,
|
303
|
+
Query[TableInstance, list[TableInstance]], Generic[TableInstance]
|
294
304
|
):
|
295
305
|
"""
|
296
306
|
Almost identical to select, except you have to select all fields, and
|
@@ -312,8 +322,8 @@ class Objects(
|
|
312
322
|
|
313
323
|
def __init__(
|
314
324
|
self,
|
315
|
-
table:
|
316
|
-
prefetch:
|
325
|
+
table: type[TableInstance],
|
326
|
+
prefetch: Sequence[Union[ForeignKey, list[ForeignKey]]] = (),
|
317
327
|
**kwargs,
|
318
328
|
):
|
319
329
|
super().__init__(table, **kwargs)
|
@@ -337,7 +347,7 @@ class Objects(
|
|
337
347
|
|
338
348
|
def callback(
|
339
349
|
self: Self,
|
340
|
-
callbacks:
|
350
|
+
callbacks: Union[Callable, list[Callable]],
|
341
351
|
*,
|
342
352
|
on: CallbackType = CallbackType.success,
|
343
353
|
) -> Self:
|
@@ -355,7 +365,7 @@ class Objects(
|
|
355
365
|
return self
|
356
366
|
|
357
367
|
def prefetch(
|
358
|
-
self: Self, *fk_columns:
|
368
|
+
self: Self, *fk_columns: Union[ForeignKey, list[ForeignKey]]
|
359
369
|
) -> Self:
|
360
370
|
self.prefetch_delegate.prefetch(*fk_columns)
|
361
371
|
return self
|
@@ -365,9 +375,9 @@ class Objects(
|
|
365
375
|
return self
|
366
376
|
|
367
377
|
def order_by(
|
368
|
-
self: Self, *columns:
|
378
|
+
self: Self, *columns: Union[Column, str, OrderByRaw], ascending=True
|
369
379
|
) -> Self:
|
370
|
-
_columns:
|
380
|
+
_columns: list[Union[Column, OrderByRaw]] = []
|
371
381
|
for column in columns:
|
372
382
|
if isinstance(column, str):
|
373
383
|
_columns.append(self.table._meta.get_column_by_name(column))
|
@@ -377,7 +387,7 @@ class Objects(
|
|
377
387
|
self.order_by_delegate.order_by(*_columns, ascending=ascending)
|
378
388
|
return self
|
379
389
|
|
380
|
-
def where(self: Self, *where:
|
390
|
+
def where(self: Self, *where: Union[Combinable, QueryString]) -> Self:
|
381
391
|
self.where_delegate.where(*where)
|
382
392
|
return self
|
383
393
|
|
@@ -389,9 +399,9 @@ class Objects(
|
|
389
399
|
|
390
400
|
def lock_rows(
|
391
401
|
self: Self,
|
392
|
-
lock_strength:
|
402
|
+
lock_strength: Union[
|
393
403
|
LockStrength,
|
394
|
-
|
404
|
+
Literal[
|
395
405
|
"UPDATE",
|
396
406
|
"NO KEY UPDATE",
|
397
407
|
"KEY SHARE",
|
@@ -400,7 +410,7 @@ class Objects(
|
|
400
410
|
] = LockStrength.update,
|
401
411
|
nowait: bool = False,
|
402
412
|
skip_locked: bool = False,
|
403
|
-
of:
|
413
|
+
of: tuple[type[Table], ...] = (),
|
404
414
|
) -> Self:
|
405
415
|
self.lock_rows_delegate.lock_rows(
|
406
416
|
lock_strength, nowait, skip_locked, of
|
@@ -415,7 +425,7 @@ class Objects(
|
|
415
425
|
def get_or_create(
|
416
426
|
self,
|
417
427
|
where: Combinable,
|
418
|
-
defaults:
|
428
|
+
defaults: Optional[dict[Column, Any]] = None,
|
419
429
|
) -> GetOrCreate[TableInstance]:
|
420
430
|
if defaults is None:
|
421
431
|
defaults = {}
|
@@ -423,15 +433,15 @@ class Objects(
|
|
423
433
|
query=self, table_class=self.table, where=where, defaults=defaults
|
424
434
|
)
|
425
435
|
|
426
|
-
def create(self, **columns:
|
436
|
+
def create(self, **columns: Any) -> Create[TableInstance]:
|
427
437
|
return Create[TableInstance](table_class=self.table, columns=columns)
|
428
438
|
|
429
439
|
###########################################################################
|
430
440
|
|
431
441
|
async def batch(
|
432
442
|
self,
|
433
|
-
batch_size:
|
434
|
-
node:
|
443
|
+
batch_size: Optional[int] = None,
|
444
|
+
node: Optional[str] = None,
|
435
445
|
**kwargs,
|
436
446
|
) -> BaseBatch:
|
437
447
|
if batch_size:
|
@@ -447,7 +457,7 @@ class Objects(
|
|
447
457
|
return response
|
448
458
|
|
449
459
|
@property
|
450
|
-
def default_querystrings(self) ->
|
460
|
+
def default_querystrings(self) -> Sequence[QueryString]:
|
451
461
|
select = Select(table=self.table)
|
452
462
|
|
453
463
|
for attr in (
|
@@ -481,17 +491,17 @@ class Objects(
|
|
481
491
|
|
482
492
|
async def run(
|
483
493
|
self,
|
484
|
-
node:
|
494
|
+
node: Optional[str] = None,
|
485
495
|
in_pool: bool = True,
|
486
496
|
use_callbacks: bool = True,
|
487
|
-
) ->
|
497
|
+
) -> list[TableInstance]:
|
488
498
|
results = await super().run(node=node, in_pool=in_pool)
|
489
499
|
|
490
500
|
if use_callbacks:
|
491
501
|
# With callbacks, the user can return any data that they want.
|
492
502
|
# Assume that most of the time they will still return a list of
|
493
503
|
# Table instances.
|
494
|
-
modified:
|
504
|
+
modified: list[TableInstance] = (
|
495
505
|
await self.callback_delegate.invoke(
|
496
506
|
results, kind=CallbackType.success
|
497
507
|
)
|
@@ -502,8 +512,8 @@ class Objects(
|
|
502
512
|
|
503
513
|
def __await__(
|
504
514
|
self,
|
505
|
-
) ->
|
515
|
+
) -> Generator[None, None, list[TableInstance]]:
|
506
516
|
return super().__await__()
|
507
517
|
|
508
518
|
|
509
|
-
Self =
|
519
|
+
Self = TypeVar("Self", bound=Objects)
|
piccolo/query/methods/raw.py
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
|
3
|
+
from collections.abc import Sequence
|
4
|
+
from typing import TYPE_CHECKING, Optional
|
4
5
|
|
5
6
|
from piccolo.engine.base import BaseBatch
|
6
7
|
from piccolo.query.base import Query
|
7
8
|
from piccolo.querystring import QueryString
|
8
9
|
|
9
|
-
if
|
10
|
+
if TYPE_CHECKING: # pragma: no cover
|
10
11
|
from piccolo.table import Table
|
11
12
|
|
12
13
|
|
@@ -15,7 +16,7 @@ class Raw(Query):
|
|
15
16
|
|
16
17
|
def __init__(
|
17
18
|
self,
|
18
|
-
table:
|
19
|
+
table: type[Table],
|
19
20
|
querystring: QueryString = QueryString(""),
|
20
21
|
**kwargs,
|
21
22
|
):
|
@@ -24,8 +25,8 @@ class Raw(Query):
|
|
24
25
|
|
25
26
|
async def batch(
|
26
27
|
self,
|
27
|
-
batch_size:
|
28
|
-
node:
|
28
|
+
batch_size: Optional[int] = None,
|
29
|
+
node: Optional[str] = None,
|
29
30
|
**kwargs,
|
30
31
|
) -> BaseBatch:
|
31
32
|
if batch_size:
|
@@ -35,5 +36,5 @@ class Raw(Query):
|
|
35
36
|
return await self.table._meta.db.batch(self, **kwargs)
|
36
37
|
|
37
38
|
@property
|
38
|
-
def default_querystrings(self) ->
|
39
|
+
def default_querystrings(self) -> Sequence[QueryString]:
|
39
40
|
return [self.querystring]
|
piccolo/query/methods/refresh.py
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
|
3
|
+
from collections.abc import Sequence
|
4
|
+
from typing import TYPE_CHECKING, Optional
|
4
5
|
|
5
6
|
from piccolo.utils.encoding import JSONDict
|
6
7
|
from piccolo.utils.sync import run_sync
|
7
8
|
|
8
|
-
if
|
9
|
+
if TYPE_CHECKING: # pragma: no cover
|
9
10
|
from piccolo.columns import Column
|
10
11
|
from piccolo.table import Table
|
11
12
|
|
@@ -30,7 +31,7 @@ class Refresh:
|
|
30
31
|
def __init__(
|
31
32
|
self,
|
32
33
|
instance: Table,
|
33
|
-
columns:
|
34
|
+
columns: Optional[Sequence[Column]] = None,
|
34
35
|
load_json: bool = False,
|
35
36
|
):
|
36
37
|
self.instance = instance
|
@@ -50,7 +51,7 @@ class Refresh:
|
|
50
51
|
self.load_json = load_json
|
51
52
|
|
52
53
|
@property
|
53
|
-
def _columns(self) ->
|
54
|
+
def _columns(self) -> Sequence[Column]:
|
54
55
|
"""
|
55
56
|
Works out which columns the user wants to refresh.
|
56
57
|
"""
|
@@ -61,7 +62,7 @@ class Refresh:
|
|
61
62
|
i for i in self.instance._meta.columns if not i._meta.primary_key
|
62
63
|
]
|
63
64
|
|
64
|
-
def _get_columns(self, instance: Table, columns:
|
65
|
+
def _get_columns(self, instance: Table, columns: Sequence[Column]):
|
65
66
|
"""
|
66
67
|
If `prefetch` was used on the object, for example::
|
67
68
|
|
@@ -100,7 +101,7 @@ class Refresh:
|
|
100
101
|
|
101
102
|
return select_columns
|
102
103
|
|
103
|
-
def _update_instance(self, instance: Table, data_dict:
|
104
|
+
def _update_instance(self, instance: Table, data_dict: dict):
|
104
105
|
"""
|
105
106
|
Update the table instance. It is called recursively, if the instance
|
106
107
|
has child instances.
|
@@ -119,7 +120,7 @@ class Refresh:
|
|
119
120
|
setattr(instance, key, value)
|
120
121
|
|
121
122
|
async def run(
|
122
|
-
self, in_pool: bool = True, node:
|
123
|
+
self, in_pool: bool = True, node: Optional[str] = None
|
123
124
|
) -> Table:
|
124
125
|
"""
|
125
126
|
Run it asynchronously. For example::
|