Adjust verbosity level retrival

* Use enum instead of string
* Change method name to simple get
* Make type registering internal
This commit is contained in:
Patrick Lannigan 2023-10-31 16:23:50 -04:00
parent ec76cf55f0
commit 933742a729
No known key found for this signature in database
GPG Key ID: 9E91A0EC425AC415
6 changed files with 41 additions and 28 deletions

View File

@ -13,6 +13,7 @@ from _pytest.assertion.rewrite import assertstate_key
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import hookimpl from _pytest.config import hookimpl
from _pytest.config import OutputVerbosity from _pytest.config import OutputVerbosity
from _pytest.config import VerbosityType
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.nodes import Item from _pytest.nodes import Item
@ -43,9 +44,9 @@ def pytest_addoption(parser: Parser) -> None:
help="Enables the pytest_assertion_pass hook. " help="Enables the pytest_assertion_pass hook. "
"Make sure to delete any previously generated pyc cache files.", "Make sure to delete any previously generated pyc cache files.",
) )
OutputVerbosity.add_ini( OutputVerbosity._add_ini(
parser, parser,
"assertions", VerbosityType.Assertions,
help=( help=(
"Specify a verbosity level for assertions, overriding the main level. " "Specify a verbosity level for assertions, overriding the main level. "
"Higher levels will provide more detailed explanation when an assertion fails." "Higher levels will provide more detailed explanation when an assertion fails."

View File

@ -7,9 +7,9 @@ from typing import List
from typing import Optional from typing import Optional
from _pytest.assertion import util from _pytest.assertion import util
from _pytest.config import VerbosityType
from _pytest.nodes import Item from _pytest.nodes import Item
DEFAULT_MAX_LINES = 8 DEFAULT_MAX_LINES = 8
DEFAULT_MAX_CHARS = 8 * 80 DEFAULT_MAX_CHARS = 8 * 80
USAGE_MSG = "use '-vv' to show" USAGE_MSG = "use '-vv' to show"
@ -26,7 +26,7 @@ def truncate_if_required(
def _should_truncate_item(item: Item) -> bool: def _should_truncate_item(item: Item) -> bool:
"""Whether or not this test item is eligible for truncation.""" """Whether or not this test item is eligible for truncation."""
verbose = item.config.output_verbosity.verbosity_for("assertions") verbose = item.config.output_verbosity.get(VerbosityType.Assertions)
return verbose < 2 and not util.running_on_ci() return verbose < 2 and not util.running_on_ci()

View File

@ -18,6 +18,7 @@ from _pytest._io.saferepr import _pformat_dispatch
from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr
from _pytest._io.saferepr import saferepr_unlimited from _pytest._io.saferepr import saferepr_unlimited
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import VerbosityType
# The _reprcompare attribute on the util module is used by the new assertion # The _reprcompare attribute on the util module is used by the new assertion
# interpretation code and assertion rewriter to detect this plugin was # interpretation code and assertion rewriter to detect this plugin was
@ -161,7 +162,7 @@ def assertrepr_compare(
config, op: str, left: Any, right: Any, use_ascii: bool = False config, op: str, left: Any, right: Any, use_ascii: bool = False
) -> Optional[List[str]]: ) -> Optional[List[str]]:
"""Return specialised explanations for some operators/operands.""" """Return specialised explanations for some operators/operands."""
verbose = config.output_verbosity.verbosity_for("assertions") verbose = config.output_verbosity.get(VerbosityType.Assertions)
# Strings which normalize equal are often hard to distinguish when printed; use ascii() to make this easier. # Strings which normalize equal are often hard to distinguish when printed; use ascii() to make this easier.
# See issue #3246. # See issue #3246.

View File

@ -13,6 +13,7 @@ import shlex
import sys import sys
import types import types
import warnings import warnings
from enum import Enum
from functools import lru_cache from functools import lru_cache
from pathlib import Path from pathlib import Path
from textwrap import dedent from textwrap import dedent
@ -1663,6 +1664,13 @@ class Config:
) )
class VerbosityType(Enum):
"""Fine-grained verbosity categories."""
Global = "global"
Assertions = "assertions"
class OutputVerbosity: class OutputVerbosity:
DEFAULT = "auto" DEFAULT = "auto"
_option_name_fmt = "verbosity_{}" _option_name_fmt = "verbosity_{}"
@ -1675,36 +1683,36 @@ class OutputVerbosity:
"""Application wide verbosity level.""" """Application wide verbosity level."""
return cast(int, self._config.option.verbose) return cast(int, self._config.option.verbose)
def verbosity_for(self, output_type: str) -> int: def get(self, verbosity_type: VerbosityType = VerbosityType.Global) -> int:
"""Return verbosity level for the given output type. """Return verbosity level for the given output type.
:param output_type: Name of the output type. :param verbosity_type: Fine-grained verbosity category.
If the level is not configured, the value of ``config.option.verbose``. If the level is not configured, the value of ``config.option.verbose``.
""" """
level = self._config.getini(OutputVerbosity._ini_name(output_type)) level = self._config.getini(OutputVerbosity._ini_name(verbosity_type))
if level == OutputVerbosity.DEFAULT: if level == OutputVerbosity.DEFAULT:
return self.verbose return self.verbose
return int(level) return int(level)
@staticmethod @staticmethod
def _ini_name(output_type: str) -> str: def _ini_name(verbosity_type: VerbosityType) -> str:
return f"verbosity_{output_type}" return f"verbosity_{verbosity_type.value}"
@staticmethod @staticmethod
def add_ini(parser: "Parser", output_type: str, help: str) -> None: def _add_ini(parser: "Parser", verbosity_type: VerbosityType, help: str) -> None:
"""Add a output verbosity configuration option for the given output type. """Add a output verbosity configuration option for the given output type.
:param parser: Parser for command line arguments and ini-file values. :param parser: Parser for command line arguments and ini-file values.
:param output_type: Name of the output type. :param verbosity_type: Fine-grained verbosity category.
:param help: Description of the output this type controls. :param help: Description of the output this type controls.
The value should be retrieved via a call to The value should be retrieved via a call to
:py:func:`config.output_verbosity.verbosity_for(name) <pytest.OutputVerbosity.verbosity_for>`. :py:func:`config.output_verbosity.get(type) <pytest.OutputVerbosity.get>`.
""" """
parser.addini( parser.addini(
OutputVerbosity._ini_name(output_type), OutputVerbosity._ini_name(verbosity_type),
help=help, help=help,
type="string", type="string",
default=OutputVerbosity.DEFAULT, default=OutputVerbosity.DEFAULT,

View File

@ -13,6 +13,7 @@ import pytest
from _pytest import outcomes from _pytest import outcomes
from _pytest.assertion import truncate from _pytest.assertion import truncate
from _pytest.assertion import util from _pytest.assertion import util
from _pytest.config import VerbosityType
from _pytest.monkeypatch import MonkeyPatch from _pytest.monkeypatch import MonkeyPatch
from _pytest.pytester import Pytester from _pytest.pytester import Pytester
@ -23,13 +24,13 @@ def mock_config(verbose: int = 0, assertion_override: Optional[int] = None):
def verbose(self) -> int: def verbose(self) -> int:
return verbose return verbose
def verbosity_for(self, output_type: str) -> int: def get(self, verbosity_type: VerbosityType = VerbosityType.Global) -> int:
if output_type == "assertions": if verbosity_type == VerbosityType.Assertions:
if assertion_override is not None: if assertion_override is not None:
return assertion_override return assertion_override
return verbose return verbose
raise KeyError("Not mocked out: %s" % output_type) raise KeyError(f"Not mocked out: {verbosity_type}")
class Config: class Config:
def __init__(self) -> None: def __init__(self) -> None:
@ -47,30 +48,30 @@ class TestMockConfig:
assert config.output_verbosity.verbose == TestMockConfig.SOME_VERBOSITY_LEVEL assert config.output_verbosity.verbose == TestMockConfig.SOME_VERBOSITY_LEVEL
def test_verbosity_for_assertion_override_not_set_verbose_value(self): def test_get_assertion_override_not_set_verbose_value(self):
config = mock_config(verbose=TestMockConfig.SOME_VERBOSITY_LEVEL) config = mock_config(verbose=TestMockConfig.SOME_VERBOSITY_LEVEL)
assert ( assert (
config.output_verbosity.verbosity_for("assertions") config.output_verbosity.get(VerbosityType.Assertions)
== TestMockConfig.SOME_VERBOSITY_LEVEL == TestMockConfig.SOME_VERBOSITY_LEVEL
) )
def test_verbosity_for_assertion_override_set_custom_value(self): def test_get_assertion_override_set_custom_value(self):
config = mock_config( config = mock_config(
verbose=TestMockConfig.SOME_VERBOSITY_LEVEL, verbose=TestMockConfig.SOME_VERBOSITY_LEVEL,
assertion_override=TestMockConfig.SOME_OTHER_VERBOSITY_LEVEL, assertion_override=TestMockConfig.SOME_OTHER_VERBOSITY_LEVEL,
) )
assert ( assert (
config.output_verbosity.verbosity_for("assertions") config.output_verbosity.get(VerbosityType.Assertions)
== TestMockConfig.SOME_OTHER_VERBOSITY_LEVEL == TestMockConfig.SOME_OTHER_VERBOSITY_LEVEL
) )
def test_verbosity_for_unsupported_type_error(self): def test_get_unsupported_type_error(self):
config = mock_config(verbose=TestMockConfig.SOME_VERBOSITY_LEVEL) config = mock_config(verbose=TestMockConfig.SOME_VERBOSITY_LEVEL)
with pytest.raises(KeyError): with pytest.raises(KeyError):
config.output_verbosity.verbosity_for("NOT CONFIGURED NAME") config.output_verbosity.get(VerbosityType.Global)
class TestImportHookInstallation: class TestImportHookInstallation:

View File

@ -22,6 +22,7 @@ from _pytest.config import ConftestImportFailure
from _pytest.config import ExitCode from _pytest.config import ExitCode
from _pytest.config import OutputVerbosity from _pytest.config import OutputVerbosity
from _pytest.config import parse_warning_filter from _pytest.config import parse_warning_filter
from _pytest.config import VerbosityType
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.config.exceptions import UsageError from _pytest.config.exceptions import UsageError
from _pytest.config.findpaths import determine_setup from _pytest.config.findpaths import determine_setup
@ -2186,12 +2187,12 @@ class TestDebugOptions:
class TestOutputVerbosity: class TestOutputVerbosity:
SOME_OUTPUT_TYPE = "foo" SOME_OUTPUT_TYPE = VerbosityType.Assertions
SOME_OUTPUT_VERBOSITY_LEVEL = 5 SOME_OUTPUT_VERBOSITY_LEVEL = 5
class VerbosityIni: class VerbosityIni:
def pytest_addoption(self, parser: Parser) -> None: def pytest_addoption(self, parser: Parser) -> None:
OutputVerbosity.add_ini( OutputVerbosity._add_ini(
parser, TestOutputVerbosity.SOME_OUTPUT_TYPE, help="some help text" parser, TestOutputVerbosity.SOME_OUTPUT_TYPE, help="some help text"
) )
@ -2229,19 +2230,20 @@ class TestOutputVerbosity:
config = pytester.parseconfig(tmp_path) config = pytester.parseconfig(tmp_path)
assert ( assert (
config.output_verbosity.verbosity_for(TestOutputVerbosity.SOME_OUTPUT_TYPE) config.output_verbosity.get(TestOutputVerbosity.SOME_OUTPUT_TYPE)
== config.output_verbosity.verbose == config.output_verbosity.verbose
) )
def test_level_matches_specified_override( def test_level_matches_specified_override(
self, pytester: Pytester, tmp_path: Path self, pytester: Pytester, tmp_path: Path
) -> None: ) -> None:
setting_name = f"verbosity_{TestOutputVerbosity.SOME_OUTPUT_TYPE.value}"
tmp_path.joinpath("pytest.ini").write_text( tmp_path.joinpath("pytest.ini").write_text(
textwrap.dedent( textwrap.dedent(
f"""\ f"""\
[pytest] [pytest]
addopts = --verbose addopts = --verbose
verbosity_{TestOutputVerbosity.SOME_OUTPUT_TYPE} = {TestOutputVerbosity.SOME_OUTPUT_VERBOSITY_LEVEL} {setting_name} = {TestOutputVerbosity.SOME_OUTPUT_VERBOSITY_LEVEL}
""" """
), ),
encoding="utf-8", encoding="utf-8",
@ -2251,6 +2253,6 @@ class TestOutputVerbosity:
config = pytester.parseconfig(tmp_path) config = pytester.parseconfig(tmp_path)
assert ( assert (
config.output_verbosity.verbosity_for(TestOutputVerbosity.SOME_OUTPUT_TYPE) config.output_verbosity.get(TestOutputVerbosity.SOME_OUTPUT_TYPE)
== TestOutputVerbosity.SOME_OUTPUT_VERBOSITY_LEVEL == TestOutputVerbosity.SOME_OUTPUT_VERBOSITY_LEVEL
) )