alembic 1.15.2__py3-none-any.whl → 1.16.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.
Files changed (41) hide show
  1. alembic/__init__.py +1 -1
  2. alembic/autogenerate/compare.py +60 -7
  3. alembic/autogenerate/render.py +25 -4
  4. alembic/command.py +112 -37
  5. alembic/config.py +574 -222
  6. alembic/ddl/base.py +31 -7
  7. alembic/ddl/impl.py +23 -5
  8. alembic/ddl/mssql.py +3 -1
  9. alembic/ddl/mysql.py +8 -4
  10. alembic/ddl/postgresql.py +6 -2
  11. alembic/ddl/sqlite.py +1 -1
  12. alembic/op.pyi +24 -5
  13. alembic/operations/base.py +18 -3
  14. alembic/operations/ops.py +49 -8
  15. alembic/operations/toimpl.py +20 -3
  16. alembic/script/base.py +123 -136
  17. alembic/script/revision.py +1 -1
  18. alembic/script/write_hooks.py +20 -21
  19. alembic/templates/async/alembic.ini.mako +40 -16
  20. alembic/templates/generic/alembic.ini.mako +39 -17
  21. alembic/templates/multidb/alembic.ini.mako +42 -17
  22. alembic/templates/pyproject/README +1 -0
  23. alembic/templates/pyproject/alembic.ini.mako +44 -0
  24. alembic/templates/pyproject/env.py +78 -0
  25. alembic/templates/pyproject/pyproject.toml.mako +76 -0
  26. alembic/templates/pyproject/script.py.mako +28 -0
  27. alembic/testing/__init__.py +2 -0
  28. alembic/testing/assertions.py +4 -0
  29. alembic/testing/env.py +56 -1
  30. alembic/testing/fixtures.py +28 -1
  31. alembic/testing/suite/_autogen_fixtures.py +113 -0
  32. alembic/util/__init__.py +1 -0
  33. alembic/util/compat.py +56 -0
  34. alembic/util/messaging.py +4 -0
  35. alembic/util/pyfiles.py +56 -19
  36. {alembic-1.15.2.dist-info → alembic-1.16.1.dist-info}/METADATA +3 -3
  37. {alembic-1.15.2.dist-info → alembic-1.16.1.dist-info}/RECORD +41 -36
  38. {alembic-1.15.2.dist-info → alembic-1.16.1.dist-info}/WHEEL +1 -1
  39. {alembic-1.15.2.dist-info → alembic-1.16.1.dist-info}/entry_points.txt +0 -0
  40. {alembic-1.15.2.dist-info → alembic-1.16.1.dist-info}/licenses/LICENSE +0 -0
  41. {alembic-1.15.2.dist-info → alembic-1.16.1.dist-info}/top_level.txt +0 -0
@@ -2,15 +2,20 @@
2
2
 
3
3
  [alembic]
4
4
  # path to migration scripts.
5
- # Use forward slashes (/) also on windows to provide an os agnostic path
5
+ # this is typically a path given in POSIX (e.g. forward slashes)
6
+ # format, relative to the token %(here)s which refers to the location of this
7
+ # ini file
6
8
  script_location = ${script_location}
7
9
 
8
10
  # template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
9
11
  # Uncomment the line below if you want the files to be prepended with date and time
12
+ # see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file
13
+ # for all available tokens
10
14
  # file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
11
15
 
12
16
  # sys.path path, will be prepended to sys.path if present.
13
- # defaults to the current working directory.
17
+ # defaults to the current working directory. for multiple paths, the path separator
18
+ # is defined by "path_separator" below.
14
19
  prepend_sys_path = .
15
20
 
16
21
  # timezone to use when rendering the date within the migration file
@@ -34,23 +39,38 @@ prepend_sys_path = .
34
39
  # sourceless = false
35
40
 
36
41
  # version location specification; This defaults
37
- # to ${script_location}/versions. When using multiple version
42
+ # to <script_location>/versions. When using multiple version
38
43
  # directories, initial revisions must be specified with --version-path.
