From 8994e1e3a17bd625e0c258d0a402062542908fe3 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 23 Jun 2020 11:38:21 +0300 Subject: [PATCH] config: make _get_plugin_specs_as_list a little clearer and more general --- src/_pytest/config/__init__.py | 41 +++++++++++++++++++--------------- testing/test_config.py | 17 ++++++-------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index ac7afcd56..717743e79 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1,5 +1,6 @@ """ command line options, ini-file and conftest.py processing. """ import argparse +import collections.abc import contextlib import copy import enum @@ -654,7 +655,9 @@ class PytestPluginManager(PluginManager): def consider_module(self, mod: types.ModuleType) -> None: 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) for import_spec in plugins: self.import_plugin(import_spec) @@ -702,24 +705,26 @@ class PytestPluginManager(PluginManager): self.register(mod, modname) -def _get_plugin_specs_as_list(specs) -> List[str]: - """ - Parses a list of "plugin specs" and returns a list of plugin names. - - Plugin specs can be given as a list of strings separated by "," or already as a list/tuple in - which case it is returned as a list. Specs can also be `None` in which case an - 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 - ) +def _get_plugin_specs_as_list( + specs: Union[None, types.ModuleType, str, Sequence[str]] +) -> List[str]: + """Parse a plugins specification into a list of plugin names.""" + # None means empty. + if specs is None: + 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) - return [] + 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: diff --git a/testing/test_config.py b/testing/test_config.py index c1e4471b9..bc0da93a5 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -11,6 +11,7 @@ import py.path import _pytest._code import pytest 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 Config 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 -def test_get_plugin_specs_as_list(): - from _pytest.config import _get_plugin_specs_as_list - - def exp_match(val): +def test_get_plugin_specs_as_list() -> None: + def exp_match(val: object) -> str: return ( - "Plugin specs must be a ','-separated string" - " or a list/tuple of strings for plugin names. Given: {}".format( - re.escape(repr(val)) - ) + "Plugins may be specified as a sequence or a ','-separated string of plugin names. Got: %s" + % re.escape(repr(val)) ) 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({})): - _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("") == []