alembic 1.14.1__py3-none-any.whl → 1.15.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.
- alembic/__init__.py +1 -1
- alembic/autogenerate/compare.py +11 -23
- alembic/autogenerate/render.py +25 -19
- alembic/command.py +3 -1
- alembic/context.pyi +5 -2
- alembic/ddl/base.py +2 -2
- alembic/ddl/impl.py +8 -9
- alembic/ddl/mysql.py +1 -2
- alembic/ddl/postgresql.py +5 -5
- alembic/ddl/sqlite.py +2 -1
- alembic/op.pyi +1 -2
- alembic/operations/base.py +1 -2
- alembic/operations/batch.py +5 -4
- alembic/operations/ops.py +1 -2
- alembic/operations/toimpl.py +0 -13
- alembic/runtime/environment.py +2 -2
- alembic/runtime/migration.py +4 -4
- alembic/templates/async/alembic.ini.mako +1 -1
- alembic/templates/async/script.py.mako +2 -0
- alembic/templates/generic/alembic.ini.mako +1 -1
- alembic/templates/generic/script.py.mako +2 -0
- alembic/templates/multidb/alembic.ini.mako +1 -1
- alembic/templates/multidb/script.py.mako +4 -0
- alembic/testing/assertions.py +2 -3
- alembic/testing/env.py +62 -78
- alembic/testing/fixtures.py +3 -15
- alembic/testing/requirements.py +1 -35
- alembic/testing/suite/test_autogen_computed.py +2 -62
- alembic/testing/warnings.py +0 -9
- alembic/util/__init__.py +0 -7
- alembic/util/exc.py +20 -1
- alembic/util/messaging.py +1 -4
- alembic/util/sqla_compat.py +72 -238
- {alembic-1.14.1.dist-info → alembic-1.15.1.dist-info}/METADATA +7 -11
- {alembic-1.14.1.dist-info → alembic-1.15.1.dist-info}/RECORD +39 -39
- {alembic-1.14.1.dist-info → alembic-1.15.1.dist-info}/WHEEL +1 -1
- {alembic-1.14.1.dist-info → alembic-1.15.1.dist-info}/LICENSE +0 -0
- {alembic-1.14.1.dist-info → alembic-1.15.1.dist-info}/entry_points.txt +0 -0
- {alembic-1.14.1.dist-info → alembic-1.15.1.dist-info}/top_level.txt +0 -0
alembic/testing/env.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import importlib.machinery
|
2
2
|
import os
|
3
|
+
from pathlib import Path
|
3
4
|
import shutil
|
4
5
|
import textwrap
|
5
6
|
|
@@ -16,7 +17,7 @@ from ..script import ScriptDirectory
|
|
16
17
|
|
17
18
|
def _get_staging_directory():
|
18
19
|
if provision.FOLLOWER_IDENT:
|
19
|
-
return "scratch_
|
20
|
+
return f"scratch_{provision.FOLLOWER_IDENT}"
|
20
21
|
else:
|
21
22
|
return "scratch"
|
22
23
|
|
@@ -24,7 +25,7 @@ def _get_staging_directory():
|
|
24
25
|
def staging_env(create=True, template="generic", sourceless=False):
|
25
26
|
cfg = _testing_config()
|
26
27
|
if create:
|
27
|
-
path =
|
28
|
+
path = _join_path(_get_staging_directory(), "scripts")
|
28
29
|
assert not os.path.exists(path), (
|
29
30
|
"staging directory %s already exists; poor cleanup?" % path
|
30
31
|
)
|
@@ -47,7 +48,7 @@ def staging_env(create=True, template="generic", sourceless=False):
|
|
47
48
|
"pep3147_everything",
|
48
49
|
), sourceless
|
49
50
|
make_sourceless(
|
50
|
-
|
51
|
+
_join_path(path, "env.py"),
|
51
52
|
"pep3147" if "pep3147" in sourceless else "simple",
|
52
53
|
)
|
53
54
|
|
@@ -63,14 +64,14 @@ def clear_staging_env():
|
|
63
64
|
|
64
65
|
|
65
66
|
def script_file_fixture(txt):
|
66
|
-
dir_ =
|
67
|
-
path =
|
67
|
+
dir_ = _join_path(_get_staging_directory(), "scripts")
|
68
|
+
path = _join_path(dir_, "script.py.mako")
|
68
69
|
with open(path, "w") as f:
|
69
70
|
f.write(txt)
|
70
71
|
|
71
72
|
|
72
73
|
def env_file_fixture(txt):
|
73
|
-
dir_ =
|
74
|
+
dir_ = _join_path(_get_staging_directory(), "scripts")
|
74
75
|
txt = (
|
75
76
|
"""
|
76
77
|
from alembic import context
|
@@ -80,7 +81,7 @@ config = context.config
|
|
80
81
|
+ txt
|
81
82
|
)
|
82
83
|
|
83
|
-
path =
|
84
|
+
path = _join_path(dir_, "env.py")
|
84
85
|
pyc_path = util.pyc_file_from_path(path)
|
85
86
|
if pyc_path:
|
86
87
|
os.unlink(pyc_path)
|
@@ -90,26 +91,26 @@ config = context.config
|
|
90
91
|
|
91
92
|
|
92
93
|
def _sqlite_file_db(tempname="foo.db", future=False, scope=None, **options):
|
93
|
-
dir_ =
|
94
|
+
dir_ = _join_path(_get_staging_directory(), "scripts")
|
94
95
|
url = "sqlite:///%s/%s" % (dir_, tempname)
|
95
|
-
if scope
|
96
|
+
if scope:
|
96
97
|
options["scope"] = scope
|
97
98
|
return testing_util.testing_engine(url=url, future=future, options=options)
|
98
99
|
|
99
100
|
|
100
101
|
def _sqlite_testing_config(sourceless=False, future=False):
|
101
|
-
dir_ =
|
102
|
-
url = "sqlite
|
102
|
+
dir_ = _join_path(_get_staging_directory(), "scripts")
|
103
|
+
url = f"sqlite:///{dir_}/foo.db"
|
103
104
|
|
104
105
|
sqlalchemy_future = future or ("future" in config.db.__class__.__module__)
|
105
106
|
|
106
107
|
return _write_config_file(
|
107
|
-
"""
|
108
|
+
f"""
|
108
109
|
[alembic]
|
109
|
-
script_location =
|
110
|
-
sqlalchemy.url =
|
111
|
-
sourceless =
|
112
|
-
|
110
|
+
script_location = {dir_}
|
111
|
+
sqlalchemy.url = {url}
|
112
|
+
sourceless = {"true" if sourceless else "false"}
|
113
|
+
{"sqlalchemy.future = true" if sqlalchemy_future else ""}
|
113
114
|
|
114
115
|
[loggers]
|
115
116
|
keys = root,sqlalchemy
|
@@ -140,29 +141,24 @@ keys = generic
|
|
140
141
|
format = %%(levelname)-5.5s [%%(name)s] %%(message)s
|
141
142
|
datefmt = %%H:%%M:%%S
|
142
143
|
"""
|
143
|
-
% (
|
144
|
-
dir_,
|
145
|
-
url,
|
146
|
-
"true" if sourceless else "false",
|
147
|
-
"sqlalchemy.future = true" if sqlalchemy_future else "",
|
148
|
-
)
|
149
144
|
)
|
150
145
|
|
151
146
|
|
152
147
|
def _multi_dir_testing_config(sourceless=False, extra_version_location=""):
|
153
|
-
dir_ =
|
148
|
+
dir_ = _join_path(_get_staging_directory(), "scripts")
|
154
149
|
sqlalchemy_future = "future" in config.db.__class__.__module__
|
155
150
|
|
156
151
|
url = "sqlite:///%s/foo.db" % dir_
|
157
152
|
|
158
153
|
return _write_config_file(
|
159
|
-
"""
|
154
|
+
f"""
|
160
155
|
[alembic]
|
161
|
-
script_location =
|
162
|
-
sqlalchemy.url =
|
163
|
-
sqlalchemy.future =
|
164
|
-
sourceless =
|
165
|
-
version_locations =
|
156
|
+
script_location = {dir_}
|
157
|
+
sqlalchemy.url = {url}
|
158
|
+
sqlalchemy.future = {"true" if sqlalchemy_future else "false"}
|
159
|
+
sourceless = {"true" if sourceless else "false"}
|
160
|
+
version_locations = %(here)s/model1/ %(here)s/model2/ %(here)s/model3/ \
|
161
|
+
{extra_version_location}
|
166
162
|
|
167
163
|
[loggers]
|
168
164
|
keys = root
|
@@ -188,26 +184,19 @@ keys = generic
|
|
188
184
|
format = %%(levelname)-5.5s [%%(name)s] %%(message)s
|
189
185
|
datefmt = %%H:%%M:%%S
|
190
186
|
"""
|
191
|
-
% (
|
192
|
-
dir_,
|
193
|
-
url,
|
194
|
-
"true" if sqlalchemy_future else "false",
|
195
|
-
"true" if sourceless else "false",
|
196
|
-
extra_version_location,
|
197
|
-
)
|
198
187
|
)
|
199
188
|
|
200
189
|
|
201
190
|
def _no_sql_testing_config(dialect="postgresql", directives=""):
|
202
191
|
"""use a postgresql url with no host so that
|
203
192
|
connections guaranteed to fail"""
|
204
|
-
dir_ =
|
193
|
+
dir_ = _join_path(_get_staging_directory(), "scripts")
|
205
194
|
return _write_config_file(
|
206
|
-
"""
|
195
|
+
f"""
|
207
196
|
[alembic]
|
208
|
-
script_location =
|
209
|
-
sqlalchemy.url =
|
210
|
-
|
197
|
+
script_location ={dir_}
|
198
|
+
sqlalchemy.url = {dialect}://
|
199
|
+
{directives}
|
211
200
|
|
212
201
|
[loggers]
|
213
202
|
keys = root
|
@@ -234,7 +223,6 @@ format = %%(levelname)-5.5s [%%(name)s] %%(message)s
|
|
234
223
|
datefmt = %%H:%%M:%%S
|
235
224
|
|
236
225
|
"""
|
237
|
-
% (dir_, dialect, directives)
|
238
226
|
)
|
239
227
|
|
240
228
|
|
@@ -250,7 +238,7 @@ def _testing_config():
|
|
250
238
|
|
251
239
|
if not os.access(_get_staging_directory(), os.F_OK):
|
252
240
|
os.mkdir(_get_staging_directory())
|
253
|
-
return Config(
|
241
|
+
return Config(_join_path(_get_staging_directory(), "test_alembic.ini"))
|
254
242
|
|
255
243
|
|
256
244
|
def write_script(
|
@@ -270,9 +258,7 @@ def write_script(
|
|
270
258
|
script = Script._from_path(scriptdir, path)
|
271
259
|
old = scriptdir.revision_map.get_revision(script.revision)
|
272
260
|
if old.down_revision != script.down_revision:
|
273
|
-
raise Exception(
|
274
|
-
"Can't change down_revision " "on a refresh operation."
|
275
|
-
)
|
261
|
+
raise Exception("Can't change down_revision on a refresh operation.")
|
276
262
|
scriptdir.revision_map.add_revision(script, _replace=True)
|
277
263
|
|
278
264
|
if sourceless:
|
@@ -312,9 +298,9 @@ def three_rev_fixture(cfg):
|
|
312
298
|
write_script(
|
313
299
|
script,
|
314
300
|
a,
|
315
|
-
"""\
|
301
|
+
f"""\
|
316
302
|
"Rev A"
|
317
|
-
revision = '
|
303
|
+
revision = '{a}'
|
318
304
|
down_revision = None
|
319
305
|
|
320
306
|
from alembic import op
|
@@ -327,8 +313,7 @@ def upgrade():
|
|
327
313
|
def downgrade():
|
328
314
|
op.execute("DROP STEP 1")
|
329
315
|
|
330
|
-
"""
|
331
|
-
% a,
|
316
|
+
""",
|
332
317
|
)
|
333
318
|
|
334
319
|
script.generate_revision(b, "revision b", refresh=True, head=a)
|
@@ -358,10 +343,10 @@ def downgrade():
|
|
358
343
|
write_script(
|
359
344
|
script,
|
360
345
|
c,
|
361
|
-
"""\
|
346
|
+
f"""\
|
362
347
|
"Rev C"
|
363
|
-
revision = '
|
364
|
-
down_revision = '
|
348
|
+
revision = '{c}'
|
349
|
+
down_revision = '{b}'
|
365
350
|
|
366
351
|
from alembic import op
|
367
352
|
|
@@ -373,8 +358,7 @@ def upgrade():
|
|
373
358
|
def downgrade():
|
374
359
|
op.execute("DROP STEP 3")
|
375
360
|
|
376
|
-
"""
|
377
|
-
% (c, b),
|
361
|
+
""",
|
378
362
|
)
|
379
363
|
return a, b, c
|
380
364
|
|
@@ -396,10 +380,10 @@ def multi_heads_fixture(cfg, a, b, c):
|
|
396
380
|
write_script(
|
397
381
|
script,
|
398
382
|
d,
|
399
|
-
"""\
|
383
|
+
f"""\
|
400
384
|
"Rev D"
|
401
|
-
revision = '
|
402
|
-
down_revision = '
|
385
|
+
revision = '{d}'
|
386
|
+
down_revision = '{b}'
|
403
387
|
|
404
388
|
from alembic import op
|
405
389
|
|
@@ -411,8 +395,7 @@ def upgrade():
|
|
411
395
|
def downgrade():
|
412
396
|
op.execute("DROP STEP 4")
|
413
397
|
|
414
|
-
"""
|
415
|
-
% (d, b),
|
398
|
+
""",
|
416
399
|
)
|
417
400
|
|
418
401
|
script.generate_revision(
|
@@ -421,10 +404,10 @@ def downgrade():
|
|
421
404
|
write_script(
|
422
405
|
script,
|
423
406
|
e,
|
424
|
-
"""\
|
407
|
+
f"""\
|
425
408
|
"Rev E"
|
426
|
-
revision = '
|
427
|
-
down_revision = '
|
409
|
+
revision = '{e}'
|
410
|
+
down_revision = '{d}'
|
428
411
|
|
429
412
|
from alembic import op
|
430
413
|
|
@@ -436,8 +419,7 @@ def upgrade():
|
|
436
419
|
def downgrade():
|
437
420
|
op.execute("DROP STEP 5")
|
438
421
|
|
439
|
-
"""
|
440
|
-
% (e, d),
|
422
|
+
""",
|
441
423
|
)
|
442
424
|
|
443
425
|
script.generate_revision(
|
@@ -446,10 +428,10 @@ def downgrade():
|
|
446
428
|
write_script(
|
447
429
|
script,
|
448
430
|
f,
|
449
|
-
"""\
|
431
|
+
f"""\
|
450
432
|
"Rev F"
|
451
|
-
revision = '
|
452
|
-
down_revision = '
|
433
|
+
revision = '{f}'
|
434
|
+
down_revision = '{b}'
|
453
435
|
|
454
436
|
from alembic import op
|
455
437
|
|
@@ -461,8 +443,7 @@ def upgrade():
|
|
461
443
|
def downgrade():
|
462
444
|
op.execute("DROP STEP 6")
|
463
445
|
|
464
|
-
"""
|
465
|
-
% (f, b),
|
446
|
+
""",
|
466
447
|
)
|
467
448
|
|
468
449
|
return d, e, f
|
@@ -471,25 +452,25 @@ def downgrade():
|
|
471
452
|
def _multidb_testing_config(engines):
|
472
453
|
"""alembic.ini fixture to work exactly with the 'multidb' template"""
|
473
454
|
|
474
|
-
dir_ =
|
455
|
+
dir_ = _join_path(_get_staging_directory(), "scripts")
|
475
456
|
|
476
457
|
sqlalchemy_future = "future" in config.db.__class__.__module__
|
477
458
|
|
478
459
|
databases = ", ".join(engines.keys())
|
479
460
|
engines = "\n\n".join(
|
480
|
-
"[
|
461
|
+
f"[{key}]\nsqlalchemy.url = {value.url}"
|
481
462
|
for key, value in engines.items()
|
482
463
|
)
|
483
464
|
|
484
465
|
return _write_config_file(
|
485
|
-
"""
|
466
|
+
f"""
|
486
467
|
[alembic]
|
487
|
-
script_location =
|
468
|
+
script_location = {dir_}
|
488
469
|
sourceless = false
|
489
|
-
sqlalchemy.future =
|
490
|
-
databases =
|
470
|
+
sqlalchemy.future = {"true" if sqlalchemy_future else "false"}
|
471
|
+
databases = {databases}
|
491
472
|
|
492
|
-
|
473
|
+
{engines}
|
493
474
|
[loggers]
|
494
475
|
keys = root
|
495
476
|
|
@@ -514,5 +495,8 @@ keys = generic
|
|
514
495
|
format = %%(levelname)-5.5s [%%(name)s] %%(message)s
|
515
496
|
datefmt = %%H:%%M:%%S
|
516
497
|
"""
|
517
|
-
% (dir_, "true" if sqlalchemy_future else "false", databases, engines)
|
518
498
|
)
|
499
|
+
|
500
|
+
|
501
|
+
def _join_path(base: str, *more: str):
|
502
|
+
return str(Path(base).joinpath(*more).as_posix())
|
alembic/testing/fixtures.py
CHANGED
@@ -8,6 +8,7 @@ from typing import Any
|
|
8
8
|
from typing import Dict
|
9
9
|
|
10
10
|
from sqlalchemy import Column
|
11
|
+
from sqlalchemy import create_mock_engine
|
11
12
|
from sqlalchemy import inspect
|
12
13
|
from sqlalchemy import MetaData
|
13
14
|
from sqlalchemy import String
|
@@ -17,6 +18,7 @@ from sqlalchemy import text
|
|
17
18
|
from sqlalchemy.testing import config
|
18
19
|
from sqlalchemy.testing import mock
|
19
20
|
from sqlalchemy.testing.assertions import eq_
|
21
|
+
from sqlalchemy.testing.fixtures import FutureEngineMixin
|
20
22
|
from sqlalchemy.testing.fixtures import TablesTest as SQLAlchemyTablesTest
|
21
23
|
from sqlalchemy.testing.fixtures import TestBase as SQLAlchemyTestBase
|
22
24
|
|
@@ -26,8 +28,6 @@ from ..environment import EnvironmentContext
|
|
26
28
|
from ..migration import MigrationContext
|
27
29
|
from ..operations import Operations
|
28
30
|
from ..util import sqla_compat
|
29
|
-
from ..util.sqla_compat import create_mock_engine
|
30
|
-
from ..util.sqla_compat import sqla_14
|
31
31
|
from ..util.sqla_compat import sqla_2
|
32
32
|
|
33
33
|
|
@@ -65,14 +65,6 @@ class TablesTest(TestBase, SQLAlchemyTablesTest):
|
|
65
65
|
pass
|
66
66
|
|
67
67
|
|
68
|
-
if sqla_14:
|
69
|
-
from sqlalchemy.testing.fixtures import FutureEngineMixin
|
70
|
-
else:
|
71
|
-
|
72
|
-
class FutureEngineMixin: # type:ignore[no-redef]
|
73
|
-
__requires__ = ("sqlalchemy_14",)
|
74
|
-
|
75
|
-
|
76
68
|
FutureEngineMixin.is_sqlalchemy_future = True
|
77
69
|
|
78
70
|
|
@@ -190,12 +182,8 @@ def op_fixture(
|
|
190
182
|
opts["as_sql"] = as_sql
|
191
183
|
if literal_binds:
|
192
184
|
opts["literal_binds"] = literal_binds
|
193
|
-
if not sqla_14 and dialect == "mariadb":
|
194
|
-
ctx_dialect = _get_dialect("mysql")
|
195
|
-
ctx_dialect.server_version_info = (10, 4, 0, "MariaDB")
|
196
185
|
|
197
|
-
|
198
|
-
ctx_dialect = _get_dialect(dialect)
|
186
|
+
ctx_dialect = _get_dialect(dialect)
|
199
187
|
if native_boolean is not None:
|
200
188
|
ctx_dialect.supports_native_boolean = native_boolean
|
201
189
|
# this is new as of SQLAlchemy 1.2.7 and is used by SQL Server,
|
alembic/testing/requirements.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
from sqlalchemy.testing.requirements import Requirements
|
2
2
|
|
3
3
|
from alembic import util
|
4
|
-
from alembic.util import sqla_compat
|
5
4
|
from ..testing import exclusions
|
6
5
|
|
7
6
|
|
@@ -74,13 +73,6 @@ class SuiteRequirements(Requirements):
|
|
74
73
|
def reflects_fk_options(self):
|
75
74
|
return exclusions.closed()
|
76
75
|
|
77
|
-
@property
|
78
|
-
def sqlalchemy_14(self):
|
79
|
-
return exclusions.skip_if(
|
80
|
-
lambda config: not util.sqla_14,
|
81
|
-
"SQLAlchemy 1.4 or greater required",
|
82
|
-
)
|
83
|
-
|
84
76
|
@property
|
85
77
|
def sqlalchemy_1x(self):
|
86
78
|
return exclusions.skip_if(
|
@@ -105,7 +97,7 @@ class SuiteRequirements(Requirements):
|
|
105
97
|
else:
|
106
98
|
return True
|
107
99
|
|
108
|
-
return
|
100
|
+
return exclusions.only_if(go)
|
109
101
|
|
110
102
|
@property
|
111
103
|
def comments(self):
|
@@ -121,26 +113,6 @@ class SuiteRequirements(Requirements):
|
|
121
113
|
def computed_columns(self):
|
122
114
|
return exclusions.closed()
|
123
115
|
|
124
|
-
@property
|
125
|
-
def computed_columns_api(self):
|
126
|
-
return exclusions.only_if(
|
127
|
-
exclusions.BooleanPredicate(sqla_compat.has_computed)
|
128
|
-
)
|
129
|
-
|
130
|
-
@property
|
131
|
-
def computed_reflects_normally(self):
|
132
|
-
return exclusions.only_if(
|
133
|
-
exclusions.BooleanPredicate(sqla_compat.has_computed_reflection)
|
134
|
-
)
|
135
|
-
|
136
|
-
@property
|
137
|
-
def computed_reflects_as_server_default(self):
|
138
|
-
return exclusions.closed()
|
139
|
-
|
140
|
-
@property
|
141
|
-
def computed_doesnt_reflect_as_server_default(self):
|
142
|
-
return exclusions.closed()
|
143
|
-
|
144
116
|
@property
|
145
117
|
def autoincrement_on_composite_pk(self):
|
146
118
|
return exclusions.closed()
|
@@ -202,9 +174,3 @@ class SuiteRequirements(Requirements):
|
|
202
174
|
@property
|
203
175
|
def identity_columns_alter(self):
|
204
176
|
return exclusions.closed()
|
205
|
-
|
206
|
-
@property
|
207
|
-
def identity_columns_api(self):
|
208
|
-
return exclusions.only_if(
|
209
|
-
exclusions.BooleanPredicate(sqla_compat.has_identity)
|
210
|
-
)
|
@@ -6,9 +6,7 @@ from sqlalchemy import Table
|
|
6
6
|
|
7
7
|
from ._autogen_fixtures import AutogenFixtureTest
|
8
8
|
from ... import testing
|
9
|
-
from ...testing import config
|
10
9
|
from ...testing import eq_
|
11
|
-
from ...testing import exclusions
|
12
10
|
from ...testing import is_
|
13
11
|
from ...testing import is_true
|
14
12
|
from ...testing import mock
|
@@ -63,18 +61,8 @@ class AutogenerateComputedTest(AutogenFixtureTest, TestBase):
|
|
63
61
|
c = diffs[0][3]
|
64
62
|
eq_(c.name, "foo")
|
65
63
|
|
66
|
-
|
67
|
-
|
68
|
-
else:
|
69
|
-
is_(c.computed, None)
|
70
|
-
|
71
|
-
if config.requirements.computed_reflects_as_server_default.enabled:
|
72
|
-
is_true(isinstance(c.server_default, sa.DefaultClause))
|
73
|
-
eq_(str(c.server_default.arg.text), "5")
|
74
|
-
elif config.requirements.computed_reflects_normally.enabled:
|
75
|
-
is_true(isinstance(c.computed, sa.Computed))
|
76
|
-
else:
|
77
|
-
is_(c.computed, None)
|
64
|
+
is_true(isinstance(c.computed, sa.Computed))
|
65
|
+
is_true(isinstance(c.server_default, sa.Computed))
|
78
66
|
|
79
67
|
@testing.combinations(
|
80
68
|
lambda: (None, sa.Computed("bar*5")),
|
@@ -85,7 +73,6 @@ class AutogenerateComputedTest(AutogenFixtureTest, TestBase):
|
|
85
73
|
),
|
86
74
|
lambda: (sa.Computed("bar*5"), sa.Computed("bar * 42")),
|
87
75
|
)
|
88
|
-
@config.requirements.computed_reflects_normally
|
89
76
|
def test_cant_change_computed_warning(self, test_case):
|
90
77
|
arg_before, arg_after = testing.resolve_lambda(test_case, **locals())
|
91
78
|
m1 = MetaData()
|
@@ -125,10 +112,6 @@ class AutogenerateComputedTest(AutogenFixtureTest, TestBase):
|
|
125
112
|
lambda: (sa.Computed("5"), sa.Computed("5")),
|
126
113
|
lambda: (sa.Computed("bar*5"), sa.Computed("bar*5")),
|
127
114
|
lambda: (sa.Computed("bar*5"), sa.Computed("bar * \r\n\t5")),
|
128
|
-
(
|
129
|
-
lambda: (sa.Computed("bar*5"), None),
|
130
|
-
config.requirements.computed_doesnt_reflect_as_server_default,
|
131
|
-
),
|
132
115
|
)
|
133
116
|
def test_computed_unchanged(self, test_case):
|
134
117
|
arg_before, arg_after = testing.resolve_lambda(test_case, **locals())
|
@@ -159,46 +142,3 @@ class AutogenerateComputedTest(AutogenFixtureTest, TestBase):
|
|
159
142
|
eq_(mock_warn.mock_calls, [])
|
160
143
|
|
161
144
|
eq_(list(diffs), [])
|
162
|
-
|
163
|
-
@config.requirements.computed_reflects_as_server_default
|
164
|
-
def test_remove_computed_default_on_computed(self):
|
165
|
-
"""Asserts the current behavior which is that on PG and Oracle,
|
166
|
-
the GENERATED ALWAYS AS is reflected as a server default which we can't
|
167
|
-
tell is actually "computed", so these come out as a modification to
|
168
|
-
the server default.
|
169
|
-
|
170
|
-
"""
|
171
|
-
m1 = MetaData()
|
172
|
-
m2 = MetaData()
|
173
|
-
|
174
|
-
Table(
|
175
|
-
"user",
|
176
|
-
m1,
|
177
|
-
Column("id", Integer, primary_key=True),
|
178
|
-
Column("bar", Integer),
|
179
|
-
Column("foo", Integer, sa.Computed("bar + 42")),
|
180
|
-
)
|
181
|
-
|
182
|
-
Table(
|
183
|
-
"user",
|
184
|
-
m2,
|
185
|
-
Column("id", Integer, primary_key=True),
|
186
|
-
Column("bar", Integer),
|
187
|
-
Column("foo", Integer),
|
188
|
-
)
|
189
|
-
|
190
|
-
diffs = self._fixture(m1, m2)
|
191
|
-
|
192
|
-
eq_(diffs[0][0][0], "modify_default")
|
193
|
-
eq_(diffs[0][0][2], "user")
|
194
|
-
eq_(diffs[0][0][3], "foo")
|
195
|
-
old = diffs[0][0][-2]
|
196
|
-
new = diffs[0][0][-1]
|
197
|
-
|
198
|
-
is_(new, None)
|
199
|
-
is_true(isinstance(old, sa.DefaultClause))
|
200
|
-
|
201
|
-
if exclusions.against(config, "postgresql"):
|
202
|
-
eq_(str(old.arg.text), "(bar + 42)")
|
203
|
-
elif exclusions.against(config, "oracle"):
|
204
|
-
eq_(str(old.arg.text), '"BAR"+42')
|
alembic/testing/warnings.py
CHANGED
@@ -10,8 +10,6 @@ import warnings
|
|
10
10
|
|
11
11
|
from sqlalchemy import exc as sa_exc
|
12
12
|
|
13
|
-
from ..util import sqla_14
|
14
|
-
|
15
13
|
|
16
14
|
def setup_filters():
|
17
15
|
"""Set global warning behavior for the test suite."""
|
@@ -23,13 +21,6 @@ def setup_filters():
|
|
23
21
|
|
24
22
|
# some selected deprecations...
|
25
23
|
warnings.filterwarnings("error", category=DeprecationWarning)
|
26
|
-
if not sqla_14:
|
27
|
-
# 1.3 uses pkg_resources in PluginLoader
|
28
|
-
warnings.filterwarnings(
|
29
|
-
"ignore",
|
30
|
-
"pkg_resources is deprecated as an API",
|
31
|
-
DeprecationWarning,
|
32
|
-
)
|
33
24
|
try:
|
34
25
|
import pytest
|
35
26
|
except ImportError:
|
alembic/util/__init__.py
CHANGED
@@ -25,11 +25,4 @@ from .pyfiles import coerce_resource_to_filename as coerce_resource_to_filename
|
|
25
25
|
from .pyfiles import load_python_file as load_python_file
|
26
26
|
from .pyfiles import pyc_file_from_path as pyc_file_from_path
|
27
27
|
from .pyfiles import template_to_file as template_to_file
|
28
|
-
from .sqla_compat import has_computed as has_computed
|
29
|
-
from .sqla_compat import sqla_13 as sqla_13
|
30
|
-
from .sqla_compat import sqla_14 as sqla_14
|
31
28
|
from .sqla_compat import sqla_2 as sqla_2
|
32
|
-
|
33
|
-
|
34
|
-
if not sqla_13:
|
35
|
-
raise CommandError("SQLAlchemy 1.3.0 or greater is required.")
|
alembic/util/exc.py
CHANGED
@@ -1,6 +1,25 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import Any
|
4
|
+
from typing import List
|
5
|
+
from typing import Tuple
|
6
|
+
from typing import TYPE_CHECKING
|
7
|
+
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
from alembic.autogenerate import RevisionContext
|
10
|
+
|
11
|
+
|
1
12
|
class CommandError(Exception):
|
2
13
|
pass
|
3
14
|
|
4
15
|
|
5
16
|
class AutogenerateDiffsDetected(CommandError):
|
6
|
-
|
17
|
+
def __init__(
|
18
|
+
self,
|
19
|
+
message: str,
|
20
|
+
revision_context: RevisionContext,
|
21
|
+
diffs: List[Tuple[Any, ...]],
|
22
|
+
) -> None:
|
23
|
+
super().__init__(message)
|
24
|
+
self.revision_context = revision_context
|
25
|
+
self.diffs = diffs
|
alembic/util/messaging.py
CHANGED
@@ -13,8 +13,6 @@ import warnings
|
|
13
13
|
|
14
14
|
from sqlalchemy.engine import url
|
15
15
|
|
16
|
-
from . import sqla_compat
|
17
|
-
|
18
16
|
log = logging.getLogger(__name__)
|
19
17
|
|
20
18
|
# disable "no handler found" errors
|
@@ -76,8 +74,7 @@ def err(message: str, quiet: bool = False) -> None:
|
|
76
74
|
|
77
75
|
|
78
76
|
def obfuscate_url_pw(input_url: str) -> str:
|
79
|
-
|
80
|
-
return sqla_compat.url_render_as_string(u, hide_password=True) # type: ignore # noqa: E501
|
77
|
+
return url.make_url(input_url).render_as_string(hide_password=True)
|
81
78
|
|
82
79
|
|
83
80
|
def warn(msg: str, stacklevel: int = 2) -> None:
|