move show_fixtures code to own module
This commit is contained in:
parent
b24e862463
commit
c58281b9ae
|
@ -35,7 +35,6 @@ from _pytest._code import filter_traceback
|
|||
from _pytest._code import getfslineno
|
||||
from _pytest._code.code import ExceptionInfo
|
||||
from _pytest._code.code import TerminalRepr
|
||||
from _pytest._io import TerminalWriter
|
||||
from _pytest._io.saferepr import saferepr
|
||||
from _pytest.compat import ascii_escaped
|
||||
from _pytest.compat import assert_never
|
||||
|
@ -43,7 +42,6 @@ from _pytest.compat import final
|
|||
from _pytest.compat import get_default_arg_names
|
||||
from _pytest.compat import get_real_func
|
||||
from _pytest.compat import getimfunc
|
||||
from _pytest.compat import getlocation
|
||||
from _pytest.compat import is_async_function
|
||||
from _pytest.compat import is_generator
|
||||
from _pytest.compat import LEGACY_PATH
|
||||
|
@ -69,7 +67,6 @@ from _pytest.mark.structures import MarkDecorator
|
|||
from _pytest.mark.structures import normalize_mark_list
|
||||
from _pytest.outcomes import fail
|
||||
from _pytest.outcomes import skip
|
||||
from _pytest.pathlib import bestrelpath
|
||||
from _pytest.pathlib import fnmatch_ex
|
||||
from _pytest.pathlib import import_path
|
||||
from _pytest.pathlib import ImportPathMismatchError
|
||||
|
@ -86,9 +83,6 @@ if TYPE_CHECKING:
|
|||
from _pytest.scope import _ScopeName
|
||||
|
||||
|
||||
_PYTEST_DIR = Path(_pytest.__file__).parent
|
||||
|
||||
|
||||
def pytest_addoption(parser: Parser) -> None:
|
||||
group = parser.getgroup("general")
|
||||
group.addoption(
|
||||
|
@ -137,11 +131,13 @@ def pytest_addoption(parser: Parser) -> None:
|
|||
|
||||
def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
|
||||
if config.option.showfixtures:
|
||||
showfixtures(config)
|
||||
return 0
|
||||
from .show_fixtures import showfixtures
|
||||
|
||||
return showfixtures(config)
|
||||
if config.option.show_fixtures_per_test:
|
||||
show_fixtures_per_test(config)
|
||||
return 0
|
||||
from .show_fixtures import show_fixtures_per_test
|
||||
|
||||
return show_fixtures_per_test(config)
|
||||
return None
|
||||
|
||||
|
||||
|
@ -1551,138 +1547,6 @@ def _ascii_escaped_by_config(val: Union[str, bytes], config: Optional[Config]) -
|
|||
return val if escape_option else ascii_escaped(val) # type: ignore
|
||||
|
||||
|
||||
def _pretty_fixture_path(func) -> str:
|
||||
cwd = Path.cwd()
|
||||
loc = Path(getlocation(func, str(cwd)))
|
||||
prefix = Path("...", "_pytest")
|
||||
try:
|
||||
return str(prefix / loc.relative_to(_PYTEST_DIR))
|
||||
except ValueError:
|
||||
return bestrelpath(cwd, loc)
|
||||
|
||||
|
||||
def show_fixtures_per_test(config):
|
||||
from _pytest.main import wrap_session
|
||||
|
||||
return wrap_session(config, _show_fixtures_per_test)
|
||||
|
||||
|
||||
def _show_fixtures_per_test(config: Config, session: Session) -> None:
|
||||
import _pytest.config
|
||||
|
||||
session.perform_collect()
|
||||
curdir = Path.cwd()
|
||||
tw = _pytest.config.create_terminal_writer(config)
|
||||
verbose = config.getvalue("verbose")
|
||||
|
||||
def get_best_relpath(func) -> str:
|
||||
loc = getlocation(func, str(curdir))
|
||||
return bestrelpath(curdir, Path(loc))
|
||||
|
||||
def write_fixture(fixture_def: fixtures.FixtureDef[object]) -> None:
|
||||
argname = fixture_def.argname
|
||||
if verbose <= 0 and argname.startswith("_"):
|
||||
return
|
||||
prettypath = _pretty_fixture_path(fixture_def.func)
|
||||
tw.write(f"{argname}", green=True)
|
||||
tw.write(f" -- {prettypath}", yellow=True)
|
||||
tw.write("\n")
|
||||
fixture_doc = inspect.getdoc(fixture_def.func)
|
||||
if fixture_doc:
|
||||
write_docstring(
|
||||
tw, fixture_doc.split("\n\n")[0] if verbose <= 0 else fixture_doc
|
||||
)
|
||||
else:
|
||||
tw.line(" no docstring available", red=True)
|
||||
|
||||
def write_item(item: nodes.Item) -> None:
|
||||
# Not all items have _fixtureinfo attribute.
|
||||
info: Optional[FuncFixtureInfo] = getattr(item, "_fixtureinfo", None)
|
||||
if info is None or not info.name2fixturedefs:
|
||||
# This test item does not use any fixtures.
|
||||
return
|
||||
tw.line()
|
||||
tw.sep("-", f"fixtures used by {item.name}")
|
||||
# TODO: Fix this type ignore.
|
||||
tw.sep("-", f"({get_best_relpath(item.function)})") # type: ignore[attr-defined]
|
||||
# dict key not used in loop but needed for sorting.
|
||||
for _, fixturedefs in sorted(info.name2fixturedefs.items()):
|
||||
assert fixturedefs is not None
|
||||
if not fixturedefs:
|
||||
continue
|
||||
# Last item is expected to be the one used by the test item.
|
||||
write_fixture(fixturedefs[-1])
|
||||
|
||||
for session_item in session.items:
|
||||
write_item(session_item)
|
||||
|
||||
|
||||
def showfixtures(config: Config) -> Union[int, ExitCode]:
|
||||
from _pytest.main import wrap_session
|
||||
|
||||
return wrap_session(config, _showfixtures_main)
|
||||
|
||||
|
||||
def _showfixtures_main(config: Config, session: Session) -> None:
|
||||
import _pytest.config
|
||||
|
||||
session.perform_collect()
|
||||
curdir = Path.cwd()
|
||||
tw = _pytest.config.create_terminal_writer(config)
|
||||
verbose = config.getvalue("verbose")
|
||||
|
||||
fm = session._fixturemanager
|
||||
|
||||
available = []
|
||||
seen: Set[Tuple[str, str]] = set()
|
||||
|
||||
for argname, fixturedefs in fm._arg2fixturedefs.items():
|
||||
assert fixturedefs is not None
|
||||
if not fixturedefs:
|
||||
continue
|
||||
for fixturedef in fixturedefs:
|
||||
loc = getlocation(fixturedef.func, str(curdir))
|
||||
if (fixturedef.argname, loc) in seen:
|
||||
continue
|
||||
seen.add((fixturedef.argname, loc))
|
||||
available.append(
|
||||
(
|
||||
len(fixturedef.baseid),
|
||||
fixturedef.func.__module__,
|
||||
_pretty_fixture_path(fixturedef.func),
|
||||
fixturedef.argname,
|
||||
fixturedef,
|
||||
)
|
||||
)
|
||||
|
||||
available.sort()
|
||||
currentmodule = None
|
||||
for baseid, module, prettypath, argname, fixturedef in available:
|
||||
if currentmodule != module:
|
||||
if not module.startswith("_pytest."):
|
||||
tw.line()
|
||||
tw.sep("-", f"fixtures defined from {module}")
|
||||
currentmodule = module
|
||||
if verbose <= 0 and argname.startswith("_"):
|
||||
continue
|
||||
tw.write(f"{argname}", green=True)
|
||||
if fixturedef.scope != "function":
|
||||
tw.write(" [%s scope]" % fixturedef.scope, cyan=True)
|
||||
tw.write(f" -- {prettypath}", yellow=True)
|
||||
tw.write("\n")
|
||||
doc = inspect.getdoc(fixturedef.func)
|
||||
if doc:
|
||||
write_docstring(tw, doc.split("\n\n")[0] if verbose <= 0 else doc)
|
||||
else:
|
||||
tw.line(" no docstring available", red=True)
|
||||
tw.line()
|
||||
|
||||
|
||||
def write_docstring(tw: TerminalWriter, doc: str, indent: str = " ") -> None:
|
||||
for line in doc.split("\n"):
|
||||
tw.line(indent + line)
|
||||
|
||||
|
||||
class Function(PyobjMixin, nodes.Item):
|
||||
"""An Item responsible for setting up and executing a Python test function.
|
||||
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
import inspect
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from typing import Set
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
|
||||
import _pytest
|
||||
from _pytest import fixtures
|
||||
from _pytest import nodes
|
||||
from _pytest._io import TerminalWriter
|
||||
from _pytest.compat import getlocation
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.fixtures import FuncFixtureInfo
|
||||
from _pytest.main import Session
|
||||
from _pytest.pathlib import bestrelpath
|
||||
|
||||
|
||||
_PYTEST_DIR = Path(_pytest.__file__).parent
|
||||
|
||||
|
||||
def _showfixtures_main(config: Config, session: Session) -> None:
|
||||
import _pytest.config
|
||||
|
||||
session.perform_collect()
|
||||
curdir = Path.cwd()
|
||||
tw = _pytest.config.create_terminal_writer(config)
|
||||
verbose = config.getvalue("verbose")
|
||||
|
||||
fm = session._fixturemanager
|
||||
|
||||
available = []
|
||||
seen: Set[Tuple[str, str]] = set()
|
||||
|
||||
for argname, fixturedefs in fm._arg2fixturedefs.items():
|
||||
assert fixturedefs is not None
|
||||
if not fixturedefs:
|
||||
continue
|
||||
for fixturedef in fixturedefs:
|
||||
loc = getlocation(fixturedef.func, str(curdir))
|
||||
if (fixturedef.argname, loc) in seen:
|
||||
continue
|
||||
seen.add((fixturedef.argname, loc))
|
||||
available.append(
|
||||
(
|
||||
len(fixturedef.baseid),
|
||||
fixturedef.func.__module__,
|
||||
_pretty_fixture_path(fixturedef.func),
|
||||
fixturedef.argname,
|
||||
fixturedef,
|
||||
)
|
||||
)
|
||||
|
||||
available.sort()
|
||||
currentmodule = None
|
||||
for baseid, module, prettypath, argname, fixturedef in available:
|
||||
if currentmodule != module:
|
||||
if not module.startswith("_pytest."):
|
||||
tw.line()
|
||||
tw.sep("-", f"fixtures defined from {module}")
|
||||
currentmodule = module
|
||||
if verbose <= 0 and argname.startswith("_"):
|
||||
continue
|
||||
tw.write(f"{argname}", green=True)
|
||||
if fixturedef.scope != "function":
|
||||
tw.write(" [%s scope]" % fixturedef.scope, cyan=True)
|
||||
tw.write(f" -- {prettypath}", yellow=True)
|
||||
tw.write("\n")
|
||||
doc = inspect.getdoc(fixturedef.func)
|
||||
if doc:
|
||||
write_docstring(tw, doc.split("\n\n")[0] if verbose <= 0 else doc)
|
||||
else:
|
||||
tw.line(" no docstring available", red=True)
|
||||
tw.line()
|
||||
|
||||
|
||||
def _pretty_fixture_path(func) -> str:
|
||||
cwd = Path.cwd()
|
||||
loc = Path(getlocation(func, str(cwd)))
|
||||
prefix = Path("...", "_pytest")
|
||||
try:
|
||||
return str(prefix / loc.relative_to(_PYTEST_DIR))
|
||||
except ValueError:
|
||||
return bestrelpath(cwd, loc)
|
||||
|
||||
|
||||
def show_fixtures_per_test(config: Config) -> Union[int, ExitCode]:
|
||||
from _pytest.main import wrap_session
|
||||
|
||||
return wrap_session(config, _show_fixtures_per_test)
|
||||
|
||||
|
||||
def _show_fixtures_per_test(config: Config, session: Session) -> None:
|
||||
import _pytest.config
|
||||
|
||||
session.perform_collect()
|
||||
curdir = Path.cwd()
|
||||
tw = _pytest.config.create_terminal_writer(config)
|
||||
verbose = config.getvalue("verbose")
|
||||
|
||||
def get_best_relpath(func) -> str:
|
||||
loc = getlocation(func, str(curdir))
|
||||
return bestrelpath(curdir, Path(loc))
|
||||
|
||||
def write_fixture(fixture_def: fixtures.FixtureDef[object]) -> None:
|
||||
argname = fixture_def.argname
|
||||
if verbose <= 0 and argname.startswith("_"):
|
||||
return
|
||||
prettypath = _pretty_fixture_path(fixture_def.func)
|
||||
tw.write(f"{argname}", green=True)
|
||||
tw.write(f" -- {prettypath}", yellow=True)
|
||||
tw.write("\n")
|
||||
fixture_doc = inspect.getdoc(fixture_def.func)
|
||||
if fixture_doc:
|
||||
write_docstring(
|
||||
tw, fixture_doc.split("\n\n")[0] if verbose <= 0 else fixture_doc
|
||||
)
|
||||
else:
|
||||
tw.line(" no docstring available", red=True)
|
||||
|
||||
def write_item(item: nodes.Item) -> None:
|
||||
# Not all items have _fixtureinfo attribute.
|
||||
info: Optional[FuncFixtureInfo] = getattr(item, "_fixtureinfo", None)
|
||||
if info is None or not info.name2fixturedefs:
|
||||
# This test item does not use any fixtures.
|
||||
return
|
||||
tw.line()
|
||||
tw.sep("-", f"fixtures used by {item.name}")
|
||||
# TODO: Fix this type ignore.
|
||||
tw.sep("-", f"({get_best_relpath(item.function)})") # type: ignore[attr-defined]
|
||||
# dict key not used in loop but needed for sorting.
|
||||
for _, fixturedefs in sorted(info.name2fixturedefs.items()):
|
||||
assert fixturedefs is not None
|
||||
if not fixturedefs:
|
||||
continue
|
||||
# Last item is expected to be the one used by the test item.
|
||||
write_fixture(fixturedefs[-1])
|
||||
|
||||
for session_item in session.items:
|
||||
write_item(session_item)
|
||||
|
||||
|
||||
def showfixtures(config: Config) -> Union[int, ExitCode]:
|
||||
from _pytest.main import wrap_session
|
||||
|
||||
return wrap_session(config, _showfixtures_main)
|
||||
|
||||
|
||||
def write_docstring(tw: TerminalWriter, doc: str, indent: str = " ") -> None:
|
||||
for line in doc.split("\n"):
|
||||
tw.line(indent + line)
|
Loading…
Reference in New Issue