39
- # The path separator used here should be the separator specified by "version_path_separator" below.
40
- # version_locations = %(here)s/bar:%(here)s/bat:${script_location}/versions
41
-
42
- # version path separator; As mentioned above, this is the character used to split
43
- # version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
44
- # If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
45
- # Valid values for version_path_separator are:
44
+ # The path separator used here should be the separator specified by "path_separator"
45
+ # below.
46
+ # version_locations = %(here)s/bar:%(here)s/bat:%(here)s/alembic/versions
47
+
48
+ # path_separator; This indicates what character is used to split lists of file
49
+ # paths, including version_locations and prepend_sys_path within configparser
50
+ # files such as alembic.ini.
51
+ # The default rendered in new alembic.ini files is "os", which uses os.pathsep
52
+ # to provide os-dependent path splitting.
53
+ #
54
+ # Note that in order to support legacy alembic.ini files, this default does NOT
55
+ # take place if path_separator is not present in alembic.ini. If this
56
+ # option is omitted entirely, fallback logic is as follows:
57
+ #
58
+ # 1. Parsing of the version_locations option falls back to using the legacy
59
+ # "version_path_separator" key, which if absent then falls back to the legacy
60
+ # behavior of splitting on spaces and/or commas.
61
+ # 2. Parsing of the prepend_sys_path option falls back to the legacy
62
+ # behavior of splitting on spaces, commas, or colons.
46
63
  #
47
- # version_path_separator = :
48
- # version_path_separator = ;
49
- # version_path_separator = space
50
- # version_path_separator = newline
64
+ # Valid values for path_separator are:
65
+ #
66
+ # path_separator = :
67
+ # path_separator = ;
68
+ # path_separator = space
69
+ # path_separator = newline
51
70
  #
52
71
  # Use os.pathsep. Default configuration used for new projects.
53
- version_path_separator = os
72
+ path_separator = os
73
+
54
74
 
55
75
  # set to 'true' to search source files recursively
56
76
  # in each "version_locations" directory
@@ -61,6 +81,9 @@ version_path_separator = os
61
81
  # are written from script.py.mako
62
82
  # output_encoding = utf-8
63
83
 
84
+ # database URL. This is consumed by the user-maintained env.py script only.
85
+ # other means of configuring database URLs may be customized within the env.py
86
+ # file.
64
87
  sqlalchemy.url = driver://user:pass@localhost/dbname
65
88
 
66
89
 
@@ -81,7 +104,8 @@ sqlalchemy.url = driver://user:pass@localhost/dbname
81
104
  # ruff.executable = %(here)s/.venv/bin/ruff
82
105
  # ruff.options = check --fix REVISION_SCRIPT_FILENAME
83
106
 
84
- # Logging configuration
107
+ # Logging configuration. This is also consumed by the user-maintained
108
+ # env.py script only.
85
109
  [loggers]
86
110
  keys = root,sqlalchemy,alembic
87
111
 
@@ -1,8 +1,10 @@
1
1
  # A generic, single database configuration.
2
2
 
3
3
  [alembic]
4
- # path to migration scripts
5
- # Use forward slashes (/) also on windows to provide an os agnostic path
4
+ # path to migration scripts.
5
+ # this is typically a path given in POSIX (e.g. forward slashes)
6
+ # format, relative to the token %(here)s which refers to the location of this
7
+ # ini file
6
8
  script_location = ${script_location}
7
9
 
8
10
  # template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
@@ -12,9 +14,11 @@ script_location = ${script_location}
12
14
  # file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
13
15
 
14
16
  # sys.path path, will be prepended to sys.path if present.
15
- # defaults to the current working directory.
17
+ # defaults to the current working directory. for multiple paths, the path separator
18
+ # is defined by "path_separator" below.
16
19
  prepend_sys_path = .
17
20
 
21
+
18
22
  # timezone to use when rendering the date within the migration file
19
23
  # as well as the filename.
20
24
  # If specified, requires the python>=3.9 or backports.zoneinfo library and tzdata library.
