Skip to content

Opt-in FunctionDefinition collection tree node (#3926)#14769

Draft
RonnyPfannschmidt wants to merge 1 commit into
pytest-dev:mainfrom
RonnyPfannschmidt:feature/function-definition-collection-node
Draft

Opt-in FunctionDefinition collection tree node (#3926)#14769
RonnyPfannschmidt wants to merge 1 commit into
pytest-dev:mainfrom
RonnyPfannschmidt:feature/function-definition-collection-node

Conversation

@RonnyPfannschmidt

Copy link
Copy Markdown
Member

Closes #3926.

Promotes the internal FunctionDefinition from a transient parametrization
helper to a real collector node in the collection tree, behind an opt-in ini
option.

collect_function_definition (tri-state string, default hidden)

Mode Tree Function-level markers
hidden (default) flat, definition kept out of the tree on the Function (legacy)
pedantic definition node inserted scoped to the definition; invocation owns only its callspec marks
messy definition node inserted transferred back onto each invocation (legacy layout), + header warning

messy is a migration stopgap for code that is not yet prepared for the
definition scope — it reproduces the old duplicated-marker layout so bad code
keeps working. The target is pedantic.

What changes

  • FunctionDefinition becomes a PyCollector (no longer a Function/Item), so
    it is collected rather than run. Its collect() runs pytest_generate_tests
    and yields the invocations.
  • Invocation node ids stay flat and identical across all modes
    (test_mod.py::test_x[0]), so -k, caching, --lf, xdist and reporting are
    unaffected.
  • obj/instance resolution and getmodpath transparently skip an interposed
    definition node.
  • Marker scoping is correct in every mode (iter_markers yields each mark once).

The default (hidden) path is behavior-preserving; the whole test suite passes
unchanged.

Known warts / follow-up TODOs

These are intentionally left as follow-ups (inline TODO(#3926) where relevant),
to keep this PR focused — happy to split into a tracking issue:

  1. Item-scoped getfixtureinfo on a collector. The fixture closure must be
    computed before the invocations exist, so FunctionDefinition._generate_functions
    calls the item-scoped getfixtureinfo on the collector via a cast. Needs a
    node-level entry point for closure computation. (TODO(#3926) inline.)
  2. messy mode is temporary. It exists only to unblock migration and should
    be removed once consumers move to the definition scope. Marked clearly in the
    docs and header warning.
  3. Collector/item node-id collision. For non-parametrized tests the definition
    node and its sole Function child share a node id. Accepted for now; the
    structured-nodeids work will give these a better data structure.
  4. originalname could now become a read-only property returning the
    definition's name (see the existing note in Function.__init__).

🤖 Generated with Claude Code

Introduce the ``collect_function_definition`` ini option to promote the
internal ``FunctionDefinition`` from a transient parametrization helper to
a real collector node in the collection tree.

The option is tri-state:

- ``hidden`` (default): unchanged flat layout; the definition drives
  parametrization and is kept out of the tree.
- ``pedantic``: insert the definition node between the Module/Class and its
  test functions; function-level markers are scoped to the definition and
  each invocation owns only its callspec markers.
- ``messy``: migration stopgap -- insert the node but transfer the
  function-level markers back onto each invocation to preserve the legacy
  marker layout for code not yet prepared for the new scope; emits a header
  warning.

FunctionDefinition becomes a PyCollector (no longer a Function/Item), so it
is collected rather than run. Invocation node ids stay flat and identical
across all modes, so selection, caching and reporting are unaffected. obj
and instance resolution and getmodpath skip an interposed definition node.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

introduce FunctionDefinition with a scope to the official collection tree

1 participant