from . import context
from . import op
-__version__ = "1.15.3"
+__version__ = "1.16.0"
from configparser import ConfigParser
import inspect
import os
+import re
import sys
from typing import Any
from typing import cast
),
)
+ def _get_file_separator_char(self, *names: str) -> Optional[str]:
+ for name in names:
+ separator = self.get_main_option(name)
+ if separator is not None:
+ break
+ else:
+ return None
+
+ split_on_path = {
+ "space": " ",
+ "newline": "\n",
+ "os": os.pathsep,
+ ":": ":",
+ ";": ";",
+ }
+
+ try:
+ sep = split_on_path[separator]
+ except KeyError as ke:
+ raise ValueError(
+ "'%s' is not a valid value for %s; "
+ "expected 'space', 'newline', 'os', ':', ';'"
+ % (separator, name)
+ ) from ke
+ else:
+ if name == "version_path_separator":
+ util.warn_deprecated(
+ "The version_path_separator configuration parameter "
+ "is deprecated; please use path_separator"
+ )
+ return sep
+
+ def get_version_locations_list(self) -> Optional[list[str]]:
+
+ version_locations_str = self.get_main_option("version_locations")
+
+ if version_locations_str:
+ split_char = self._get_file_separator_char(
+ "path_separator", "version_path_separator"
+ )
+
+ if split_char is None:
+
+ # legacy behaviour for backwards compatibility
+ util.warn_deprecated(
+ "No path_separator found in configuration; "
+ "falling back to legacy splitting on spaces/commas "
+ "for version_locations. Consider adding "
+ "path_separator=os to Alembic config."
+ )
+
+ _split_on_space_comma = re.compile(r", *|(?: +)")
+ return _split_on_space_comma.split(version_locations_str)
+ else:
+ return [
+ x.strip()
+ for x in version_locations_str.split(split_char)
+ if x
+ ]
+ else:
+ return None
+
+ def get_prepend_sys_paths_list(self) -> Optional[list[str]]:
+ prepend_sys_path_str = self.get_main_option("prepend_sys_path")
+
+ if prepend_sys_path_str:
+ split_char = self._get_file_separator_char("path_separator")
+
+ if split_char is None:
+
+ # legacy behaviour for backwards compatibility
+ util.warn_deprecated(
+ "No path_separator found in configuration; "
+ "falling back to legacy splitting on spaces, commas, "
+ "and colons for prepend_sys_path. Consider adding "
+ "path_separator=os to Alembic config."
+ )
+
+ _split_on_space_comma_colon = re.compile(r", *|(?: +)|\:")
+ return _split_on_space_comma_colon.split(prepend_sys_path_str)
+ else:
+ return [
+ x.strip()
+ for x in prepend_sys_path_str.split(split_char)
+ if x
+ ]
+ else:
+ return None
+
+ def get_hooks_list(self) -> list[PostWriteHookConfig]:
+ _split_on_space_comma = re.compile(r", *|(?: +)")
+
+ hook_config = self.get_section("post_write_hooks", {})
+ names = _split_on_space_comma.split(hook_config.get("hooks", ""))
+
+ hooks: list[PostWriteHookConfig] = []
+ for name in names:
+ if not name:
+ continue
+ opts = {
+ key[len(name) + 1 :]: hook_config[key]
+ for key in hook_config
+ if key.startswith(name + ".")
+ }
+
+ opts["_hook_name"] = name
+ hooks.append(opts)
+
+ return hooks
+
+
+PostWriteHookConfig = Mapping[str, str]
+
class MessagingOptions(TypedDict, total=False):
quiet: bool
from typing import cast
from typing import Iterator
from typing import List
-from typing import Mapping
from typing import Optional
from typing import Sequence
from typing import Set
from .revision import Revision
from ..config import Config
from ..config import MessagingOptions
+ from ..config import PostWriteHookConfig
from ..runtime.migration import RevisionStep
from ..runtime.migration import StampStep
_legacy_rev = re.compile(r"([a-f0-9]+)\.py$")
_slug_re = re.compile(r"\w+")
_default_file_template = "%(rev)s_%(slug)s"
-_split_on_space_comma = re.compile(r", *|(?: +)")
-
-_split_on_space_comma_colon = re.compile(r", *|(?: +)|\:")
class ScriptDirectory:
sourceless: bool = False,
output_encoding: str = "utf-8",
timezone: Optional[str] = None,
- hook_config: Optional[Mapping[str, str]] = None,
+ hooks: list[PostWriteHookConfig] = [],
recursive_version_locations: bool = False,
messaging_opts: MessagingOptions = cast(
"MessagingOptions", util.EMPTY_DICT
self.output_encoding = output_encoding
self.revision_map = revision.RevisionMap(self._load_revisions)
self.timezone = timezone
- self.hook_config = hook_config
+ self.hooks = hooks
self.recursive_version_locations = recursive_version_locations
self.messaging_opts = messaging_opts
script_location = config.get_main_option("script_location")
if script_location is None:
raise util.CommandError(
- "No 'script_location' key " "found in configuration."
+ "No 'script_location' key found in configuration."
)
truncate_slug_length: Optional[int]
tsl = config.get_main_option("truncate_slug_length")
else:
truncate_slug_length = None
- version_locations_str = config.get_main_option("version_locations")
- version_locations: Optional[List[str]]
- if version_locations_str:
- version_path_separator = config.get_main_option(
- "version_path_separator"
- )
-
- split_on_path = {
- None: None,
- "space": " ",
- "newline": "\n",
- "os": os.pathsep,
- ":": ":",
- ";": ";",
- }
-
- try:
- split_char: Optional[str] = split_on_path[
- version_path_separator
- ]
- except KeyError as ke:
- raise ValueError(
- "'%s' is not a valid value for "
- "version_path_separator; "
- "expected 'space', 'newline', 'os', ':', ';'"
- % version_path_separator
- ) from ke
- else:
- if split_char is None:
- # legacy behaviour for backwards compatibility
- version_locations = _split_on_space_comma.split(
- version_locations_str
- )
- else:
- version_locations = [
- x.strip()
- for x in version_locations_str.split(split_char)
- if x
- ]
- else:
- version_locations = None
-
- prepend_sys_path = config.get_main_option("prepend_sys_path")
+ prepend_sys_path = config.get_prepend_sys_paths_list()
if prepend_sys_path:
- sys.path[:0] = list(
- _split_on_space_comma_colon.split(prepend_sys_path)
- )
+ sys.path[:0] = prepend_sys_path
rvl = config.get_main_option("recursive_version_locations") == "true"
return ScriptDirectory(
truncate_slug_length=truncate_slug_length,
sourceless=config.get_main_option("sourceless") == "true",
output_encoding=config.get_main_option("output_encoding", "utf-8"),
- version_locations=version_locations,
+ version_locations=config.get_version_locations_list(),
timezone=config.get_main_option("timezone"),
- hook_config=config.get_section("post_write_hooks", {}),
+ hooks=config.get_hooks_list(),
recursive_version_locations=rvl,
messaging_opts=config.messaging_opts,
)
**kw,
)
- post_write_hooks = self.hook_config
+ post_write_hooks = self.hooks
if post_write_hooks:
write_hooks._run_hooks(path, post_write_hooks)
from typing import Callable
from typing import Dict
from typing import List
-from typing import Mapping
from typing import Optional
-from typing import Union
+from typing import TYPE_CHECKING
from .. import util
from ..util import compat
+if TYPE_CHECKING:
+ from ..config import PostWriteHookConfig
REVISION_SCRIPT_TOKEN = "REVISION_SCRIPT_FILENAME"
return decorate
-def _invoke(
- name: str, revision: str, options: Mapping[str, Union[str, int]]
-) -> Any:
+def _invoke(name: str, revision: str, options: PostWriteHookConfig) -> Any:
"""Invokes the formatter registered for the given name.
:param name: The name of a formatter in the registry
return hook(revision, options)
-def _run_hooks(path: str, hook_config: Mapping[str, str]) -> None:
+def _run_hooks(path: str, hooks: list[PostWriteHookConfig]) -> None:
"""Invoke hooks for a generated revision."""
- from .base import _split_on_space_comma
-
- names = _split_on_space_comma.split(hook_config.get("hooks", ""))
-
- for name in names:
- if not name:
- continue
- opts = {
- key[len(name) + 1 :]: hook_config[key]
- for key in hook_config
- if key.startswith(name + ".")
- }
- opts["_hook_name"] = name
+ for hook in hooks:
+ name = hook["_hook_name"]
try:
- type_ = opts["type"]
+ type_ = hook["type"]
except KeyError as ke:
raise util.CommandError(
f"Key {name}.type is required for post write hook {name!r}"
with util.status(
f"Running post write hook {name!r}", newline=True
):
- _invoke(type_, path, opts)
+ _invoke(type_, path, hook)
def _parse_cmdline_options(cmdline_options_str: str, path: str) -> List[str]:
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
# sys.path path, will be prepended to sys.path if present.
-# defaults to the current working directory.
+# defaults to the current working directory. for multiple paths, the path separator
+# is defined by "path_separator" below.
prepend_sys_path = .
# timezone to use when rendering the date within the migration file
# version location specification; This defaults
# to ${script_location}/versions. When using multiple version
# directories, initial revisions must be specified with --version-path.
-# The path separator used here should be the separator specified by "version_path_separator" below.
+# The path separator used here should be the separator specified by "path_separator"
+# below.
# version_locations = %(here)s/bar:%(here)s/bat:${script_location}/versions
-# version path separator; As mentioned above, this is the character used to split
-# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
-# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
-# Valid values for version_path_separator are:
+# path_separator; This indicates what character is used to split lists of file
+# paths, including version_locations and prepend_sys_path within configparser
+# files such as alembic.ini.
+# The default rendered in new alembic.ini files is "os", which uses os.pathsep
+# to provide os-dependent path splitting.
#
-# version_path_separator = :
-# version_path_separator = ;
-# version_path_separator = space
-# version_path_separator = newline
+# Note that in order to support legacy alembic.ini files, this default does NOT
+# take place if path_separator is not present in alembic.ini. If this
+# option is omitted entirely, fallback logic is as follows:
+#
+# 1. Parsing of the version_locations option falls back to using the legacy
+# "version_path_separator" key, which if absent then falls back to the legacy
+# behavior of splitting on spaces and/or commas.
+# 2. Parsing of the prepend_sys_path option falls back to the legacy
+# behavior of splitting on spaces, commas, or colons.
+#
+# Valid values for path_separator are:
+#
+# path_separator = :
+# path_separator = ;
+# path_separator = space
+# path_separator = newline
#
# Use os.pathsep. Default configuration used for new projects.
-version_path_separator = os
+path_separator = os
+
# set to 'true' to search source files recursively
# in each "version_locations" directory
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
# sys.path path, will be prepended to sys.path if present.
-# defaults to the current working directory.
+# defaults to the current working directory. for multiple paths, the path separator
+# is defined by "path_separator" below.
prepend_sys_path = .
+
# timezone to use when rendering the date within the migration file
# as well as the filename.
# If specified, requires the python>=3.9 or backports.zoneinfo library and tzdata library.
# version location specification; This defaults
# to ${script_location}/versions. When using multiple version
# directories, initial revisions must be specified with --version-path.
-# The path separator used here should be the separator specified by "version_path_separator" below.
+# The path separator used here should be the separator specified by "path_separator"
+# below.
# version_locations = %(here)s/bar:%(here)s/bat:${script_location}/versions
-# version path separator; As mentioned above, this is the character used to split
-# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
-# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
-# Valid values for version_path_separator are:
+# path_separator; This indicates what character is used to split lists of file
+# paths, including version_locations and prepend_sys_path within configparser
+# files such as alembic.ini.
+# The default rendered in new alembic.ini files is "os", which uses os.pathsep
+# to provide os-dependent path splitting.
+#
+# Note that in order to support legacy alembic.ini files, this default does NOT
+# take place if path_separator is not present in alembic.ini. If this
+# option is omitted entirely, fallback logic is as follows:
+#
+# 1. Parsing of the version_locations option falls back to using the legacy
+# "version_path_separator" key, which if absent then falls back to the legacy
+# behavior of splitting on spaces and/or commas.
+# 2. Parsing of the prepend_sys_path option falls back to the legacy
+# behavior of splitting on spaces, commas, or colons.
+#
+# Valid values for path_separator are:
#
-# version_path_separator = :
-# version_path_separator = ;
-# version_path_separator = space
-# version_path_separator = newline
+# path_separator = :
+# path_separator = ;
+# path_separator = space
+# path_separator = newline
#
# Use os.pathsep. Default configuration used for new projects.
-version_path_separator = os
+path_separator = os
# set to 'true' to search source files recursively
# in each "version_locations" directory
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
# sys.path path, will be prepended to sys.path if present.
-# defaults to the current working directory.
+# defaults to the current working directory. for multiple paths, the path separator
+# is defined by "path_separator" below.
prepend_sys_path = .
# timezone to use when rendering the date within the migration file
# version location specification; This defaults
# to ${script_location}/versions. When using multiple version
# directories, initial revisions must be specified with --version-path.
-# The path separator used here should be the separator specified by "version_path_separator" below.
+# The path separator used here should be the separator specified by "path_separator"
+# below.
# version_locations = %(here)s/bar:%(here)s/bat:${script_location}/versions
-# version path separator; As mentioned above, this is the character used to split
-# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
-# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
-# Valid values for version_path_separator are:
+# path_separator; This indicates what character is used to split lists of file
+# paths, including version_locations and prepend_sys_path within configparser
+# files such as alembic.ini.
+# The default rendered in new alembic.ini files is "os", which uses os.pathsep
+# to provide os-dependent path splitting.
#
-# version_path_separator = :
-# version_path_separator = ;
-# version_path_separator = space
-# version_path_separator = newline
+# Note that in order to support legacy alembic.ini files, this default does NOT
+# take place if path_separator is not present in alembic.ini. If this
+# option is omitted entirely, fallback logic is as follows:
+#
+# 1. Parsing of the version_locations option falls back to using the legacy
+# "version_path_separator" key, which if absent then falls back to the legacy
+# behavior of splitting on spaces and/or commas.
+# 2. Parsing of the prepend_sys_path option falls back to the legacy
+# behavior of splitting on spaces, commas, or colons.
+#
+# Valid values for path_separator are:
+#
+# path_separator = :
+# path_separator = ;
+# path_separator = space
+# path_separator = newline
#
# Use os.pathsep. Default configuration used for new projects.
-version_path_separator = os
+path_separator = os
# set to 'true' to search source files recursively
# in each "version_locations" directory
from .assertions import emits_python_deprecation_warning
from .assertions import eq_
from .assertions import eq_ignore_whitespace
+from .assertions import expect_deprecated
from .assertions import expect_raises
from .assertions import expect_raises_message
from .assertions import expect_sqlalchemy_deprecated
return decorate
+def expect_deprecated(*messages, **kw):
+ return _expect_warnings(DeprecationWarning, messages, **kw)
+
+
def expect_sqlalchemy_deprecated(*messages, **kw):
return _expect_warnings(sa_exc.SADeprecationWarning, messages, **kw)
sqlalchemy.url = {url}
sqlalchemy.future = {"true" if sqlalchemy_future else "false"}
sourceless = {"true" if sourceless else "false"}
+path_separator = space
version_locations = %(here)s/model1/ %(here)s/model2/ %(here)s/model3/ \
{extra_version_location}
from .messaging import obfuscate_url_pw as obfuscate_url_pw
from .messaging import status as status
from .messaging import warn as warn
+from .messaging import warn_deprecated as warn_deprecated
from .messaging import write_outstream as write_outstream
from .pyfiles import coerce_resource_to_filename as coerce_resource_to_filename
from .pyfiles import load_python_file as load_python_file
warnings.warn(msg, UserWarning, stacklevel=stacklevel)
+def warn_deprecated(msg: str, stacklevel: int = 2) -> None:
+ warnings.warn(msg, DeprecationWarning, stacklevel=stacklevel)
+
+
def msg(
msg: str, newline: bool = True, flush: bool = False, quiet: bool = False
) -> None:
to multiple directories; we'll also state the current ``versions``
directory as one of them::
- # A separator for the location paths must be defined first.
- version_path_separator = os # Use os.pathsep.
+ # A separator for the location paths needs to be defined
+ path_separator = os # Use os.pathsep.
# version location specification; this defaults
# to foo/versions. When using multiple version
# directories, initial revisions must be specified with --version-path
==========
.. changelog::
- :version: 1.15.3
+ :version: 1.16.0
:include_notes_from: unreleased
.. changelog::
# The path separator used here should be the separator specified by "version_path_separator" below.
# version_locations = %(here)s/bar:%(here)s/bat:${script_location}/versions
- # version path separator; As mentioned above, this is the character used to split
- # version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
- # If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
- # Valid values for version_path_separator are:
+ # path_separator (New in Alembic 1.16.0, supersedes version_path_separator);
+ # This indicates what character is used to
+ # split lists of file paths, including version_locations and prepend_sys_path
+ # within configparser files such as alembic.ini.
#
- # version_path_separator = :
- # version_path_separator = ;
- # version_path_separator = space
- # version_path_separator = newline
- version_path_separator = os # Use os.pathsep. Default configuration used for new projects.
+ # The default rendered in new alembic.ini files is "os", which uses os.pathsep
+ # to provide os-dependent path splitting.
+ #
+ # Note that in order to support legacy alembic.ini files, this default does NOT
+ # take place if path_separator is not present in alembic.ini. If this
+ # option is omitted entirely, fallback logic is as follows:
+ #
+ # 1. Parsing of the version_locations option falls back to using the legacy
+ # "version_path_separator" key, which if absent then falls back to the legacy
+ # behavior of splitting on spaces and/or commas.
+ # 2. Parsing of the prepend_sys_path option falls back to the legacy
+ # behavior of splitting on spaces, commas, or colons.
+ #
+ # Valid values for path_separator are:
+ #
+ # path_separator = :
+ # path_separator = ;
+ # path_separator = space
+ # path_separator = newline
+ #
+ # Use os.pathsep. Default configuration used for new projects.
+ path_separator = os
# set to 'true' to search source files recursively
# in each "version_locations" directory
* ``timezone`` - an optional timezone name (e.g. ``UTC``, ``EST5EDT``, etc.)
that will be applied to the timestamp which renders inside the migration
file's comment as well as within the filename. This option requires Python>=3.9
- or installing the ``backports.zoneinfo`` library and the ``tzdata`` library.
+ or installing the ``backports.zoneinfo`` library and the ``tzdata`` library.
If ``timezone`` is specified, the create date object is no longer derived
from ``datetime.datetime.now()`` and is instead generated as::
allow revisions to exist in multiple directories simultaneously.
See :ref:`multiple_bases` for examples.
-* ``version_path_separator`` - a separator of ``version_locations`` paths.
- It should be defined if multiple ``version_locations`` is used.
- See :ref:`multiple_bases` for examples.
+* ``path_separator`` - a separator character for the ``version_locations``
+ and ``prepend_sys_path`` path lists. See :ref:`multiple_bases` for examples.
* ``recursive_version_locations`` - when set to 'true', revision files
are searched recursively in each "version_locations" directory.
--- /dev/null
+.. change::
+ :tags: bug, environment
+ :tickets: 1330
+
+ Added new option to the ConfigParser config (typically via ``alembic.ini``)
+ ``path_separator``. This new option supersedes the previous similar
+ option ``version_path_separator``. The new ``path_separator`` option
+ applies to the path splitting mechanism of both the ``version_locations``
+ option as well as the ``prepend_sys_path`` option, and in newly
+ rendered ``alembic.ini`` files will use the value ``os``, which means to
+ use the operating system path separator when splitting these string values
+ into a list of paths.
+
+ The new attribute applies necessary os-dependent path splitting to the
+ ``prepend_sys_path`` option so that windows paths which contain drive
+ letters with colons are not inadvertently split, whereas previously
+ os-dependent path splitting were only available for the
+ ``version_locations`` option.
+
+ Existing installations that do not have ``path_separator`` present
+ will continue to make use of ``version_path_separator`` when parsing the
+ ``version_locations`` option, or splitting on spaces / commas if
+ ``version_path_separator`` is also not present. ``prepend_sys_path`` will
+ continue to be split on spaces/commas/colons if ``path_separator`` is
+ not present. Under all of these fallback conditions, a deprecation
+ warning is now emitted encouraging to set ``path_separator``.
+
+ Pull request courtesy Mike Werezak.
\ No newline at end of file
import os
+import sys
import tempfile
from alembic import config
"|",
"/foo|/bar",
ValueError(
- "'|' is not a valid value for version_path_separator; "
+ "'|' is not a valid value for path_separator; "
"expected 'space', 'newline', 'os', ':', ';'"
),
),
cfg = config.Config()
if separator is not None:
cfg.set_main_option(
- "version_path_separator",
+ "path_separator",
separator,
)
cfg.set_main_option("script_location", tempfile.gettempdir())
with expect_raises_message(ValueError, message, text_exact=True):
ScriptDirectory.from_config(cfg)
else:
- s = ScriptDirectory.from_config(cfg)
+ if separator is None:
+ with testing.expect_deprecated(
+ "No path_separator found in configuration; "
+ "falling back to legacy splitting on spaces/commas "
+ "for version_locations"
+ ):
+ s = ScriptDirectory.from_config(cfg)
+ else:
+ s = ScriptDirectory.from_config(cfg)
+
eq_(s.version_locations, expected_result)
+ @testing.combinations(
+ (
+ "legacy raw string 1",
+ None,
+ "/foo",
+ ["/foo"],
+ ),
+ (
+ "legacy raw string 2",
+ None,
+ "/foo /bar",
+ ["/foo", "/bar"],
+ ),
+ (
+ "legacy raw string 3",
+ "space",
+ "/foo",
+ ["/foo"],
+ ),
+ (
+ "legacy raw string 4",
+ "space",
+ "/foo /bar",
+ ["/foo", "/bar"],
+ ),
+ (
+ "multiline string 1",
+ "newline",
+ " /foo \n/bar ",
+ ["/foo", "/bar"],
+ ),
+ (
+ "Linux pathsep 1",
+ ":",
+ "/Project A",
+ ["/Project A"],
+ ),
+ (
+ "Linux pathsep 2",
+ ":",
+ "/Project A:/Project B",
+ ["/Project A", "/Project B"],
+ ),
+ (
+ "Windows pathsep 1",
+ ";",
+ r"C:\Project A",
+ [r"C:\Project A"],
+ ),
+ (
+ "Windows pathsep 2",
+ ";",
+ r"C:\Project A;C:\Project B",
+ [r"C:\Project A", r"C:\Project B"],
+ ),
+ (
+ "os pathsep",
+ "os",
+ r"path_number_one%(sep)spath_number_two%(sep)s"
+ % {"sep": os.pathsep},
+ [r"path_number_one", r"path_number_two"],
+ ),
+ (
+ "invalid pathsep 2",
+ "|",
+ "/foo|/bar",
+ ValueError(
+ "'|' is not a valid value for path_separator; "
+ "expected 'space', 'newline', 'os', ':', ';'"
+ ),
+ ),
+ id_="iaaa",
+ argnames="separator, string_value, expected_result",
+ )
+ def test_prepend_sys_path_locations(
+ self, separator, string_value, expected_result
+ ):
+ cfg = config.Config()
+ if separator is not None:
+ cfg.set_main_option(
+ "path_separator",
+ separator,
+ )
+ cfg.set_main_option("script_location", tempfile.gettempdir())
+ cfg.set_main_option("prepend_sys_path", string_value)
+
+ if isinstance(expected_result, ValueError):
+ message = str(expected_result)
+ with expect_raises_message(ValueError, message, text_exact=True):
+ ScriptDirectory.from_config(cfg)
+ else:
+ restore_path = list(sys.path)
+ try:
+ sys.path.clear()
+
+ if separator is None:
+ with testing.expect_deprecated(
+ "No path_separator found in configuration; "
+ "falling back to legacy splitting on spaces, commas, "
+ "and colons for prepend_sys_path"
+ ):
+ ScriptDirectory.from_config(cfg)
+ else:
+ ScriptDirectory.from_config(cfg)
+ eq_(sys.path, expected_result)
+ finally:
+ sys.path = restore_path
+
+ def test_version_path_separator_deprecation_warning(self):
+ cfg = config.Config()
+ cfg.set_main_option("script_location", tempfile.gettempdir())
+ cfg.set_main_option("version_path_separator", "space")
+ cfg.set_main_option(
+ "version_locations", "/path/one /path/two /path:/three"
+ )
+ with testing.expect_deprecated(
+ "The version_path_separator configuration parameter is "
+ "deprecated; please use path_separator"
+ ):
+ script = ScriptDirectory.from_config(cfg)
+ eq_(
+ script.version_locations,
+ ["/path/one", "/path/two", "/path:/three"],
+ )
+
class StdoutOutputEncodingTest(TestBase):
def test_plain(self):
@testing.combinations(
(
".",
+ None,
["."],
),
- ("/tmp/foo:/tmp/bar", ["/tmp/foo", "/tmp/bar"]),
- ("/tmp/foo /tmp/bar", ["/tmp/foo", "/tmp/bar"]),
- ("/tmp/foo,/tmp/bar", ["/tmp/foo", "/tmp/bar"]),
- (". /tmp/foo", [".", "/tmp/foo"]),
+ ("/tmp/foo:/tmp/bar", None, ["/tmp/foo", "/tmp/bar"]),
+ ("/tmp/foo:/tmp/bar", ":", ["/tmp/foo", "/tmp/bar"]),
+ ("/tmp/foo /tmp/bar", None, ["/tmp/foo", "/tmp/bar"]),
+ ("/tmp/foo,/tmp/bar", None, ["/tmp/foo", "/tmp/bar"]),
+ (". /tmp/foo", None, [".", "/tmp/foo"]),
+ (". /tmp/foo", "space", [".", "/tmp/foo"]),
)
- def test_sys_path_prepend(self, config_value, expected):
+ def test_sys_path_prepend(self, config_value, path_separator, expected):
+ if path_separator is not None:
+ self.cfg.set_main_option("path_separator", path_separator)
self.cfg.set_main_option("prepend_sys_path", config_value)
- script = ScriptDirectory.from_config(self.cfg)
+ if path_separator is None:
+ with testing.expect_deprecated(
+ "No path_separator found in configuration;"
+ ):
+ script = ScriptDirectory.from_config(self.cfg)
+ else:
+ script = ScriptDirectory.from_config(self.cfg)
env = EnvironmentContext(self.cfg, script)
target = os.path.abspath(_get_staging_directory())