diff --git a/CHANGES.rst b/CHANGES.rst index f056ddd6d..69eed03b2 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 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/_static/coverage.css b/doc/_static/coverage.css index ee5349910..43d2ae12e 100644 --- a/doc/_static/coverage.css +++ b/doc/_static/coverage.css @@ -66,6 +66,16 @@ img.tideliftlogo { background: #efc; } +/* I'm not sure why I had to make this so specific to get it to take effect... */ +div.rst-content div.document div.wy-table-responsive table.docutils.align-default tbody tr td { + vertical-align: top !important; +} + +/* And this doesn't work, and I guess I just have to live with it. */ +div.rst-content div.document div.wy-table-responsive table.docutils.align-default tbody tr td .line-block { + margin-bottom: 0 !important; +} + /* sphinx-code-tabs */ /* Some selectors here are extra-specific (.container) because this file comes diff --git a/doc/source.rst b/doc/source.rst index 44b84f001..3357ae73d 100644 --- a/doc/source.rst +++ b/doc/source.rst @@ -178,15 +178,67 @@ individual source lines. See :ref:`excluding` for details. 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. +File path patterns are used for :ref:`include ` and +:ref:`omit `, and for :ref:`combining path remapping +`. They follow common shell syntax: - ``?`` matches a single file name character. -- ``**`` matches any number of nested directory names, including none. +- ``*`` 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. It must + be used as a full component of the path, not as part of a word: ``/**/`` is + allowed, but ``/a**/`` is not. - Both ``/`` and ``\`` will match either a slash or a backslash, to make cross-platform matching easier. + +- A pattern with no directory separators matches the file name in any + directory. + +Some examples: + +.. list-table:: + :widths: 20 20 20 + :header-rows: 1 + + * - Pattern + - Matches + - Doesn't Match + * - ``a*.py`` + - | anything.py + | sub1/sub2/another.py + - | cat.py + * - ``sub/*/*.py`` + - | sub/a/main.py + | sub/b/another.py + - | sub/foo.py + | sub/m1/m2/foo.py + * - ``sub/**/*.py`` + - | sub/something.py + | sub/a/main.py + | sub/b/another.py + | sub/m1/m2/foo.py + - | sub1/anything.py + | sub1/more/code/main.py + * - ``*/sub/*`` + - | some/where/sub/more/something.py + | sub/hello.py + - | sub1/anything.py + * - ``*/sub*/*`` + - | some/where/sub/more/something.py + | sub/hello.py + | sub1/anything.py + - | some/more/something.py + * - ``*/*sub/test_*.py`` + - | some/where/sub/test_everything.py + | moresub/test_things.py + - | some/where/sub/more/test_everything.py + | more/test_things.py + * - ``*/*sub/*sub/**`` + - | sub/sub/something.py + | asub/bsub/more/thing.py + | code/sub/sub/code.py + - | sub/something.py 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"],