Skip to content

Commit 6890312

Browse files
committed
docs(_ext[sphinx_pytest_fixtures]): explicit :kind: option; deprecate heuristics (B5)
why: _is_factory and _is_overridable were fragile heuristics — uppercase-first name and docstring keyword scanning. Authors writing manual .. py:fixture:: blocks had no way to set the kind explicitly. what: - Add _infer_kind(obj, explicit_kind) with priority chain: explicit :kind: option > type annotation (factory) > heuristic (override_hook) > resource - Add "kind" to PyFixtureDirective.option_spec so :kind: override_hook works in RST source - Render kind as a "Kind" field in transform_content when non-default - Route add_directive_header through _infer_kind instead of emitting bare :factory: / :overridable: flags - Keep _is_factory and _is_overridable as internal helpers (used by _infer_kind); all 10 integration tests now pass including test_kind_override_hook_option
1 parent 86e5b1b commit 6890312

1 file changed

Lines changed: 45 additions & 4 deletions

File tree

docs/_ext/sphinx_pytest_fixtures.py

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,38 @@ def _is_overridable(obj: t.Any) -> bool:
390390
return "override" in doc.lower() or "conftest" in doc.lower()
391391

392392

393+
def _infer_kind(obj: t.Any, explicit_kind: str | None = None) -> str:
394+
"""Return the fixture kind, honouring an explicit override.
395+
396+
Priority chain:
397+
398+
1. *explicit_kind* — set via ``:kind:`` directive option by the author.
399+
2. Type annotation — ``type[X]`` / ``Callable`` → ``"factory"``.
400+
3. Heuristic overridable detection → ``"override_hook"``.
401+
4. Default → ``"resource"``.
402+
403+
Parameters
404+
----------
405+
obj : Any
406+
A pytest fixture wrapper object.
407+
explicit_kind : str | None
408+
Value from the ``:kind:`` directive option, if provided.
409+
410+
Returns
411+
-------
412+
str
413+
One of ``"resource"``, ``"factory"``, or ``"override_hook"`` (or any
414+
custom string passed via ``:kind:``).
415+
"""
416+
if explicit_kind:
417+
return explicit_kind
418+
if _is_factory(obj):
419+
return "factory"
420+
if _is_overridable(obj):
421+
return "override_hook"
422+
return "resource"
423+
424+
393425
# ---------------------------------------------------------------------------
394426
# PyFixtureDirective — py:fixture domain directive
395427
# ---------------------------------------------------------------------------
@@ -415,6 +447,7 @@ class PyFixtureDirective(PyFunction):
415447
"depends": directives.unchanged,
416448
"factory": directives.flag,
417449
"overridable": directives.flag,
450+
"kind": directives.unchanged, # explicit kind override
418451
"return-type": directives.unchanged,
419452
"usage": directives.unchanged, # "auto" (default) or "none"
420453
},
@@ -511,6 +544,7 @@ def transform_content(
511544
depends_str = self.options.get("depends", "")
512545
ret_type = self.options.get("return-type", "")
513546
show_usage = self.options.get("usage", "auto") != "none"
547+
kind = self.options.get("kind", "")
514548

515549
field_list = nodes.field_list()
516550

@@ -521,6 +555,14 @@ def transform_content(
521555
nodes.field_body("", nodes.paragraph("", scope)),
522556
)
523557

558+
# --- Kind field (only when explicitly set or non-default) ---
559+
if kind and kind != "resource":
560+
field_list += nodes.field(
561+
"",
562+
nodes.field_name("", "Kind"),
563+
nodes.field_body("", nodes.paragraph("", kind)),
564+
)
565+
524566
# --- Depends-on fields — project deps as :fixture: xrefs,
525567
# builtin/external deps as external hyperlinks ---
526568
if depends_str:
@@ -713,10 +755,9 @@ def add_directive_header(self, sig: str) -> None:
713755
if ret is not inspect.Parameter.empty:
714756
self.add_line(f" :return-type: {_format_type_short(ret)}", sourcename)
715757

716-
if _is_factory(self.object):
717-
self.add_line(" :factory:", sourcename)
718-
elif _is_overridable(self.object):
719-
self.add_line(" :overridable:", sourcename)
758+
kind = _infer_kind(self.object)
759+
if kind != "resource":
760+
self.add_line(f" :kind: {kind}", sourcename)
720761

721762

722763
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)