From: Mike Bayer Date: Tue, 20 May 2025 19:17:54 +0000 (-0400) Subject: make sure no-ini-file actually works X-Git-Tag: rel_1_16_0~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a7117a43f6cc2b55fda45d4231d3f3b2a8c50d78;p=thirdparty%2Fsqlalchemy%2Falembic.git make sure no-ini-file actually works because Config has an alembic.ini path in it by default, if the file doesnt exist it will raise when you call get_main_option(). make sure no alembic function calls upon get_main_option() directly at all so that configparser is entirely not required Change-Id: Idae5979778e67075b3b233c902bfa4c70a2e614e --- diff --git a/alembic/command.py b/alembic/command.py index dd507a8a..9b1a44cb 100644 --- a/alembic/command.py +++ b/alembic/command.py @@ -271,7 +271,9 @@ def revision( process_revision_directives=process_revision_directives, ) - environment = util.asbool(config.get_main_option("revision_environment")) + environment = util.asbool( + config.get_alembic_option("revision_environment") + ) if autogenerate: environment = True @@ -411,7 +413,9 @@ def merge( # e.g. multiple databases } - environment = util.asbool(config.get_main_option("revision_environment")) + environment = util.asbool( + config.get_alembic_option("revision_environment") + ) if environment: @@ -584,7 +588,7 @@ def history( base = head = None environment = ( - util.asbool(config.get_main_option("revision_environment")) + util.asbool(config.get_alembic_option("revision_environment")) or indicate_current ) diff --git a/alembic/config.py b/alembic/config.py index 7a555faf..f1579928 100644 --- a/alembic/config.py +++ b/alembic/config.py @@ -501,7 +501,9 @@ class Config: def get_version_locations_list(self) -> Optional[list[str]]: - version_locations_str = self.get_main_option("version_locations") + version_locations_str = self.file_config.get( + self.config_ini_section, "version_locations", fallback=None + ) if version_locations_str: split_char = self._get_file_separator_char( @@ -530,8 +532,9 @@ class Config: return self.toml_alembic_config.get("version_locations", None) def get_prepend_sys_paths_list(self) -> Optional[list[str]]: - - prepend_sys_path_str = self.get_main_option("prepend_sys_path") + prepend_sys_path_str = self.file_config.get( + self.config_ini_section, "prepend_sys_path", fallback=None + ) if prepend_sys_path_str: split_char = self._get_file_separator_char("path_separator") diff --git a/tests/test_config.py b/tests/test_config.py index cf85f516..411aa112 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,7 +1,9 @@ import os +import pathlib import sys import tempfile +from alembic import command from alembic import config from alembic import testing from alembic import util @@ -12,7 +14,9 @@ from alembic.testing import assert_raises_message from alembic.testing import eq_ from alembic.testing import mock from alembic.testing.assertions import expect_raises_message +from alembic.testing.env import _get_staging_directory from alembic.testing.env import _no_sql_testing_config +from alembic.testing.env import _testing_config from alembic.testing.env import _write_config_file from alembic.testing.env import clear_staging_env from alembic.testing.env import staging_env @@ -337,6 +341,65 @@ class ConfigTest(TestBase): ) +class PyprojectConfigTest(TestBase): + @testing.fixture + def pyproject_only_env(self): + cfg = _testing_config() + path = pathlib.Path(_get_staging_directory(), "scripts") + command.init(cfg, str(path), template="pyproject") + cfg._config_file_path.unlink() + yield cfg + clear_staging_env() + + def test_revision_command_no_alembicini(self, pyproject_only_env): + cfg = pyproject_only_env + path = pathlib.Path(_get_staging_directory(), "scripts") + pyproject_path = path.parent / "pyproject.toml" + eq_(pyproject_path, cfg._toml_file_path) + assert pyproject_path.exists() + assert not cfg._config_file_path.exists() + + # the cfg contains the path to alembic.ini but the file + # is not present. the idea here is that all the required config + # should go to pyproject.toml first before raising. + + ScriptDirectory.from_config(cfg) + + command.revision(cfg, message="x") + + command.history(cfg) + + def test_no_config_at_all_still_raises(self, pyproject_only_env): + cfg = pyproject_only_env + cfg._toml_file_path.unlink() + assert not cfg._toml_file_path.exists() + assert not cfg._config_file_path.exists() + + with expect_raises_message( + util.CommandError, + r"No 'script_location' key found in configuration.", + ): + ScriptDirectory.from_config(cfg) + + def test_get_main_option_raises(self, pyproject_only_env): + cfg = pyproject_only_env + + with expect_raises_message( + util.CommandError, + r"No config file '.*test_alembic.ini' found, " + r"or file has no '\[alembic\]' section", + ): + cfg.get_main_option("asdf") + + def test_get_main_ini_added(self, pyproject_only_env): + cfg = pyproject_only_env + + with cfg._config_file_path.open("w") as file_: + file_.write("[alembic]\nasdf = back_at_ya") + + eq_(cfg.get_main_option("asdf"), "back_at_ya") + + class StdoutOutputEncodingTest(TestBase): def test_plain(self): stdout = mock.Mock(encoding="latin-1")