Coverage for human_requests/pytest_plugin/_config.py: 85%
67 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-05-28 00:39 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-05-28 00:39 +0000
1from __future__ import annotations
3import importlib
4import inspect
5from typing import Any
7import pytest
9from ._constants import (
10 AUTOTEST_INI_KEY,
11 AUTOTEST_TRACE_LIMIT_INI_KEY,
12 AUTOTEST_TRUNCATION_CONTEXT_LINES_INI_KEY,
13 AUTOTEST_TYPECHECK_INI_KEY,
14 VALID_TYPECHECK_MODES,
15)
18def register_ini_options(parser: pytest.Parser) -> None:
19 parser.addini(
20 AUTOTEST_INI_KEY,
21 default="",
22 help="Dotted import path to the root API class, e.g. package_name.StartClass",
23 )
24 parser.addini(
25 AUTOTEST_TYPECHECK_INI_KEY,
26 default="off",
27 help="Autotest params type checking mode: off, warn, strict.",
28 )
29 parser.addini(
30 AUTOTEST_TRACE_LIMIT_INI_KEY,
31 default="3",
32 help=(
33 "Maximum number of Source blocks shown in crash reports. Use 0 to "
34 "hide the source chain."
35 ),
36 )
37 parser.addini(
38 AUTOTEST_TRUNCATION_CONTEXT_LINES_INI_KEY,
39 default="3",
40 help=(
41 "How many source context lines to keep on each side of a split crash "
42 "report excerpt before the … skipped N lines … marker."
43 ),
44 )
47def get_start_class_path(config: pytest.Config) -> str:
48 return str(config.getini(AUTOTEST_INI_KEY)).strip()
51def get_typecheck_mode(config: pytest.Config) -> str:
52 raw = str(config.getini(AUTOTEST_TYPECHECK_INI_KEY)).strip().lower()
53 if not raw:
54 return "off"
55 if raw in VALID_TYPECHECK_MODES:
56 return raw
58 expected = ", ".join(sorted(VALID_TYPECHECK_MODES))
59 raise pytest.UsageError(
60 f"Invalid {AUTOTEST_TYPECHECK_INI_KEY} value {raw!r}. Expected one of: {expected}."
61 )
64def get_trace_limit(config: pytest.Config) -> int:
65 raw = str(config.getini(AUTOTEST_TRACE_LIMIT_INI_KEY)).strip()
66 if not raw:
67 return 3
69 try:
70 value = int(raw)
71 except ValueError as error:
72 raise pytest.UsageError(
73 f"Invalid {AUTOTEST_TRACE_LIMIT_INI_KEY} value {raw!r}. "
74 "Expected a non-negative integer."
75 ) from error
77 if value < 0:
78 raise pytest.UsageError(
79 f"Invalid {AUTOTEST_TRACE_LIMIT_INI_KEY} value {raw!r}. "
80 "Expected a non-negative integer."
81 )
82 return value
85def get_truncation_context_lines(config: pytest.Config) -> int:
86 raw = str(config.getini(AUTOTEST_TRUNCATION_CONTEXT_LINES_INI_KEY)).strip()
87 if not raw:
88 return 3
90 try:
91 value = int(raw)
92 except ValueError as error:
93 raise pytest.UsageError(
94 f"Invalid {AUTOTEST_TRUNCATION_CONTEXT_LINES_INI_KEY} value {raw!r}. "
95 "Expected a non-negative integer."
96 ) from error
98 if value < 0:
99 raise pytest.UsageError(
100 f"Invalid {AUTOTEST_TRUNCATION_CONTEXT_LINES_INI_KEY} value {raw!r}. "
101 "Expected a non-negative integer."
102 )
103 return value
106def resolve_runtime_dependencies(request: pytest.FixtureRequest) -> tuple[object, Any]:
107 start_class_path = get_start_class_path(request.config)
108 if not start_class_path:
109 raise pytest.UsageError(
110 f"{AUTOTEST_INI_KEY} must be configured when autotest plugin is enabled."
111 )
113 start_class = import_start_class(start_class_path)
115 api = request.getfixturevalue("api")
116 if not isinstance(api, start_class):
117 expected = f"{start_class.__module__}.{start_class.__qualname__}"
118 actual = f"{type(api).__module__}.{type(api).__qualname__}"
119 raise TypeError(f"`api` fixture must return an instance of {expected}. " f"Got {actual}.")
121 schemashot = request.getfixturevalue("schemashot")
122 return api, schemashot
125def import_start_class(dotted_path: str) -> type[Any]:
126 module_name, separator, class_name = dotted_path.rpartition(".")
127 if not separator or not module_name or not class_name:
128 raise pytest.UsageError(
129 f"Invalid {AUTOTEST_INI_KEY} value {dotted_path!r}. Expected format: module.StartClass"
130 )
132 try:
133 module = importlib.import_module(module_name)
134 except Exception as error: # pragma: no cover - importlib already provides full details
135 raise pytest.UsageError(
136 f"Cannot import module {module_name!r} from {AUTOTEST_INI_KEY}={dotted_path!r}."
137 ) from error
139 if not hasattr(module, class_name):
140 raise pytest.UsageError(
141 f"Class {class_name!r} was not found in module {module_name!r} "
142 f"from {AUTOTEST_INI_KEY}={dotted_path!r}."
143 )
145 start_class = getattr(module, class_name)
146 if not inspect.isclass(start_class):
147 raise pytest.UsageError(f"{AUTOTEST_INI_KEY}={dotted_path!r} must point to a class.")
149 return start_class