summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBernát Gábor <bgabor8@bloomberg.net>2021-01-16 11:19:36 +0000
committerGitHub <noreply@github.com>2021-01-16 11:19:36 +0000
commitf19fcd19a7098033b78229ce10a176e29c0ccce0 (patch)
tree238bfe219e4d3e19053c0d9b438b76abe3ddf329 /src
parentd9c5b9cc6c4aa6a4cd477b3dbb5b8e09efcb922a (diff)
downloadtox-git-f19fcd19a7098033b78229ce10a176e29c0ccce0.tar.gz
Handle spaces in paths within requirement files (#1828)
Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
Diffstat (limited to 'src')
-rw-r--r--src/tox/tox_env/python/req_file.py22
1 files changed, 17 insertions, 5 deletions
diff --git a/src/tox/tox_env/python/req_file.py b/src/tox/tox_env/python/req_file.py
index 2796e492..cd690646 100644
--- a/src/tox/tox_env/python/req_file.py
+++ b/src/tox/tox_env/python/req_file.py
@@ -56,13 +56,21 @@ class RequirementsFile:
],
}
- def __init__(self, raw: str, allow_short_req_file: bool = True, root: Optional[Path] = None) -> None:
+ def __init__(self, raw: str, within_tox_ini: bool = True, root: Optional[Path] = None) -> None:
self._root = Path().cwd() if root is None else root
- if allow_short_req_file: # patch for tox<4 supporting requirement/constraint files via -rreq.txt/-creq.txt
+ if within_tox_ini: # patch the content coming from tox.ini
lines: List[str] = []
for line in raw.splitlines():
+ # for tox<4 supporting requirement/constraint files via -rreq.txt/-creq.txt
if len(line) >= 3 and (line.startswith("-r") or line.startswith("-c")) and not line[2].isspace():
line = f"{line[:2]} {line[2:]}"
+ # escape spaces
+ escape_for = ("-c", "--constraint", "-r", "--requirement", "-f", "--find-links" "-e", "--editable")
+ escape_match = next((e for e in escape_for if line.startswith(e) and line[len(e)].isspace()), None)
+ if escape_match is not None:
+ # escape not already escaped spaces
+ escaped = re.sub(r"(?<!\\)(\s)", r"\\\1", line[len(escape_match) + 1 :])
+ line = f"{line[:len(escape_match)]} {escaped}"
lines.append(line)
adjusted = "\n".join(lines)
raw = f"{adjusted}\n" if raw.endswith("\\\n") else adjusted # preserve trailing newline if input has it
@@ -86,7 +94,7 @@ class RequirementsFile:
if not line:
continue
if line.startswith("-"): # handle flags
- words = re.findall(r"\S+", line)
+ words = [i for i in re.split(r"(?<!\\)\s", line) if i]
first = words[0]
if first in self.VALID_OPTIONS["no_arg"]:
if len(words) != 1:
@@ -98,10 +106,14 @@ class RequirementsFile:
raise ValueError(line)
else:
if first in ("-r", "--requirement", "-c", "--constraint"):
- path = Path(line[len(first) + 1 :].strip())
+ raw_path = line[len(first) + 1 :].strip()
+ unescaped_path = re.sub(r"\\(\s)", r"\1", raw_path)
+ path = Path(unescaped_path)
if not path.is_absolute():
path = ini_dir / path
- req_file = RequirementsFile(path.read_text(), allow_short_req_file=False, root=self.root)
+ if not path.exists():
+ raise ValueError(f"requirement file path {str(path)!r} does not exist")
+ req_file = RequirementsFile(path.read_text(), within_tox_ini=False, root=self.root)
result.extend(req_file.validate_and_expand())
else:
result.append(" ".join(words))