Skip to content

Commit 2d57d5c

Browse files
committed
Do not break on very long command-line options
`_set_initial_conftests` could break on some systems if a very long option was passed, because the `Path.exists()` call raises an `OSError` instead of returning `False`. Fix pytest-dev#10169
1 parent faeb161 commit 2d57d5c

File tree

3 files changed

+28
-14
lines changed

3 files changed

+28
-14
lines changed

changelog/10169.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix bug where very long option names could cause pytest to break with ``OSError: [Errno 36] File name too long`` on some systems.

src/_pytest/config/__init__.py

+6-12
Original file line numberDiff line numberDiff line change
@@ -556,19 +556,13 @@ def _set_initial_conftests(
556556
path = path[:i]
557557
anchor = absolutepath(current / path)
558558

559-
# On Python 3.7 on Windows, anchor.exists() might raise
560-
# if the anchor contains glob characters (for example "*//tests"), specially
561-
# in the case of the 'testpaths' ini option.
562-
# Using an explicit version check to remove this code later once
563-
# Python 3.7 is dropped.
564-
if sys.version_info[:2] == (3, 7):
565-
try:
566-
anchor_exists = anchor.exists()
567-
except OSError: # pragma: no cover
568-
anchor_exists = False
569-
else:
559+
# Ensure we do not break if what appears to be an anchor
560+
# is in fact a very long option (#10169).
561+
try:
570562
anchor_exists = anchor.exists()
571-
if anchor_exists: # We found some file object.
563+
except OSError: # pragma: no cover
564+
anchor_exists = False
565+
if anchor_exists:
572566
self._try_load_conftest(anchor, namespace.importmode, rootpath)
573567
foundanchor = True
574568
if not foundanchor:

testing/test_collection.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,7 @@ def test_initial_conftests_with_testpaths(pytester: Pytester) -> None:
12541254
textwrap.dedent(
12551255
"""
12561256
def pytest_sessionstart(session):
1257-
raise Exception("pytest_sessionstart hook is successfully run")
1257+
raise Exception("pytest_sessionstart hook successfully run")
12581258
"""
12591259
)
12601260
)
@@ -1266,10 +1266,29 @@ def pytest_sessionstart(session):
12661266
)
12671267
result = pytester.runpytest()
12681268
result.stdout.fnmatch_lines(
1269-
"INTERNALERROR* Exception: pytest_sessionstart hook is successfully run"
1269+
"INTERNALERROR* Exception: pytest_sessionstart hook successfully run"
12701270
)
12711271

12721272

1273+
def test_large_option_breaks_initial_conftests(pytester: Pytester) -> None:
1274+
"""Long option values do not break initial conftests handling (#10169)."""
1275+
option_value = "x" * 1024 * 1000
1276+
pytester.makeconftest(
1277+
"""
1278+
def pytest_addoption(parser):
1279+
parser.addoption("--xx", default=None)
1280+
"""
1281+
)
1282+
pytester.makepyfile(
1283+
f"""
1284+
def test_foo(request):
1285+
assert request.config.getoption("xx") == {option_value!r}
1286+
"""
1287+
)
1288+
result = pytester.runpytest(f"--xx={option_value}")
1289+
assert result.ret == 0
1290+
1291+
12731292
def test_collect_symlink_file_arg(pytester: Pytester) -> None:
12741293
"""Collect a direct symlink works even if it does not match python_files (#4325)."""
12751294
real = pytester.makepyfile(

0 commit comments

Comments
 (0)