diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index f61496050..88331dd4b 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -19,7 +19,7 @@ import py from _pytest.assertion import util from _pytest.pathlib import PurePath from _pytest.compat import spec_from_file_location -from _pytest.paths import fnmatch_ex +from _pytest.pathlib import fnmatch_ex # pytest caches rewritten pycs in __pycache__. if hasattr(imp, "get_tag"): diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index be291bbff..eaa470fbf 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -15,9 +15,8 @@ import pytest import json import shutil -from . import paths from .compat import _PY2 as PY2 -from .pathlib import Path +from .pathlib import Path, resolve_from_str README_CONTENT = u"""\ # pytest cache directory # @@ -46,7 +45,7 @@ class Cache(object): @staticmethod def cache_dir_from_config(config): - return paths.resolve_from_str(config.getini("cache_dir"), config.rootdir) + return resolve_from_str(config.getini("cache_dir"), config.rootdir) def warn(self, fmt, **args): from _pytest.warnings import _issue_config_warning diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 2d9f1d640..a86f1e40a 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -4,14 +4,19 @@ import errno import atexit import operator import six +import sys from functools import reduce import uuid from six.moves import map import itertools import shutil +from os.path import expanduser, expandvars, isabs, sep +from posixpath import sep as posix_sep +import fnmatch from .compat import PY36 + if PY36: from pathlib import Path, PurePath else: @@ -181,3 +186,47 @@ def make_numbered_dir_with_cleanup(root, prefix, keep, lock_timeout): return p assert e is not None raise e + + +def resolve_from_str(input, root): + assert not isinstance(input, Path), "would break on py2" + root = Path(root) + input = expanduser(input) + input = expandvars(input) + if isabs(input): + return Path(input) + else: + return root.joinpath(input) + + +def fnmatch_ex(pattern, path): + """FNMatcher port from py.path.common which works with PurePath() instances. + + The difference between this algorithm and PurePath.match() is that the latter matches "**" glob expressions + for each part of the path, while this algorithm uses the whole path instead. + + For example: + "tests/foo/bar/doc/test_foo.py" matches pattern "tests/**/doc/test*.py" with this algorithm, but not with + PurePath.match(). + + This algorithm was ported to keep backward-compatibility with existing settings which assume paths match according + this logic. + + References: + * https://bugs.python.org/issue29249 + * https://bugs.python.org/issue34731 + """ + path = PurePath(path) + iswin32 = sys.platform.startswith("win") + + if iswin32 and sep not in pattern and posix_sep in pattern: + # Running on Windows, the pattern has no Windows path separators, + # and the pattern has one or more Posix path separators. Replace + # the Posix path separators with the Windows path separator. + pattern = pattern.replace(posix_sep, sep) + + if sep not in pattern: + name = path.name + else: + name = six.text_type(path) + return fnmatch.fnmatch(name, pattern) diff --git a/src/_pytest/paths.py b/src/_pytest/paths.py deleted file mode 100644 index 3507cae7f..000000000 --- a/src/_pytest/paths.py +++ /dev/null @@ -1,52 +0,0 @@ -from os.path import expanduser, expandvars, isabs, sep -from posixpath import sep as posix_sep -import fnmatch -import sys - -import six - -from .pathlib import Path, PurePath - - -def resolve_from_str(input, root): - assert not isinstance(input, Path), "would break on py2" - root = Path(root) - input = expanduser(input) - input = expandvars(input) - if isabs(input): - return Path(input) - else: - return root.joinpath(input) - - -def fnmatch_ex(pattern, path): - """FNMatcher port from py.path.common which works with PurePath() instances. - - The difference between this algorithm and PurePath.match() is that the latter matches "**" glob expressions - for each part of the path, while this algorithm uses the whole path instead. - - For example: - "tests/foo/bar/doc/test_foo.py" matches pattern "tests/**/doc/test*.py" with this algorithm, but not with - PurePath.match(). - - This algorithm was ported to keep backward-compatibility with existing settings which assume paths match according - this logic. - - References: - * https://bugs.python.org/issue29249 - * https://bugs.python.org/issue34731 - """ - path = PurePath(path) - iswin32 = sys.platform.startswith("win") - - if iswin32 and sep not in pattern and posix_sep in pattern: - # Running on Windows, the pattern has no Windows path separators, - # and the pattern has one or more Posix path separators. Replace - # the Posix path separators with the Windows path separator. - pattern = pattern.replace(posix_sep, sep) - - if sep not in pattern: - name = path.name - else: - name = six.text_type(path) - return fnmatch.fnmatch(name, pattern) diff --git a/testing/test_paths.py b/testing/test_paths.py index 2bb1335fb..2eb07bbd4 100644 --- a/testing/test_paths.py +++ b/testing/test_paths.py @@ -4,7 +4,7 @@ import py import pytest -from _pytest.paths import fnmatch_ex +from _pytest.pathlib import fnmatch_ex class TestPort: