Skip to content

Commit

Permalink
fix: glob characters in local paths (#552)
Browse files Browse the repository at this point in the history
* Prototype fix for local globbing problem with glob characters in pathnames.

* refactor: support Python 2, add test

* tests: skip glob test on Windows

Co-authored-by: Henry Schreiner <[email protected]>
  • Loading branch information
wtanksleyjr and henryiii authored Nov 23, 2021
1 parent e388030 commit 6cc4b98
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 8 deletions.
2 changes: 1 addition & 1 deletion noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def tests(session):
Run the unit and regular tests.
"""
session.install("-e", ".[dev]")
session.run("pytest", "--cov", *session.posargs)
session.run("pytest", *session.posargs)


@nox.session(reuse_venv=True)
Expand Down
15 changes: 15 additions & 0 deletions plumbum/lib.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import inspect
import os
import re
import sys
from contextlib import contextmanager

Expand Down Expand Up @@ -102,6 +103,20 @@ def get_method_function(m):
else:
from StringIO import StringIO

if sys.version_info >= (3,):
from glob import escape as glob_escape
else:
_magic_check = re.compile(u"([*?[])")
_magic_check_bytes = re.compile(b"([*?[])")

def glob_escape(pathname):
drive, pathname = os.path.splitdrive(pathname)
if isinstance(pathname, str):
pathname = _magic_check_bytes.sub(r"[\1]", pathname)
else:
pathname = _magic_check.sub(u"[\\1]", pathname)
return drive + pathname


@contextmanager
def captured_stdout(stdin=""):
Expand Down
6 changes: 4 additions & 2 deletions plumbum/path/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import sys
from contextlib import contextmanager

from plumbum.lib import IS_WIN32, _setdoc, six
from plumbum.lib import IS_WIN32, _setdoc, glob_escape, six
from plumbum.path.base import FSUser, Path
from plumbum.path.remote import RemotePath

Expand Down Expand Up @@ -170,7 +170,9 @@ def with_suffix(self, suffix, depth=1):

@_setdoc(Path)
def glob(self, pattern):
fn = lambda pat: [LocalPath(m) for m in glob.glob(str(self / pat))]
fn = lambda pat: [
LocalPath(m) for m in glob.glob(os.path.join(glob_escape(str(self)), pat))
]
return self._glob(pattern, fn)

@_setdoc(Path)
Expand Down
9 changes: 4 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,15 @@ def pytest_addoption(parser):
default=None,
help="Optional test markers to run, multiple and/or comma separated okay",
)
parser.addini(
"optional_tests", "list of optional markers", type="linelist", default=""
)


def pytest_configure(config):
# register all optional tests declared in ini file as markers
# https://docs.pytest.org/en/latest/writing_plugins.html#registering-custom-markers
ot_ini = config.inicfg.get("optional_tests") # None if NA
if ot_ini:
ot_ini = ot_ini.split("\n")
else:
ot_ini = []
ot_ini = config.inicfg.get("optional_tests").splitlines()
for ot in ot_ini:
# ot should be a line like "optmarker: this is an opt marker", as with markers section
config.addinivalue_line("markers", ot)
Expand Down
14 changes: 14 additions & 0 deletions tests/test_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -1073,3 +1073,17 @@ def test_runfile_rich(self):
os.chmod(name, st.st_mode | stat.S_IEXEC)

assert "yes" in local[local.cwd / name]()


@pytest.mark.skipif(
IS_WIN32, reason="Windows does not support these weird paths, so unambiguous there"
)
def test_local_glob_path(tmpdir):
p = tmpdir.mkdir("a*b?c")
p2 = tmpdir.mkdir("aanythingbxc")
p2.join("something.txt").write("content")
p.join("hello.txt").write("content")
p.join("other.txt").write("content")

pp = LocalPath(str(p))
assert len(pp // "*.txt") == 2

0 comments on commit 6cc4b98

Please sign in to comment.