Skip to content

Commit 5448db8

Browse files
committed
clean up
1 parent 357c274 commit 5448db8

3 files changed

Lines changed: 42 additions & 40 deletions

File tree

python/lib/sift_client/_tests/_pytester_fakes.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from __future__ import annotations
99

10+
import itertools
1011
import json
1112
from typing import TYPE_CHECKING, Any
1213
from unittest.mock import MagicMock
@@ -39,8 +40,6 @@ def update(self, fields: dict[str, Any]) -> None:
3940

4041

4142
class FakeReportContext:
42-
_counter = 0
43-
4443
def __init__(self, steps_file: Path) -> None:
4544
self.steps_file = steps_file
4645
self.report = FakeReport()
@@ -51,6 +50,7 @@ def __init__(self, steps_file: Path) -> None:
5150
self.any_failures = False
5251
self.log_file: Path | None = None
5352
self.steps: list[dict[str, Any]] = []
53+
self._ids = itertools.count(1)
5454

5555
def __enter__(self) -> FakeReportContext:
5656
return self
@@ -90,11 +90,10 @@ def create_step(
9090
description: str | None = None,
9191
metadata: dict[str, Any] | None = None,
9292
) -> FakeStep:
93-
type(self)._counter += 1
9493
step_path = self.get_next_step_path()
9594
parent = self.step_stack[-1] if self.step_stack else None
9695
step = FakeStep(
97-
id_=f"step-{type(self)._counter}",
96+
id_=f"step-{next(self._ids)}",
9897
name=name,
9998
parent_step_id=parent.id_ if parent else None,
10099
step_path=step_path,

python/lib/sift_client/_tests/test_pytest_plugin_parametrize.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from __future__ import annotations
1313

1414
import json
15-
import os
1615
from textwrap import dedent
1716
from typing import TYPE_CHECKING
1817

@@ -58,11 +57,12 @@ def client_has_connection() -> bool:
5857
return False
5958

6059

61-
def _setup(pytester: pytest.Pytester) -> Path:
62-
steps_file = pytester.path / "captured_steps.json"
60+
@pytest.fixture
61+
def steps_file(pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch) -> Path:
62+
path = pytester.path / "captured_steps.json"
6363
pytester.makeconftest(_INNER_CONFTEST)
64-
os.environ[_STEPS_FILE_ENV] = str(steps_file)
65-
return steps_file
64+
monkeypatch.setenv(_STEPS_FILE_ENV, str(path))
65+
return path
6666

6767

6868
def _by_name(steps: list[dict]) -> dict[str, list[dict]]:
@@ -72,8 +72,9 @@ def _by_name(steps: list[dict]) -> dict[str, list[dict]]:
7272
return out
7373

7474

75-
def test_single_parametrize_clusters_under_originalname(pytester: pytest.Pytester) -> None:
76-
steps_file = _setup(pytester)
75+
def test_single_parametrize_clusters_under_originalname(
76+
pytester: pytest.Pytester, steps_file: Path
77+
) -> None:
7778
pytester.makepyfile(
7879
test_rail=dedent(
7980
"""
@@ -99,8 +100,9 @@ def test_rail(v):
99100
assert by_name["v=5.0"][0]["parent_step_id"] == test_rail_id
100101

101102

102-
def test_stacked_parametrize_nests_outer_to_inner(pytester: pytest.Pytester) -> None:
103-
steps_file = _setup(pytester)
103+
def test_stacked_parametrize_nests_outer_to_inner(
104+
pytester: pytest.Pytester, steps_file: Path
105+
) -> None:
104106
pytester.makepyfile(
105107
test_iso=dedent(
106108
"""
@@ -137,8 +139,7 @@ def test_iso(voltage, component):
137139
assert leaf["parent_step_id"] in voltage_ids
138140

139141

140-
def test_fixture_parametrization_participates(pytester: pytest.Pytester) -> None:
141-
steps_file = _setup(pytester)
142+
def test_fixture_parametrization_participates(pytester: pytest.Pytester, steps_file: Path) -> None:
142143
pytester.makepyfile(
143144
test_widget=dedent(
144145
"""
@@ -163,8 +164,9 @@ def test_widget(widget):
163164
assert by_name["widget='b'"][0]["parent_step_id"] == parent_id
164165

165166

166-
def test_module_boundary_isolates_parametrize_stack(pytester: pytest.Pytester) -> None:
167-
steps_file = _setup(pytester)
167+
def test_module_boundary_isolates_parametrize_stack(
168+
pytester: pytest.Pytester, steps_file: Path
169+
) -> None:
168170
pytester.makepyfile(
169171
test_a=dedent(
170172
"""
@@ -196,8 +198,9 @@ def test_two(w):
196198
assert by_name["test_two"][0]["parent_step_id"] == mod_b["id"]
197199

198200

199-
def test_leaf_parent_chain_terminates_at_report(pytester: pytest.Pytester) -> None:
200-
steps_file = _setup(pytester)
201+
def test_leaf_parent_chain_terminates_at_report(
202+
pytester: pytest.Pytester, steps_file: Path
203+
) -> None:
201204
pytester.makepyfile(
202205
test_chain=dedent(
203206
"""

python/lib/sift_client/pytest_plugin.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,15 @@
1717
REPORT_CONTEXT: ReportContext | None = None
1818

1919
_PARAMETRIZE_PATH_KEY = pytest.StashKey[tuple[str, ...]]()
20-
_PARAMETRIZE_STACK: list[NewStep] = []
20+
# Each frame: (path_key, open NewStep). Frames are shared across sibling test
21+
# items and drained at module teardown / session end.
22+
_PARAMETRIZE_STACK: list[tuple[str, NewStep]] = []
23+
24+
25+
def _drain_parametrize_stack() -> None:
26+
while _PARAMETRIZE_STACK:
27+
_, ns = _PARAMETRIZE_STACK.pop()
28+
ns.__exit__(None, None, None)
2129

2230

2331
def _build_parametrize_path(item: pytest.Item) -> tuple[str, ...]:
@@ -45,8 +53,7 @@ def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item
4553

4654
def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None:
4755
"""Drain any parametrize parents still open (e.g. when module_substep was disabled)."""
48-
while _PARAMETRIZE_STACK:
49-
_PARAMETRIZE_STACK.pop().__exit__(None, None, None)
56+
_drain_parametrize_stack()
5057

5158

5259
def pytest_addoption(parser: pytest.Parser) -> None:
@@ -201,14 +208,8 @@ def _step_impl(
201208
report_context: ReportContext, request: pytest.FixtureRequest
202209
) -> Generator[NewStep | None, None, None]:
203210
item = request.node
204-
callspec = getattr(item, "callspec", None)
205-
if callspec is not None and callspec.params:
206-
# Bottom decorator's axis is first in callspec.params, which matches the
207-
# innermost (leaf) frame in the parametrize path.
208-
axis, value = next(iter(callspec.params.items()))
209-
name = f"{axis}={value!r}"
210-
else:
211-
name = str(item.name)
211+
path = item.stash.get(_PARAMETRIZE_PATH_KEY, ())
212+
name = path[-1] if path else str(item.name)
212213
existing_docstring = item.obj.__doc__ or None
213214
with report_context.new_step(
214215
name=name, description=existing_docstring, assertion_as_fail_not_error=False
@@ -243,19 +244,20 @@ def _parametrize_parents(
243244
return
244245
desired = request.node.stash.get(_PARAMETRIZE_PATH_KEY, ())
245246
parents = desired[:-1]
246-
open_keys = [getattr(ns, "_parametrize_key", None) for ns in _PARAMETRIZE_STACK]
247247
common = 0
248248
while (
249-
common < len(open_keys) and common < len(parents) and open_keys[common] == parents[common]
249+
common < len(_PARAMETRIZE_STACK)
250+
and common < len(parents)
251+
and _PARAMETRIZE_STACK[common][0] == parents[common]
250252
):
251253
common += 1
252254
while len(_PARAMETRIZE_STACK) > common:
253-
_PARAMETRIZE_STACK.pop().__exit__(None, None, None)
255+
_, ns = _PARAMETRIZE_STACK.pop()
256+
ns.__exit__(None, None, None)
254257
for display in parents[common:]:
255258
ns = report_context.new_step(name=display, assertion_as_fail_not_error=False)
256259
ns.__enter__()
257-
ns._parametrize_key = display # type: ignore[attr-defined]
258-
_PARAMETRIZE_STACK.append(ns)
260+
_PARAMETRIZE_STACK.append((display, ns))
259261
yield
260262

261263

@@ -301,11 +303,9 @@ def module_substep(
301303
name=name, description=existing_docstring, assertion_as_fail_not_error=False
302304
) as new_step:
303305
yield new_step
304-
# Drain parametrize parents nested under this module before the module
305-
# step exits — otherwise ReportContext.exit_step asserts that the module
306-
# step is the stack top.
307-
while _PARAMETRIZE_STACK:
308-
_PARAMETRIZE_STACK.pop().__exit__(None, None, None)
306+
# Drain parametrize parents nested under this module step before it
307+
# exits — ReportContext.exit_step asserts the module step is the top.
308+
_drain_parametrize_stack()
309309

310310

311311
@pytest.fixture(scope="session")

0 commit comments

Comments
 (0)