config: make _get_plugin_specs_as_list a little clearer and more general

This commit is contained in:
Ran Benita 2020-06-23 11:38:21 +03:00
parent 4655b79985
commit 8994e1e3a1
2 changed files with 30 additions and 28 deletions

View File

@ -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:

View File

@ -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("") == []