diff --git a/CHANGES.rst b/CHANGES.rst index f056ddd6d..781d44419 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -20,8 +20,15 @@ development at the same time, such as 4.5.x and 5.0. Unreleased ---------- -Nothing yet. +- The semantics of stars in file patterns has been clarified in the docs. A + leading or trailing star component matches any number of path components, + like a double star would. This is different than the behavior of a star in + the middle of a pattern. This discrepancy was `identified by Sviatoslav + Sydorenko `_, who `provided patient detailed diagnosis + `_ and graciously agreed to a pragmatic resolution. +.. _starbad: https://github.com/nedbat/coveragepy/issues/1407#issuecomment-1631085209 +.. _pull 1650: https://github.com/nedbat/coveragepy/pull/1650 .. scriv-start-here @@ -32,7 +39,7 @@ Version 7.3.0 — 2023-08-12 - Added a :meth:`.Coverage.collect` context manager to start and stop coverage data collection. - + - Dropped support for Python 3.7. - Fix: in unusual circumstances, SQLite cannot be set to asynchronous mode. diff --git a/doc/source.rst b/doc/source.rst index 44b84f001..72bcada2a 100644 --- a/doc/source.rst +++ b/doc/source.rst @@ -181,11 +181,12 @@ File patterns File path patterns are used for include and omit, and for combining path remapping. They follow common shell syntax: -- ``*`` matches any number of file name characters, not including the directory - separator. - - ``?`` matches a single file name character. +- ``*`` matches any number of file name characters, not including the directory + separator. As a special case, if a pattern starts with ``*/``, it is treated + as ``**/``, and if a pattern ends with ``/*``, it is treated as ``/**`. + - ``**`` matches any number of nested directory names, including none. - Both ``/`` and ``\`` will match either a slash or a backslash, to make diff --git a/tests/test_files.py b/tests/test_files.py index ae3a5e2b2..09da65c20 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -235,9 +235,24 @@ def globs_to_regex_params( ), globs_to_regex_params( ["*/foo"], case_insensitive=False, partial=True, - matches=["abc/foo/hi.py", "foo/hi.py"], + matches=["abc/foo/hi.py", "foo/hi.py", "abc/def/foo/hi.py"], nomatches=["abc/xfoo/hi.py"], ), + globs_to_regex_params( + ["*c/foo"], case_insensitive=False, partial=True, + matches=["abc/foo/hi.py"], + nomatches=["abc/xfoo/hi.py", "foo/hi.py", "def/abc/foo/hi.py"], + ), + globs_to_regex_params( + ["foo/x*"], case_insensitive=False, partial=True, + matches=["foo/x", "foo/xhi.py", "foo/x/hi.py"], + nomatches=[], + ), + globs_to_regex_params( + ["foo/x*"], case_insensitive=False, partial=False, + matches=["foo/x", "foo/xhi.py"], + nomatches=["foo/x/hi.py"], + ), globs_to_regex_params( ["**/foo"], matches=["foo", "hello/foo", "hi/there/foo"],