From e022f0cca454d18fdf7336a71fefc35a1939a089 Mon Sep 17 00:00:00 2001 From: Apeksha_2022 <70309060+Apeksha9389@users.noreply.github.com> Date: Mon, 19 Oct 2026 12:16:55 +0530 Subject: [PATCH] Escape literal parent directories in glob searches --- newsfragments/+glob-literal-parent.bugfix.rst | 1 + path/__init__.py | 4 ++-- tests/test_path.py | 9 +++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 newsfragments/+glob-literal-parent.bugfix.rst diff --git a/newsfragments/+glob-literal-parent.bugfix.rst b/newsfragments/+glob-literal-parent.bugfix.rst new file mode 100644 index 0000000..468d380 --- /dev/null +++ b/newsfragments/+glob-literal-parent.bugfix.rst @@ -0,0 +1 @@ +Treat the parent directory literally in ``Path.glob()`` and ``Path.iglob()`` when its name contains wildcard characters. diff --git a/path/__init__.py b/path/__init__.py index 731e88e..0ca6c12 100644 --- a/path/__init__.py +++ b/path/__init__.py @@ -647,7 +647,7 @@ def glob(self, pattern: str) -> list[Self]: :func:`walkdirs` or :func:`walkfiles`. """ cls = self._next_class - return [cls(s) for s in glob.glob(self / pattern)] + return [cls(s) for s in glob.glob(cls(glob.escape(self)) / pattern)] def iglob(self, pattern: str) -> Iterator[Self]: """Return an iterator of Path objects that match the pattern. @@ -665,7 +665,7 @@ def iglob(self, pattern: str) -> Iterator[Self]: :func:`walkdirs` or :func:`walkfiles`. """ cls = self._next_class - return (cls(s) for s in glob.iglob(self / pattern)) + return (cls(s) for s in glob.iglob(cls(glob.escape(self)) / pattern)) # # --- Reading or writing an entire file at once. diff --git a/tests/test_path.py b/tests/test_path.py index 55d733c..21b0652 100644 --- a/tests/test_path.py +++ b/tests/test_path.py @@ -460,6 +460,15 @@ class TestScratchDir: Tests that run in a temporary directory (does not test TempDir class) """ + @pytest.mark.parametrize('method', ['glob', 'iglob']) + def test_glob_literal_parent(self, tmp_path, method): + directory = Path(tmp_path / '[reports]').mkdir() + expected = (directory / 'result.txt').touch() + (directory / 'ignored.csv').touch() + decoy = Path(tmp_path / 'r').mkdir() + (decoy / 'wrong.txt').touch() + assert list(getattr(directory, method)('*.txt')) == [expected] + def test_context_manager(self, tmpdir): """Can be used as context manager for chdir.""" d = Path(tmpdir)