get_dirs_from_args handles paths with invalid syntax

Fix #7638
This commit is contained in:
Bruno Oliveira 2020-08-12 17:17:43 -03:00
parent 15d8293241
commit 36c8bb492e
3 changed files with 22 additions and 14 deletions

View File

@ -0,0 +1 @@
Fix handling of command-line options that appear as paths but trigger an OS-level syntax error on Windows, such as the options used internally by ``pytest-xdist``.

View File

@ -1,6 +1,5 @@
import itertools import itertools
import os import os
import sys
from typing import Dict from typing import Dict
from typing import Iterable from typing import Iterable
from typing import List from typing import List
@ -146,21 +145,14 @@ def get_dirs_from_args(args: Iterable[str]) -> List[Path]:
return path return path
return path.parent return path.parent
if sys.version_info < (3, 8):
def safe_exists(path: Path) -> bool: def safe_exists(path: Path) -> bool:
# On Python<3.8, this can throw on paths that contain characters # This can throw on paths that contain characters unrepresentable at the OS level,
# unrepresentable at the OS level. # or with invalid syntax on Windows
try: try:
return path.exists() return path.exists()
except OSError: except OSError:
return False return False
else:
def safe_exists(path: Path) -> bool:
return path.exists()
# These look like paths but may not exist # These look like paths but may not exist
possible_paths = ( possible_paths = (
absolutepath(get_file_part_from_node_id(arg)) absolutepath(get_file_part_from_node_id(arg))

View File

@ -2,6 +2,7 @@ from textwrap import dedent
import pytest import pytest
from _pytest.config.findpaths import get_common_ancestor from _pytest.config.findpaths import get_common_ancestor
from _pytest.config.findpaths import get_dirs_from_args
from _pytest.config.findpaths import load_config_dict_from_file from _pytest.config.findpaths import load_config_dict_from_file
from _pytest.pathlib import Path from _pytest.pathlib import Path
@ -108,3 +109,17 @@ class TestCommonAncestor:
fn = tmp_path / "foo.py" fn = tmp_path / "foo.py"
fn.touch() fn.touch()
assert get_common_ancestor([fn]) == tmp_path assert get_common_ancestor([fn]) == tmp_path
def test_get_dirs_from_args(tmp_path):
"""get_dirs_from_args() skips over non-existing directories and files"""
fn = tmp_path / "foo.py"
fn.touch()
d = tmp_path / "tests"
d.mkdir()
option = "--foobar=/foo.txt"
# xdist uses options in this format for its rsync feature (#7638)
xdist_rsync_option = "popen=c:/dest"
assert get_dirs_from_args(
[str(fn), str(tmp_path / "does_not_exist"), str(d), option, xdist_rsync_option]
) == [fn.parent, d]