@@ -36,23 +40,37 @@ prepend_sys_path = .
36
40
  # sourceless = false
37
41
 
38
42
  # version location specification; This defaults
39
- # to ${script_location}/versions. When using multiple version
43
+ # to <script_location>/versions. When using multiple version
40
44
  # directories, initial revisions must be specified with --version-path.
41
- # The path separator used here should be the separator specified by "version_path_separator" below.
42
- # version_locations = %(here)s/bar:%(here)s/bat:${script_location}/versions
43
-
44
- # version path separator; As mentioned above, this is the character used to split
45
- # version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
46
- # If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
47
- # Valid values for version_path_separator are:
45
+ # The path separator used here should be the separator specified by "path_separator"
46
+ # below.
47
+ # version_locations = %(here)s/bar:%(here)s/bat:%(here)s/alembic/versions
48
+
49
+ # path_separator; This indicates what character is used to split lists of file
50
+ # paths, including version_locations and prepend_sys_path within configparser
51
+ # files such as alembic.ini.
52
+ # The default rendered in new alembic.ini files is "os", which uses os.pathsep
53
+ # to provide os-dependent path splitting.
54
+ #
55
+ # Note that in order to support legacy alembic.ini files, this default does NOT
56
+ # take place if path_separator is not present in alembic.ini. If this
57
+ # option is omitted entirely, fallback logic is as follows:
58
+ #
59
+ # 1. Parsing of the version_locations option falls back to using the legacy
60
+ # "version_path_separator" key, which if absent then falls back to the legacy
61
+ # behavior of splitting on spaces and/or commas.
62
+ # 2. Parsing of the prepend_sys_path option falls back to the legacy
63
+ # behavior of splitting on spaces, commas, or colons.
64
+ #
65
+ # Valid values for path_separator are:
48
66
  #
49
- # version_path_separator = :
50
- # version_path_separator = ;
51
- # version_path_separator = space
52
- # version_path_separator = newline
67
+ # path_separator = :
68
+ # path_separator = ;
69
+ # path_separator = space
70
+ # path_separator = newline
53
71
  #
54
72
  # Use os.pathsep. Default configuration used for new projects.
55
- version_path_separator = os
73
+ path_separator = os
56
74
 
57
75
  # set to 'true' to search source files recursively
58
76
  # in each "version_locations" directory
@@ -63,6 +81,9 @@ version_path_separator = os
63
81
  # are written from script.py.mako
64
82
  # output_encoding = utf-8
65
83
 
84
+ # database URL. This is consumed by the user-maintained env.py script only.
85
+ # other means of configuring database URLs may be customized within the env.py
86
+ # file.
66
87
  sqlalchemy.url = driver://user:pass@localhost/dbname
67
88
 
68
89
 
@@ -83,7 +104,8 @@ sqlalchemy.url = driver://user:pass@localhost/dbname
83
104
  # ruff.executable = %(here)s/.venv/bin/ruff
84
105
  # ruff.options = check --fix REVISION_SCRIPT_FILENAME
85
106
 
86
- # Logging configuration
107
+ # Logging configuration. This is also consumed by the user-maintained
108
+ # env.py script only.
87
109
  [loggers]
88
110
  keys = root,sqlalchemy,alembic
89
111
 
@@ -1,8 +1,10 @@
1
1
  # a multi-database configuration.
2
2
 
3
3
  [alembic]
4
- # path to migration scripts
5
- # Use forward slashes (/) also on windows to provide an os agnostic path
4
+ # path to migration scripts.
5
+ # this is typically a path given in POSIX (e.g. forward slashes)
6
+ # format, relative to the token %(here)s which refers to the location of this
7
+ # ini file
6
8
  script_location = ${script_location}
7
9
 
8
10
  # template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
@@ -12,7 +14,8 @@ script_location = ${script_location}
12
14
  # file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
13
15
 
14
16
  # sys.path path, will be prepended to sys.path if present.
