diff options
author | Bernát Gábor <bgabor8@bloomberg.net> | 2021-01-16 11:19:36 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-16 11:19:36 +0000 |
commit | f19fcd19a7098033b78229ce10a176e29c0ccce0 (patch) | |
tree | 238bfe219e4d3e19053c0d9b438b76abe3ddf329 /src | |
parent | d9c5b9cc6c4aa6a4cd477b3dbb5b8e09efcb922a (diff) | |
download | tox-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.py | 22 |
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)) |