Skip to content

Commit 5a85b90

Browse files
committed
config: inline _preparse
No that "preparse" phase is no longer a thing, with the removal of the historic `pytest_cmdline_preparse` hook and `after_preparse` hack, let's inline so we can see the full parse flow in linear code.
1 parent d0e6076 commit 5a85b90

File tree

3 files changed

+95
-95
lines changed

3 files changed

+95
-95
lines changed

src/_pytest/config/__init__.py

Lines changed: 89 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,92 +1355,6 @@ def _decide_args(
13551355
result = [str(invocation_dir)]
13561356
return result, source
13571357

1358-
def _preparse(self, args: list[str], addopts: bool = True) -> None:
1359-
if addopts:
1360-
env_addopts = os.environ.get("PYTEST_ADDOPTS", "")
1361-
if len(env_addopts):
1362-
args[:] = (
1363-
self._validate_args(shlex.split(env_addopts), "via PYTEST_ADDOPTS")
1364-
+ args
1365-
)
1366-
1367-
ns = self._parser.parse_known_args(args, namespace=copy.copy(self.option))
1368-
rootpath, inipath, inicfg, ignored_config_files = determine_setup(
1369-
inifile=ns.inifilename,
1370-
override_ini=ns.override_ini,
1371-
args=ns.file_or_dir,
1372-
rootdir_cmd_arg=ns.rootdir or None,
1373-
invocation_dir=self.invocation_params.dir,
1374-
)
1375-
self._rootpath = rootpath
1376-
self._inipath = inipath
1377-
self._ignored_config_files = ignored_config_files
1378-
self.inicfg = inicfg
1379-
self._parser.extra_info["rootdir"] = str(self.rootpath)
1380-
self._parser.extra_info["inifile"] = str(self.inipath)
1381-
self._parser.addini("addopts", "Extra command line options", "args")
1382-
self._parser.addini("minversion", "Minimally required pytest version")
1383-
self._parser.addini(
1384-
"pythonpath", type="paths", help="Add paths to sys.path", default=[]
1385-
)
1386-
self._parser.addini(
1387-
"required_plugins",
1388-
"Plugins that must be present for pytest to run",
1389-
type="args",
1390-
default=[],
1391-
)
1392-
1393-
if addopts:
1394-
args[:] = (
1395-
self._validate_args(self.getini("addopts"), "via addopts config") + args
1396-
)
1397-
1398-
self.known_args_namespace = self._parser.parse_known_args(
1399-
args, namespace=copy.copy(self.option)
1400-
)
1401-
self._checkversion()
1402-
self._consider_importhook()
1403-
self._configure_python_path()
1404-
self.pluginmanager.consider_preparse(args, exclude_only=False)
1405-
if (
1406-
not os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD")
1407-
and not self.known_args_namespace.disable_plugin_autoload
1408-
):
1409-
# Autoloading from distribution package entry point has
1410-
# not been disabled.
1411-
self.pluginmanager.load_setuptools_entrypoints("pytest11")
1412-
# Otherwise only plugins explicitly specified in PYTEST_PLUGINS
1413-
# are going to be loaded.
1414-
self.pluginmanager.consider_env()
1415-
1416-
self.known_args_namespace = self._parser.parse_known_args(
1417-
args, namespace=copy.copy(self.known_args_namespace)
1418-
)
1419-
1420-
self._validate_plugins()
1421-
self._warn_about_skipped_plugins()
1422-
1423-
if self.known_args_namespace.confcutdir is None:
1424-
if self.inipath is not None:
1425-
confcutdir = str(self.inipath.parent)
1426-
else:
1427-
confcutdir = str(self.rootpath)
1428-
self.known_args_namespace.confcutdir = confcutdir
1429-
try:
1430-
self.hook.pytest_load_initial_conftests(
1431-
early_config=self, args=args, parser=self._parser
1432-
)
1433-
except ConftestImportFailure as e:
1434-
if self.known_args_namespace.help or self.known_args_namespace.version:
1435-
# we don't want to prevent --help/--version to work
1436-
# so just let it pass and print a warning at the end
1437-
self.issue_config_time_warning(
1438-
PytestConfigWarning(f"could not load initial conftests: {e.path}"),
1439-
stacklevel=2,
1440-
)
1441-
else:
1442-
raise
1443-
14441358
@hookimpl(wrapper=True)
14451359
def pytest_collection(self) -> Generator[None, object, object]:
14461360
# Validate invalid configuration keys after collection is done so we
@@ -1524,14 +1438,102 @@ def parse(self, args: list[str], addopts: bool = True) -> None:
15241438
assert self.args == [], (
15251439
"can only parse cmdline args at most once per Config object"
15261440
)
1441+
15271442
self.hook.pytest_addhooks.call_historic(
15281443
kwargs=dict(pluginmanager=self.pluginmanager)
15291444
)
1530-
self._preparse(args, addopts=addopts)
1445+
1446+
if addopts:
1447+
env_addopts = os.environ.get("PYTEST_ADDOPTS", "")
1448+
if len(env_addopts):
1449+
args[:] = (
1450+
self._validate_args(shlex.split(env_addopts), "via PYTEST_ADDOPTS")
1451+
+ args
1452+
)
1453+
1454+
ns = self._parser.parse_known_args(args, namespace=copy.copy(self.option))
1455+
rootpath, inipath, inicfg, ignored_config_files = determine_setup(
1456+
inifile=ns.inifilename,
1457+
override_ini=ns.override_ini,
1458+
args=ns.file_or_dir,
1459+
rootdir_cmd_arg=ns.rootdir or None,
1460+
invocation_dir=self.invocation_params.dir,
1461+
)
1462+
self._rootpath = rootpath
1463+
self._inipath = inipath
1464+
self._ignored_config_files = ignored_config_files
1465+
self.inicfg = inicfg
1466+
self._parser.extra_info["rootdir"] = str(self.rootpath)
1467+
self._parser.extra_info["inifile"] = str(self.inipath)
1468+
1469+
self._parser.addini("addopts", "Extra command line options", "args")
1470+
self._parser.addini("minversion", "Minimally required pytest version")
1471+
self._parser.addini(
1472+
"pythonpath", type="paths", help="Add paths to sys.path", default=[]
1473+
)
1474+
self._parser.addini(
1475+
"required_plugins",
1476+
"Plugins that must be present for pytest to run",
1477+
type="args",
1478+
default=[],
1479+
)
1480+
1481+
if addopts:
1482+
args[:] = (
1483+
self._validate_args(self.getini("addopts"), "via addopts config") + args
1484+
)
1485+
1486+
self.known_args_namespace = self._parser.parse_known_args(
1487+
args, namespace=copy.copy(self.option)
1488+
)
1489+
self._checkversion()
1490+
self._consider_importhook()
1491+
self._configure_python_path()
1492+
self.pluginmanager.consider_preparse(args, exclude_only=False)
1493+
if (
1494+
not os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD")
1495+
and not self.known_args_namespace.disable_plugin_autoload
1496+
):
1497+
# Autoloading from distribution package entry point has
1498+
# not been disabled.
1499+
self.pluginmanager.load_setuptools_entrypoints("pytest11")
1500+
# Otherwise only plugins explicitly specified in PYTEST_PLUGINS
1501+
# are going to be loaded.
1502+
self.pluginmanager.consider_env()
1503+
1504+
self.known_args_namespace = self._parser.parse_known_args(
1505+
args, namespace=copy.copy(self.known_args_namespace)
1506+
)
1507+
1508+
self._validate_plugins()
1509+
self._warn_about_skipped_plugins()
1510+
1511+
if self.known_args_namespace.confcutdir is None:
1512+
if self.inipath is not None:
1513+
confcutdir = str(self.inipath.parent)
1514+
else:
1515+
confcutdir = str(self.rootpath)
1516+
self.known_args_namespace.confcutdir = confcutdir
1517+
try:
1518+
self.hook.pytest_load_initial_conftests(
1519+
early_config=self, args=args, parser=self._parser
1520+
)
1521+
except ConftestImportFailure as e:
1522+
if self.known_args_namespace.help or self.known_args_namespace.version:
1523+
# we don't want to prevent --help/--version to work
1524+
# so just let it pass and print a warning at the end
1525+
self.issue_config_time_warning(
1526+
PytestConfigWarning(f"could not load initial conftests: {e.path}"),
1527+
stacklevel=2,
1528+
)
1529+
else:
1530+
raise
1531+
15311532
try:
15321533
self._parser.parse(args, namespace=self.option)
15331534
except PrintHelp:
15341535
return
1536+
15351537
self.args, self.args_source = self._decide_args(
15361538
args=getattr(self.option, FILE_OR_DIR),
15371539
pyargs=self.option.pyargs,

testing/test_config.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,7 +2276,7 @@ def test_addopts_before_initini(
22762276
cache_dir = ".custom_cache"
22772277
monkeypatch.setenv("PYTEST_ADDOPTS", f"-o cache_dir={cache_dir}")
22782278
config = _config_for_test
2279-
config._preparse([], addopts=True)
2279+
config.parse([], addopts=True)
22802280
assert config.inicfg.get("cache_dir") == ConfigValue(
22812281
cache_dir, origin="override", mode="ini"
22822282
)
@@ -2288,7 +2288,7 @@ def test_addopts_from_env_not_concatenated(
22882288
monkeypatch.setenv("PYTEST_ADDOPTS", "-o")
22892289
config = _config_for_test
22902290
with pytest.raises(UsageError) as excinfo:
2291-
config._preparse(["cache_dir=ignored"], addopts=True)
2291+
config.parse(["cache_dir=ignored"], addopts=True)
22922292
assert (
22932293
"error: argument -o/--override-ini: expected one argument"
22942294
in excinfo.value.args[0]
@@ -2317,7 +2317,7 @@ def test_override_ini_does_not_contain_paths(
23172317
) -> None:
23182318
"""Check that -o no longer swallows all options after it (#3103)"""
23192319
config = _config_for_test
2320-
config._preparse(["-o", "cache_dir=/cache", "/some/test/path"])
2320+
config.parse(["-o", "cache_dir=/cache", "/some/test/path"])
23212321
assert config.inicfg.get("cache_dir") == ConfigValue(
23222322
"/cache", origin="override", mode="ini"
23232323
)

testing/test_warnings.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -742,10 +742,8 @@ def test_issue4445_rewrite(self, pytester: Pytester, capwarn) -> None:
742742
assert func == "<module>" # the above conftest.py
743743
assert lineno == 4
744744

745-
def test_issue4445_preparse(self, pytester: Pytester, capwarn) -> None:
746-
"""#4445: Make sure the warning points to a reasonable location
747-
See origin of _issue_warning_captured at: _pytest.config.__init__.py:910
748-
"""
745+
def test_issue4445_initial_conftest(self, pytester: Pytester, capwarn) -> None:
746+
"""#4445: Make sure the warning points to a reasonable location."""
749747
pytester.makeconftest(
750748
"""
751749
import nothing
@@ -761,7 +759,7 @@ def test_issue4445_preparse(self, pytester: Pytester, capwarn) -> None:
761759

762760
assert "could not load initial conftests" in str(warning.message)
763761
assert f"config{os.sep}__init__.py" in file
764-
assert func == "_preparse"
762+
assert func == "parse"
765763

766764
@pytest.mark.filterwarnings("default")
767765
def test_conftest_warning_captured(self, pytester: Pytester) -> None:

0 commit comments

Comments
 (0)