15
- # defaults to the current working directory.
17
+ # defaults to the current working directory. for multiple paths, the path separator
18
+ # is defined by "path_separator" below.
16
19
  prepend_sys_path = .
17
20
 
18
21
  # timezone to use when rendering the date within the migration file
@@ -36,23 +39,37 @@ prepend_sys_path = .
36
39
  # sourceless = false
37
40
 
38
41
  # version location specification; This defaults
39
- # to ${script_location}/versions. When using multiple version
42
+ # to <script_location>/versions. When using multiple version
40
43
  # directories, initial revisions must be specified with --version-path.
41
- # The path separator used here should be the separator specified by "version_path_separator" below.
42
- # version_locations = %(here)s/bar:%(here)s/bat:${script_location}/versions
43
-
44
- # version path separator; As mentioned above, this is the character used to split
45
- # version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
46
- # If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
47
- # Valid values for version_path_separator are:
44
+ # The path separator used here should be the separator specified by "path_separator"
45
+ # below.
46
+ # version_locations = %(here)s/bar:%(here)s/bat:%(here)s/alembic/versions
47
+
48
+ # path_separator; This indicates what character is used to split lists of file
49
+ # paths, including version_locations and prepend_sys_path within configparser
50
+ # files such as alembic.ini.
51
+ # The default rendered in new alembic.ini files is "os", which uses os.pathsep
52
+ # to provide os-dependent path splitting.
53
+ #
54
+ # Note that in order to support legacy alembic.ini files, this default does NOT
55
+ # take place if path_separator is not present in alembic.ini. If this
56
+ # option is omitted entirely, fallback logic is as follows:
57
+ #
58
+ # 1. Parsing of the version_locations option falls back to using the legacy
59
+ # "version_path_separator" key, which if absent then falls back to the legacy
60
+ # behavior of splitting on spaces and/or commas.
61
+ # 2. Parsing of the prepend_sys_path option falls back to the legacy
62
+ # behavior of splitting on spaces, commas, or colons.
48
63
  #
49
- # version_path_separator = :
50
- # version_path_separator = ;
51
- # version_path_separator = space
52
- # version_path_separator = newline
64
+ # Valid values for path_separator are:
65
+ #
66
+ # path_separator = :
67
+ # path_separator = ;
68
+ # path_separator = space
69
+ # path_separator = newline
53
70
  #
54
71
  # Use os.pathsep. Default configuration used for new projects.
55
- version_path_separator = os
72
+ path_separator = os
56
73
 
57
74
  # set to 'true' to search source files recursively
58
75
  # in each "version_locations" directory
@@ -63,6 +80,13 @@ version_path_separator = os
63
80
  # are written from script.py.mako
64
81
  # output_encoding = utf-8
65
82
 
83
+ # for multiple database configuration, new named sections are added
84
+ # which each include a distinct ``sqlalchemy.url`` entry. A custom value
85
+ # ``databases`` is added which indicates a listing of the per-database sections.
86
+ # The ``databases`` entry as well as the URLs present in the ``[engine1]``
87
+ # and ``[engine2]`` sections continue to be consumed by the user-maintained env.py
88
+ # script only.
89
+
66
90
  databases = engine1, engine2
67
91
 
68
92
  [engine1]
@@ -88,7 +112,8 @@ sqlalchemy.url = driver://user:pass@localhost/dbname2
88
112
  # ruff.executable = %(here)s/.venv/bin/ruff
89
113
  # ruff.options = check --fix REVISION_SCRIPT_FILENAME
90
114
 
91
- # Logging configuration
115
+ # Logging configuration. This is also consumed by the user-maintained
116
+ # env.py script only.
92
117
  [loggers]
93
118
  keys = root,sqlalchemy,alembic
94
119
 
