config: make _get_plugin_specs_as_list a little clearer and more general
This commit is contained in:
parent
4655b79985
commit
8994e1e3a1
|
@ -1,5 +1,6 @@
|
||||||
""" command line options, ini-file and conftest.py processing. """
|
""" command line options, ini-file and conftest.py processing. """
|
||||||
import argparse
|
import argparse
|
||||||
|
import collections.abc
|
||||||
import contextlib
|
import contextlib
|
||||||
import copy
|
import copy
|
||||||
import enum
|
import enum
|
||||||
|
@ -654,7 +655,9 @@ class PytestPluginManager(PluginManager):
|
||||||
def consider_module(self, mod: types.ModuleType) -> None:
|
def consider_module(self, mod: types.ModuleType) -> None:
|
||||||
self._import_plugin_specs(getattr(mod, "pytest_plugins", []))
|
self._import_plugin_specs(getattr(mod, "pytest_plugins", []))
|
||||||
|
|
||||||
def _import_plugin_specs(self, spec) -> None:
|
def _import_plugin_specs(
|
||||||
|
self, spec: Union[None, types.ModuleType, str, Sequence[str]]
|
||||||
|
) -> None:
|
||||||
plugins = _get_plugin_specs_as_list(spec)
|
plugins = _get_plugin_specs_as_list(spec)
|
||||||
for import_spec in plugins:
|
for import_spec in plugins:
|
||||||
self.import_plugin(import_spec)
|
self.import_plugin(import_spec)
|
||||||
|
@ -702,24 +705,26 @@ class PytestPluginManager(PluginManager):
|
||||||
self.register(mod, modname)
|
self.register(mod, modname)
|
||||||
|
|
||||||
|
|
||||||
def _get_plugin_specs_as_list(specs) -> List[str]:
|
def _get_plugin_specs_as_list(
|
||||||
"""
|
specs: Union[None, types.ModuleType, str, Sequence[str]]
|
||||||
Parses a list of "plugin specs" and returns a list of plugin names.
|
) -> List[str]:
|
||||||
|
"""Parse a plugins specification into a list of plugin names."""
|
||||||
Plugin specs can be given as a list of strings separated by "," or already as a list/tuple in
|
# None means empty.
|
||||||
which case it is returned as a list. Specs can also be `None` in which case an
|
if specs is None:
|
||||||
empty list is returned.
|
|
||||||
"""
|
|
||||||
if specs is not None and not isinstance(specs, types.ModuleType):
|
|
||||||
if isinstance(specs, str):
|
|
||||||
specs = specs.split(",") if specs else []
|
|
||||||
if not isinstance(specs, (list, tuple)):
|
|
||||||
raise UsageError(
|
|
||||||
"Plugin specs must be a ','-separated string or a "
|
|
||||||
"list/tuple of strings for plugin names. Given: %r" % specs
|
|
||||||
)
|
|
||||||
return list(specs)
|
|
||||||
return []
|
return []
|
||||||
|
# Workaround for #3899 - a submodule which happens to be called "pytest_plugins".
|
||||||
|
if isinstance(specs, types.ModuleType):
|
||||||
|
return []
|
||||||
|
# Comma-separated list.
|
||||||
|
if isinstance(specs, str):
|
||||||
|
return specs.split(",") if specs else []
|
||||||
|
# Direct specification.
|
||||||
|
if isinstance(specs, collections.abc.Sequence):
|
||||||
|
return list(specs)
|
||||||
|
raise UsageError(
|
||||||
|
"Plugins may be specified as a sequence or a ','-separated string of plugin names. Got: %r"
|
||||||
|
% specs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _ensure_removed_sysmodule(modname: str) -> None:
|
def _ensure_removed_sysmodule(modname: str) -> None:
|
||||||
|
|
|
@ -11,6 +11,7 @@ import py.path
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.compat import importlib_metadata
|
from _pytest.compat import importlib_metadata
|
||||||
|
from _pytest.config import _get_plugin_specs_as_list
|
||||||
from _pytest.config import _iter_rewritable_modules
|
from _pytest.config import _iter_rewritable_modules
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config import ConftestImportFailure
|
from _pytest.config import ConftestImportFailure
|
||||||
|
@ -1115,21 +1116,17 @@ def test_load_initial_conftest_last_ordering(_config_for_test):
|
||||||
assert [x.function.__module__ for x in values] == expected
|
assert [x.function.__module__ for x in values] == expected
|
||||||
|
|
||||||
|
|
||||||
def test_get_plugin_specs_as_list():
|
def test_get_plugin_specs_as_list() -> None:
|
||||||
from _pytest.config import _get_plugin_specs_as_list
|
def exp_match(val: object) -> str:
|
||||||
|
|
||||||
def exp_match(val):
|
|
||||||
return (
|
return (
|
||||||
"Plugin specs must be a ','-separated string"
|
"Plugins may be specified as a sequence or a ','-separated string of plugin names. Got: %s"
|
||||||
" or a list/tuple of strings for plugin names. Given: {}".format(
|
% re.escape(repr(val))
|
||||||
re.escape(repr(val))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
with pytest.raises(pytest.UsageError, match=exp_match({"foo"})):
|
with pytest.raises(pytest.UsageError, match=exp_match({"foo"})):
|
||||||
_get_plugin_specs_as_list({"foo"})
|
_get_plugin_specs_as_list({"foo"}) # type: ignore[arg-type]
|
||||||
with pytest.raises(pytest.UsageError, match=exp_match({})):
|
with pytest.raises(pytest.UsageError, match=exp_match({})):
|
||||||
_get_plugin_specs_as_list(dict())
|
_get_plugin_specs_as_list(dict()) # type: ignore[arg-type]
|
||||||
|
|
||||||
assert _get_plugin_specs_as_list(None) == []
|
assert _get_plugin_specs_as_list(None) == []
|
||||||
assert _get_plugin_specs_as_list("") == []
|
assert _get_plugin_specs_as_list("") == []
|
||||||
|
|
Loading…
Reference in New Issue