From b2d780d753c0e5e9b6543e0416445c0ad0bda989 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 11 Jul 2023 19:07:53 +0200 Subject: [PATCH 1/2] Add regression test for path w/ trailing wildcard This patch demonstrates a corner case in the path glob matcher. Specifically, it documents how a single trailing asterisk is supposed to be treated as opposed to a double asterisk. With [[1]], a trailing `/*` is interpreted as an equivalent of `/**`. The commit add a case that shows that `/*` shouldn't be greedy as described in the docs [[2]][[3]]. See also the observations in the bug report ticket [[4]]. [1]: https://github.com/nedbat/coveragepy/commit/ec6205a8de972af6a09453235d02a7ebea6aea8e [2]: https://coverage.rtfd.io/en/stable/source.html#file-patterns [3]: https://coverage.rtfd.io/en/7.2.7/migrating.html#migrating-to-coverage-py-7-x [4]: https://github.com/nedbat/coveragepy/issues/1407#issuecomment-1631085209 --- tests/test_files.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/test_files.py b/tests/test_files.py index 7424775b3..9420eeb05 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -348,11 +348,14 @@ def test_glob_matcher(self) -> None: (self.make_file("sub/file1.py"), True), (self.make_file("sub/file2.c"), False), (self.make_file("sub2/file3.h"), True), + (self.make_file("sub2/sub/file3.h"), False), (self.make_file("sub3/file4.py"), True), (self.make_file("sub3/file5.c"), False), + (self.make_file("sub4/file3.h"), True), + (self.make_file("sub4/sub/file3.h"), True), ] - fnm = GlobMatcher(["*.py", "*/sub2/*"]) - assert fnm.info() == ["*.py", "*/sub2/*"] + fnm = GlobMatcher(["*.py", "*/sub2/*", "*/sub4/**"]) + assert fnm.info() == ["*.py", "*/sub2/*", "*/sub4/**"] for filepath, matches in matches_to_try: self.assertMatches(fnm, filepath, matches) From 5e2d1e57ec441ae2a3b2099d7c6b8db6c6fc5691 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 11 Jul 2023 21:52:27 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9B=20Fix=20trailing=20single=20as?= =?UTF-8?q?terisk=20matching=20subdirs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch aims to prevent path patterns ending with `/*` from being greedy and interpreted the same as `/**`. After applying it, that trailing asterisk only matches one file or directory but not nested ones. --- coverage/files.py | 2 +- tests/test_report.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/coverage/files.py b/coverage/files.py index aade31afd..2daa4a59e 100644 --- a/coverage/files.py +++ b/coverage/files.py @@ -316,7 +316,7 @@ def sep(s: str) -> str: (r"\*\*+[^/]+", None), # Can't have **x (r"\*\*/\*\*", None), # Can't have **/** (r"^\*+/", r"(.*[/\\\\])?"), # ^*/ matches any prefix-slash, or nothing. - (r"/\*+$", r"[/\\\\].*"), # /*$ matches any slash-suffix. + (r"/\*\*+$", r"[/\\\\].*"), # /**$ matches any slash-suffix. (r"\*\*/", r"(.*[/\\\\])?"), # **/ matches any subdirs, including none (r"/", r"[/\\\\]"), # / matches either slash or backslash (r"\*", r"[^/\\\\]*"), # * matches any number of non slash-likes diff --git a/tests/test_report.py b/tests/test_report.py index 51a4fc683..316472537 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -107,7 +107,7 @@ def test_report_omitting(self) -> None: self.make_mycode() cov = coverage.Coverage() self.start_import_stop(cov, "mycode") - report = self.get_report(cov, omit=[f"{TESTS_DIR}/*", "*/site-packages/*"]) + report = self.get_report(cov, omit=[f"{TESTS_DIR}/**", "*/site-packages/**"]) # Name Stmts Miss Cover # -------------------------------