@@ -0,0 +1 @@
1
+ pyproject configuration, based on the generic configuration.
@@ -0,0 +1,44 @@
1
+ # A generic, single database configuration.
2
+
3
+ [alembic]
4
+
5
+ # database URL. This is consumed by the user-maintained env.py script only.
6
+ # other means of configuring database URLs may be customized within the env.py
7
+ # file.
8
+ sqlalchemy.url = driver://user:pass@localhost/dbname
9
+
10
+
11
+ # Logging configuration
12
+ [loggers]
13
+ keys = root,sqlalchemy,alembic
14
+
15
+ [handlers]
16
+ keys = console
17
+
18
+ [formatters]
19
+ keys = generic
20
+
21
+ [logger_root]
22
+ level = WARNING
23
+ handlers = console
24
+ qualname =
25
+
26
+ [logger_sqlalchemy]
27
+ level = WARNING
28
+ handlers =
29
+ qualname = sqlalchemy.engine
30
+
31
+ [logger_alembic]
32
+ level = INFO
33
+ handlers =
34
+ qualname = alembic
35
+
36
+ [handler_console]
37
+ class = StreamHandler
38
+ args = (sys.stderr,)
39
+ level = NOTSET
40
+ formatter = generic
41
+
42
+ [formatter_generic]
43
+ format = %(levelname)-5.5s [%(name)s] %(message)s
44
+ datefmt = %H:%M:%S
@@ -0,0 +1,78 @@
1
+ from logging.config import fileConfig
2
+
3
+ from sqlalchemy import engine_from_config
4
+ from sqlalchemy import pool
5
+
6
+ from alembic import context
7
+
8
+ # this is the Alembic Config object, which provides
9
+ # access to the values within the .ini file in use.
10
+ config = context.config
11
+
12
+ # Interpret the config file for Python logging.
13
+ # This line sets up loggers basically.
14
+ if config.config_file_name is not None:
15
+ fileConfig(config.config_file_name)
16
+
17
+ # add your model's MetaData object here
18
+ # for 'autogenerate' support
19
+ # from myapp import mymodel
20
+ # target_metadata = mymodel.Base.metadata
21
+ target_metadata = None
22
+
23
+ # other values from the config, defined by the needs of env.py,
24
+ # can be acquired:
25
+ # my_important_option = config.get_main_option("my_important_option")
26
+ # ... etc.
27
+
28
+
29
+ def run_migrations_offline() -> None:
30
+ """Run migrations in 'offline' mode.
31
+
32
+ This configures the context with just a URL
33
+ and not an Engine, though an Engine is acceptable
34
+ here as well. By skipping the Engine creation
35
+ we don't even need a DBAPI to be available.
36
+
37
+ Calls to context.execute() here emit the given string to the
38
+ script output.
39
+
40
+ """
41
+ url = config.get_main_option("sqlalchemy.url")
42
+ context.configure(
43
+ url=url,
44
+ target_metadata=target_metadata,
45
+ literal_binds=True,
46
+ dialect_opts={"paramstyle": "named"},
47
+ )
48
+
49
+ with context.begin_transaction():
50
+ context.run_migrations()
51
+
52
+
53
+ def run_migrations_online() -> None:
54
+ """Run migrations in 'online' mode.
55
+
56
+ In this scenario we need to create an Engine
57
+ and associate a connection with the context.
58
+
59
+ """
60
+ connectable = engine_from_config(
61
+ config.get_section(config.config_ini_section, {}),
62
+ prefix="sqlalchemy.",
63
+ poolclass=pool.NullPool,
64
+ )
65
+
66
+ with connectable.connect() as connection:
67
+ context.configure(
68
+ connection=connection, target_metadata=target_metadata
69
+ )
70
+
71
+ with context.begin_transaction():
72
+ context.run_migrations()
73
+
74
+
75
+ if context.is_offline_mode():
76
+ run_migrations_offline()
77
+ else:
78
+ run_migrations_online()
@@ -0,0 +1,76 @@
1
+ [tool.alembic]
2
+
3
+ # path to migration scripts.
4
+ # this is typically a path given in POSIX (e.g. forward slashes)
5
+ # format, relative to the token %(here)s which refers to the location of this
6
+ # ini file
7
+ script_location = "${script_location}"
8
+
9
+ # template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
10
+ # Uncomment the line below if you want the files to be prepended with date and time
11
+ # see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file
12
+ # for all available tokens
13
+ # file_template = "%%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s"
14
+
15
+ # additional paths to be prepended to sys.path. defaults to the current working directory.
16
+ prepend_sys_path = [
17
+ "."
18
+ ]
19
+
20
+ # timezone to use when rendering the date within the migration file
21
+ # as well as the filename.
22
+ # If specified, requires the python>=3.9 or backports.zoneinfo library and tzdata library.
23
+ # Any required deps can installed by adding `alembic[tz]` to the pip requirements
24
+ # string value is passed to ZoneInfo()
25
+ # leave blank for localtime
26
+ # timezone =
27
+
28
+ # max length of characters to apply to the "slug" field
29
+ # truncate_slug_length = 40
30
+
31
+ # set to 'true' to run the environment during
32
+ # the 'revision' command, regardless of autogenerate
33
+ # revision_environment = false
34
+
35
+ # set to 'true' to allow .pyc and .pyo files without
36
+ # a source .py file to be detected as revisions in the
37
+ # versions/ directory
38
+ # sourceless = false
39
+
40
+ # version location specification; This defaults
41
+ # to <script_location>/versions. When using multiple version
42
+ # directories, initial revisions must be specified with --version-path.
43
+ # version_locations = [
44
+ # "%(here)s/alembic/versions",
45
+ # "%(here)s/foo/bar"
46
+ # ]
47
+
48
+
49
+ # set to 'true' to search source files recursively
50
+ # in each "version_locations" directory
51
+ # new in Alembic version 1.10
52
+ # recursive_version_locations = false
53
+
54
+ # the output encoding used when revision files
55
+ # are written from script.py.mako
56
+ # output_encoding = "utf-8"
57
+
58
+ # This section defines scripts or Python functions that are run
59
+ # on newly generated revision scripts. See the documentation for further
60
+ # detail and examples
61
+ # [[tool.alembic.post_write_hooks]]
62
+ # format using "black" - use the console_scripts runner,
63
+ # against the "black" entrypoint
64
+ # name = "black"
65
+ # type = "console_scripts"
66
+ # entrypoint = "black"
67
+ # options = "-l 79 REVISION_SCRIPT_FILENAME"
68
+ #
69
+ # [[tool.alembic.post_write_hooks]]
70
+ # lint with attempts to fix using "ruff" - use the exec runner,
71
+ # execute a binary
72
+ # name = "ruff"
73
+ # type = "exec"
74
+ # executable = "%(here)s/.venv/bin/ruff"
75
+ # options = "check --fix REVISION_SCRIPT_FILENAME"
76
+
@@ -0,0 +1,28 @@
1
+ """${message}
2
+
3
+ Revision ID: ${up_revision}
4
+ Revises: ${down_revision | comma,n}
5
+ Create Date: ${create_date}
6
+
7
+ """
8
+ from typing import Sequence, Union
9
+
10
+ from alembic import op
11
+ import sqlalchemy as sa
12
+ ${imports if imports else ""}
13
+
14
+ # revision identifiers, used by Alembic.
15
+ revision: str = ${repr(up_revision)}
16
+ down_revision: Union[str, None] = ${repr(down_revision)}
17
+ branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
18
+ depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
19
+
20
+
21
+ def upgrade() -> None:
22
+ """Upgrade schema."""
23
+ ${upgrades if upgrades else "pass"}
24
+
25
+
26
+ def downgrade() -> None:
27
+ """Downgrade schema."""
28
+ ${downgrades if downgrades else "pass"}
@@ -9,12 +9,14 @@ from sqlalchemy.testing import uses_deprecated
9
9
  from sqlalchemy.testing.config import combinations
