piccolo 1.16.0__py3-none-any.whl → 1.17.1__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 +3 -3
- piccolo/apps/asgi/commands/templates/app/main.py.jinja +4 -0
- piccolo/apps/migrations/auto/diffable_table.py +10 -3
- piccolo/apps/migrations/auto/migration_manager.py +22 -1
- {piccolo-1.16.0.dist-info → piccolo-1.17.1.dist-info}/METADATA +1 -1
- {piccolo-1.16.0.dist-info → piccolo-1.17.1.dist-info}/RECORD +14 -14
- {piccolo-1.16.0.dist-info → piccolo-1.17.1.dist-info}/WHEEL +1 -1
- tests/apps/migrations/auto/integration/test_migrations.py +19 -0
- tests/apps/migrations/auto/test_diffable_table.py +13 -0
- tests/apps/migrations/auto/test_migration_manager.py +36 -1
- {piccolo-1.16.0.dist-info → piccolo-1.17.1.dist-info}/LICENSE +0 -0
- {piccolo-1.16.0.dist-info → piccolo-1.17.1.dist-info}/entry_points.txt +0 -0
- {piccolo-1.16.0.dist-info → piccolo-1.17.1.dist-info}/top_level.txt +0 -0
piccolo/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__VERSION__ = "1.
|
1
|
+
__VERSION__ = "1.17.1"
|
@@ -9,13 +9,13 @@ import colorama
|
|
9
9
|
from jinja2 import Environment, FileSystemLoader
|
10
10
|
|
11
11
|
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), "templates/app/")
|
12
|
-
SERVERS = ["uvicorn", "Hypercorn"]
|
12
|
+
SERVERS = ["uvicorn", "Hypercorn", "granian"]
|
13
13
|
ROUTER_DEPENDENCIES = {
|
14
14
|
"starlette": ["starlette"],
|
15
|
-
"fastapi": ["fastapi>=0.
|
15
|
+
"fastapi": ["fastapi>=0.112.1"],
|
16
16
|
"blacksheep": ["blacksheep"],
|
17
17
|
"litestar": ["litestar"],
|
18
|
-
"esmerald": ["esmerald"],
|
18
|
+
"esmerald": ["esmerald==3.3.0"],
|
19
19
|
"lilya": ["lilya"],
|
20
20
|
}
|
21
21
|
ROUTERS = list(ROUTER_DEPENDENCIES.keys())
|
@@ -40,10 +40,17 @@ def compare_dicts(
|
|
40
40
|
|
41
41
|
for key, value in dict_1.items():
|
42
42
|
dict_2_value = dict_2.get(key, ...)
|
43
|
+
|
43
44
|
if (
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
# If the value is `...` then it means no value was found.
|
46
|
+
(dict_2_value is ...)
|
47
|
+
# We have to compare the types, because if we just use equality
|
48
|
+
# then 1.0 == 1 is True.
|
49
|
+
# See this issue:
|
50
|
+
# https://github.com/piccolo-orm/piccolo/issues/1071
|
51
|
+
or (type(value) is not type(dict_2_value))
|
52
|
+
# Finally compare the actual values.
|
53
|
+
or (dict_2_value != value)
|
47
54
|
):
|
48
55
|
output[key] = value
|
49
56
|
|
@@ -130,11 +130,27 @@ class AlterColumnCollection:
|
|
130
130
|
AsyncFunction = t.Callable[[], t.Coroutine]
|
131
131
|
|
132
132
|
|
133
|
+
class SkippedTransaction:
|
134
|
+
async def __aenter__(self):
|
135
|
+
print("Automatic transaction disabled")
|
136
|
+
|
137
|
+
async def __aexit__(self, *args, **kwargs):
|
138
|
+
pass
|
139
|
+
|
140
|
+
|
133
141
|
@dataclass
|
134
142
|
class MigrationManager:
|
135
143
|
"""
|
136
144
|
Each auto generated migration returns a MigrationManager. It contains
|
137
145
|
all of the schema changes that migration wants to make.
|
146
|
+
|
147
|
+
:param wrap_in_transaction:
|
148
|
+
By default, the migration is wrapped in a transaction, so if anything
|
149
|
+
fails, the whole migration will get rolled back. You can disable this
|
150
|
+
behaviour if you want - for example, in a manual migration you might
|
151
|
+
want to create the transaction yourself (perhaps you're using
|
152
|
+
savepoints), or you may want multiple transactions.
|
153
|
+
|
138
154
|
"""
|
139
155
|
|
140
156
|
migration_id: str = ""
|
@@ -166,6 +182,7 @@ class MigrationManager:
|
|
166
182
|
default_factory=list
|
167
183
|
)
|
168
184
|
fake: bool = False
|
185
|
+
wrap_in_transaction: bool = True
|
169
186
|
|
170
187
|
def add_table(
|
171
188
|
self,
|
@@ -935,7 +952,11 @@ class MigrationManager:
|
|
935
952
|
if not engine:
|
936
953
|
raise Exception("Can't find engine")
|
937
954
|
|
938
|
-
async with
|
955
|
+
async with (
|
956
|
+
engine.transaction()
|
957
|
+
if self.wrap_in_transaction
|
958
|
+
else SkippedTransaction()
|
959
|
+
):
|
939
960
|
if not self.preview:
|
940
961
|
if direction == "backwards":
|
941
962
|
raw_list = self.raw_backwards
|
@@ -1,4 +1,4 @@
|
|
1
|
-
piccolo/__init__.py,sha256=
|
1
|
+
piccolo/__init__.py,sha256=LHM-IUVB0dp8WEkvdMoZPznVSxU-UEwiRDYV3iBGA4w,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
|
@@ -17,7 +17,7 @@ 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=Y9-uw9BdrL_wY_zJhKVTNuVHIE6hDa52YcDgBBA2yII,4248
|
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
|
@@ -27,7 +27,7 @@ piccolo/apps/asgi/commands/templates/app/_litestar_app.py.jinja,sha256=oMH5KXoEY
|
|
27
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
|
-
piccolo/apps/asgi/commands/templates/app/main.py.jinja,sha256=
|
30
|
+
piccolo/apps/asgi/commands/templates/app/main.py.jinja,sha256=QxMpsevsxGQdL_xwfvcNalGLXGswgqiVvApitkP1TuQ,533
|
31
31
|
piccolo/apps/asgi/commands/templates/app/piccolo_conf.py.jinja,sha256=f9Nb08_yipi0_mDUYrUvVoGCz7MRRS5QjCdUGBHN760,379
|
32
32
|
piccolo/apps/asgi/commands/templates/app/piccolo_conf_test.py.jinja,sha256=ZB32IZQFjA67U7N7hD_wwZdbTdxAofj3-66EnX8Gqd0,235
|
33
33
|
piccolo/apps/asgi/commands/templates/app/requirements.txt.jinja,sha256=w4FXnehMNsauBjf1OcJ547SL8uymhTKcjvSH60Nns7I,149
|
@@ -59,8 +59,8 @@ piccolo/apps/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
59
59
|
piccolo/apps/migrations/piccolo_app.py,sha256=1EcS2ComBPCaMCC2C3WaPR_GqLwt3XiIJNfm5D2hMgo,593
|
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
|
-
piccolo/apps/migrations/auto/diffable_table.py,sha256=
|
63
|
-
piccolo/apps/migrations/auto/migration_manager.py,sha256=
|
62
|
+
piccolo/apps/migrations/auto/diffable_table.py,sha256=1HdqGeWFUYVJ2cJg6DZWOCh67SbgCxFVc554uD7N71A,7405
|
63
|
+
piccolo/apps/migrations/auto/migration_manager.py,sha256=tyAE1Xk6Xb58igbuHw3FGHhKkVjv_Vr5qBH4AbvVb8k,35856
|
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
|
@@ -211,13 +211,13 @@ tests/apps/meta/commands/test_version.py,sha256=GxBeoC6O3OGICVOWtcCdP3bZza1MR2v9
|
|
211
211
|
tests/apps/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
212
212
|
tests/apps/migrations/test_migration.py,sha256=JmPLtf2BCWX3Yofe0GQe40m8I_yWa_-3vk1lDfFDfIo,308
|
213
213
|
tests/apps/migrations/auto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
214
|
-
tests/apps/migrations/auto/test_diffable_table.py,sha256=
|
215
|
-
tests/apps/migrations/auto/test_migration_manager.py,sha256=
|
214
|
+
tests/apps/migrations/auto/test_diffable_table.py,sha256=p0cKDkfhmu96-rB9bonOlg5bmfQ7U9S2kRppOt4YxyU,3338
|
215
|
+
tests/apps/migrations/auto/test_migration_manager.py,sha256=L2raSuhZybRyK-BEh-G-nDndAgl4sLynekHQFqyrteY,35719
|
216
216
|
tests/apps/migrations/auto/test_schema_differ.py,sha256=UdsaZisA02j15wr1bXkXD6Cqu3p0A23NwFQLXsJdQL4,19391
|
217
217
|
tests/apps/migrations/auto/test_schema_snapshot.py,sha256=ZyvGZqn3N3cwd-3S-FME5AJ8buDSHesw7yPIvY6mE5k,6196
|
218
218
|
tests/apps/migrations/auto/test_serialisation.py,sha256=EFkhES1w9h51UCamWrhxs3mf4I718ggeP7Yl5J_UID4,13548
|
219
219
|
tests/apps/migrations/auto/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
220
|
-
tests/apps/migrations/auto/integration/test_migrations.py,sha256=
|
220
|
+
tests/apps/migrations/auto/integration/test_migrations.py,sha256=e4GCAfMWvo5-6EM8f-EmAiLLGR62dxCZ8Tp-0bZ_kDQ,47285
|
221
221
|
tests/apps/migrations/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
222
222
|
tests/apps/migrations/commands/test_base.py,sha256=NgHgVjNd3Hil9eODvW7Ic2D9muTa_grNaH3YpRFfR8I,1829
|
223
223
|
tests/apps/migrations/commands/test_check.py,sha256=hOX_sVk1nfCRfbQ8tJoFEUBFhih9O4QuQLHTp5TQaiY,630
|
@@ -367,9 +367,9 @@ tests/utils/test_sql_values.py,sha256=vzxRmy16FfLZPH-sAQexBvsF9MXB8n4smr14qoEOS5
|
|
367
367
|
tests/utils/test_sync.py,sha256=9ytVo56y2vPQePvTeIi9lHIouEhWJbodl1TmzkGFrSo,799
|
368
368
|
tests/utils/test_table_reflection.py,sha256=SIzuat-IpcVj1GCFyOWKShI8YkhdOPPFH7qVrvfyPNE,3794
|
369
369
|
tests/utils/test_warnings.py,sha256=NvSC_cvJ6uZcwAGf1m-hLzETXCqprXELL8zg3TNLVMw,269
|
370
|
-
piccolo-1.
|
371
|
-
piccolo-1.
|
372
|
-
piccolo-1.
|
373
|
-
piccolo-1.
|
374
|
-
piccolo-1.
|
375
|
-
piccolo-1.
|
370
|
+
piccolo-1.17.1.dist-info/LICENSE,sha256=zFIpi-16uIJ420UMIG75NU0JbDBykvrdnXcj5U_EYBI,1059
|
371
|
+
piccolo-1.17.1.dist-info/METADATA,sha256=TZvCpeVtvGuvBWlyeNvBGPXN7dFZNSrRVuvUwyCOGRs,5178
|
372
|
+
piccolo-1.17.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
373
|
+
piccolo-1.17.1.dist-info/entry_points.txt,sha256=SJPHET4Fi1bN5F3WqcKkv9SClK3_F1I7m4eQjk6AFh0,46
|
374
|
+
piccolo-1.17.1.dist-info/top_level.txt,sha256=-SR74VGbk43VoPy1HH-mHm97yoGukLK87HE5kdBW6qM,24
|
375
|
+
piccolo-1.17.1.dist-info/RECORD,,
|
@@ -888,6 +888,25 @@ class TestMigrations(MigrationTestCase):
|
|
888
888
|
]
|
889
889
|
)
|
890
890
|
|
891
|
+
def test_column_type_conversion_integer_float(self):
|
892
|
+
"""
|
893
|
+
Make sure conversion between ``Integer`` and ``Real`` works - related
|
894
|
+
to this bug:
|
895
|
+
|
896
|
+
https://github.com/piccolo-orm/piccolo/issues/1071
|
897
|
+
|
898
|
+
"""
|
899
|
+
self._test_migrations(
|
900
|
+
table_snapshots=[
|
901
|
+
[self.table(column)]
|
902
|
+
for column in [
|
903
|
+
Real(default=1.0),
|
904
|
+
Integer(default=1),
|
905
|
+
Real(default=1.0),
|
906
|
+
]
|
907
|
+
]
|
908
|
+
)
|
909
|
+
|
891
910
|
def test_column_type_conversion_json(self):
|
892
911
|
self._test_migrations(
|
893
912
|
table_snapshots=[
|
@@ -73,6 +73,19 @@ class TestCompareDicts(TestCase):
|
|
73
73
|
response = compare_dicts(dict_1, dict_2)
|
74
74
|
self.assertEqual(response, {"a": OnDelete.set_default})
|
75
75
|
|
76
|
+
def test_numeric_values(self):
|
77
|
+
"""
|
78
|
+
Make sure that if we have two numbers which are equal, but different
|
79
|
+
types, then they are identified as being different.
|
80
|
+
|
81
|
+
https://github.com/piccolo-orm/piccolo/issues/1071
|
82
|
+
|
83
|
+
"""
|
84
|
+
dict_1 = {"a": 1}
|
85
|
+
dict_2 = {"a": 1.0}
|
86
|
+
response = compare_dicts(dict_1, dict_2)
|
87
|
+
self.assertEqual(response, {"a": 1})
|
88
|
+
|
76
89
|
|
77
90
|
class TestDiffableTable(TestCase):
|
78
91
|
def test_subtract(self):
|
@@ -2,7 +2,7 @@ import asyncio
|
|
2
2
|
import random
|
3
3
|
import typing as t
|
4
4
|
from io import StringIO
|
5
|
-
from unittest import TestCase
|
5
|
+
from unittest import IsolatedAsyncioTestCase, TestCase
|
6
6
|
from unittest.mock import MagicMock, patch
|
7
7
|
|
8
8
|
from piccolo.apps.migrations.auto.migration_manager import MigrationManager
|
@@ -11,6 +11,7 @@ from piccolo.columns import Text, Varchar
|
|
11
11
|
from piccolo.columns.base import OnDelete, OnUpdate
|
12
12
|
from piccolo.columns.column_types import ForeignKey
|
13
13
|
from piccolo.conf.apps import AppConfig
|
14
|
+
from piccolo.engine import engine_finder
|
14
15
|
from piccolo.table import Table, sort_table_classes
|
15
16
|
from piccolo.utils.lazy_loader import LazyLoader
|
16
17
|
from tests.base import AsyncMock, DBTestCase, engine_is, engines_only
|
@@ -1052,3 +1053,37 @@ class TestMigrationManager(DBTestCase):
|
|
1052
1053
|
output,
|
1053
1054
|
' - 1 [preview forwards]... CREATE SCHEMA IF NOT EXISTS "schema_1"\nALTER TABLE "manager" SET SCHEMA "schema_1"\n', # noqa: E501
|
1054
1055
|
)
|
1056
|
+
|
1057
|
+
|
1058
|
+
class TestWrapInTransaction(IsolatedAsyncioTestCase):
|
1059
|
+
|
1060
|
+
async def test_enabled(self):
|
1061
|
+
"""
|
1062
|
+
Make sure we can wrap the migration in a transaction if we want to.
|
1063
|
+
"""
|
1064
|
+
|
1065
|
+
async def run():
|
1066
|
+
db = engine_finder()
|
1067
|
+
assert db
|
1068
|
+
assert db.transaction_exists() is True
|
1069
|
+
|
1070
|
+
manager = MigrationManager(wrap_in_transaction=True)
|
1071
|
+
manager.add_raw(run)
|
1072
|
+
|
1073
|
+
await manager.run()
|
1074
|
+
|
1075
|
+
async def test_disabled(self):
|
1076
|
+
"""
|
1077
|
+
Make sure we can stop the migration being wrapped in a transaction if
|
1078
|
+
we want to.
|
1079
|
+
"""
|
1080
|
+
|
1081
|
+
async def run():
|
1082
|
+
db = engine_finder()
|
1083
|
+
assert db
|
1084
|
+
assert db.transaction_exists() is False
|
1085
|
+
|
1086
|
+
manager = MigrationManager(wrap_in_transaction=False)
|
1087
|
+
manager.add_raw(run)
|
1088
|
+
|
1089
|
+
await manager.run()
|
File without changes
|
File without changes
|
File without changes
|