From 822b6ac461697700782513a3641502d98063d122 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sun, 2 Oct 2022 21:39:36 -0400 Subject: [PATCH] fix: */foo matches "foo/x.py", to help with combining relative file names. #991 --- coverage/files.py | 2 ++ coverage/misc.py | 2 +- tests/test_files.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/coverage/files.py b/coverage/files.py index 4475f2f11..87a18bc2a 100644 --- a/coverage/files.py +++ b/coverage/files.py @@ -296,6 +296,8 @@ def fnmatches_to_regex(patterns, case_insensitive=False, partial=False): """ regexes = (fnmatch.translate(pattern) for pattern in patterns) + # */ at the start should also match nothing. + regexes = (re.sub(r"^\(\?s:\.\*(\\\\|/)", r"(?s:^(.*\1)?", regex) for regex in regexes) # Be agnostic: / can mean backslash or slash. regexes = (re.sub(r"/", r"[\\\\/]", regex) for regex in regexes) diff --git a/coverage/misc.py b/coverage/misc.py index e9b1b8eba..98a5d139f 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -181,7 +181,7 @@ def bool_or_none(b): def join_regex(regexes): - """Combine a list of regexes into one that matches any of them.""" + """Combine a series of regexes into one that matches any of them.""" return "|".join(f"(?:{r})" for r in regexes) diff --git a/tests/test_files.py b/tests/test_files.py index 58084f7c7..3f3caae6b 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -144,6 +144,12 @@ def test_flat_rootname(original, flat): ["abc/foo/hi.py", "ABC/foo/bar/hi.py", r"ABC\foo/bar/hi.py"], ["abcd/foo.py", "xabc/hi.py"], ), + ( + ["*/foo"], False, True, + ["abc/foo/hi.py", "foo/hi.py"], + ["abc/xfoo/hi.py"], + ), + ]) def test_fnmatches_to_regex(patterns, case_insensitive, partial, matches, nomatches): regex = fnmatches_to_regex(patterns, case_insensitive=case_insensitive, partial=partial) @@ -386,6 +392,30 @@ def test_linux_on_windows(self, paths, rel_yn): "project\\module\\tests\\file.py", ) + @pytest.mark.parametrize("paths", lin_win_paths) + def test_relative_windows_on_linux(self, paths): + # https://github.com/nedbat/coveragepy/issues/991 + aliases = PathAliases(relative=True) + for path in paths: + aliases.add(path, "project/module") + self.assert_mapped( + aliases, + r"project\module\tests\file.py", + r"project/module/tests/file.py", + ) + + @pytest.mark.parametrize("paths", lin_win_paths) + def test_relative_linux_on_windows(self, paths): + # https://github.com/nedbat/coveragepy/issues/991 + aliases = PathAliases(relative=True) + for path in paths: + aliases.add(path, r"project\module") + self.assert_mapped( + aliases, + r"project/module/tests/file.py", + r"project\module\tests\file.py", + ) + def test_multiple_wildcard(self, rel_yn): aliases = PathAliases(relative=rel_yn) aliases.add('/home/jenkins/*/a/*/b/*/django', './django')