10
10
  from sqlalchemy.testing.config import fixture
11
11
  from sqlalchemy.testing.config import requirements as requires
12
+ from sqlalchemy.testing.config import variation
12
13
 
13
14
  from .assertions import assert_raises
14
15
  from .assertions import assert_raises_message
15
16
  from .assertions import emits_python_deprecation_warning
16
17
  from .assertions import eq_
17
18
  from .assertions import eq_ignore_whitespace
19
+ from .assertions import expect_deprecated
18
20
  from .assertions import expect_raises
19
21
  from .assertions import expect_raises_message
20
22
  from .assertions import expect_sqlalchemy_deprecated
@@ -167,6 +167,10 @@ def emits_python_deprecation_warning(*messages):
167
167
  return decorate
168
168
 
169
169
 
170
+ def expect_deprecated(*messages, **kw):
171
+ return _expect_warnings(DeprecationWarning, messages, **kw)
172
+
173
+
170
174
  def expect_sqlalchemy_deprecated(*messages, **kw):
171
175
  return _expect_warnings(sa_exc.SADeprecationWarning, messages, **kw)
172
176
 
alembic/testing/env.py CHANGED
@@ -157,6 +157,7 @@ script_location = {dir_}
157
157
  sqlalchemy.url = {url}
158
158
  sqlalchemy.future = {"true" if sqlalchemy_future else "false"}
159
159
  sourceless = {"true" if sourceless else "false"}
160
+ path_separator = space
160
161
  version_locations = %(here)s/model1/ %(here)s/model2/ %(here)s/model3/ \
161
162
  {extra_version_location}
162
163
 
@@ -187,6 +188,50 @@ datefmt = %%H:%%M:%%S
187
188
  )
188
189
 
189
190
 
191
+ def _no_sql_pyproject_config(dialect="postgresql", directives=""):
192
+ """use a postgresql url with no host so that
193
+ connections guaranteed to fail"""
194
+ dir_ = _join_path(_get_staging_directory(), "scripts")
195
+
196
+ return _write_toml_config(
197
+ f"""
198
+ [tool.alembic]
199
+ script_location ="{dir_}"
200
+ {textwrap.dedent(directives)}
201
+
202
+ """,
203
+ f"""
204
+ [alembic]
205
+ sqlalchemy.url = {dialect}://
206
+
207
+ [loggers]
208
+ keys = root
209
+
210
+ [handlers]
211
+ keys = console
212
+
213
+ [logger_root]
214
+ level = WARNING
215
+ handlers = console
216
+ qualname =
217
+
218
+ [handler_console]
219
+ class = StreamHandler
220
+ args = (sys.stderr,)
221
+ level = NOTSET
222
+ formatter = generic
223
+
224
+ [formatters]
225
+ keys = generic
226
+
227
+ [formatter_generic]
228
+ format = %%(levelname)-5.5s [%%(name)s] %%(message)s
229
+ datefmt = %%H:%%M:%%S
230
+
231
+ """,
232
+ )
233
+
234
+
190
235
  def _no_sql_testing_config(dialect="postgresql", directives=""):
191
236
  """use a postgresql url with no host so that
192
237
  connections guaranteed to fail"""
@@ -226,6 +271,13 @@ datefmt = %%H:%%M:%%S
226
271
  )
227
272
 
228
273
 
274
+ def _write_toml_config(tomltext, initext):
275
+ cfg = _write_config_file(initext)
276
+ with open(cfg.toml_file_name, "w") as f:
277
+ f.write(tomltext)
278
+ return cfg
279
+
280
+
229
281
  def _write_config_file(text):
230
282
  cfg = _testing_config()
231
283
  with open(cfg.config_file_name, "w") as f:
@@ -238,7 +290,10 @@ def _testing_config():
238
290
 
239
291
  if not os.access(_get_staging_directory(), os.F_OK):
240
292
  os.mkdir(_get_staging_directory())
241
- return Config(_join_path(_get_staging_directory(), "test_alembic.ini"))
293
+ return Config(
294
+ _join_path(_get_staging_directory(), "test_alembic.ini"),
295
+ _join_path(_get_staging_directory(), "pyproject.toml"),
296
+ )
242
297
 
243
298
 
244
299
  def write_script(