Skip to content

Accept MarkDecorator as get_closest_marker default - #14833

Open
ace2016 wants to merge 1 commit into
pytest-dev:mainfrom
ace2016:fix-13354-marker-default
Open

Accept MarkDecorator as get_closest_marker default#14833
ace2016 wants to merge 1 commit into
pytest-dev:mainfrom
ace2016:fix-13354-marker-default

Conversation

@ace2016

@ace2016 ace2016 commented Aug 4, 2026

Copy link
Copy Markdown

closes #13354

Problem

Node.get_closest_marker(name, default) documents and type-hints its default as a Mark:

@overload
def get_closest_marker(self, name: str, default: Mark) -> Mark: ...

But Mark.__init__ is private-gated — it ends in check_ispytest(_ispytest), which raises a PytestDeprecationWarning ("A private pytest class or function was used.") when a user constructs a Mark directly. That leaves the public parameter with no supported way to produce a value: the API asks for a Mark, and the obvious way to build one warns.

Approach

So get_closest_marker now also accepts a MarkDecorator and unwraps it:

if isinstance(default, MarkDecorator):
    default = default.mark
# now works, no warning
item.get_closest_marker("foo", pytest.mark.foo(1))

pytest.mark.foo(1) builds its Mark internally with _ispytest=True, so nothing warns.

Changes

File Change
src/_pytest/nodes.py Widen default to Mark | MarkDecorator, unwrap to .mark, document it
testing/test_mark.py Regression test alongside the existing test_mark_closest
changelog/13354.improvement.rst Changelog entry
AUTHORS Added myself

doc/en/reference/reference.rst needed no edit — it autodocs the method, so the updated docstring flows through.

Testing

  • testing/test_mark.py and testing/test_nodes.py pass (124 passed, 1 xfailed).
  • The new test is a genuine regression test: reverting only the nodes.py change makes it fail, restoring it makes it pass.
  • Full pre-commit on all changed files passes, including mypy, ruff, ruff format, and codespell.

The new test uses the registered dummy marker foo from pyproject.toml rather than an ad-hoc name, because the decorator is constructed in the outer test process where pytest's own suite runs with --strict-markers.

##Checklist:

  • Include documentation when adding new features.
    -> The method docstring is updated; reference docs autodoc it.
  • Include new tests or update existing tests when applicable.
  • Allow maintainers to push and squash when merging my commits.
  • Add text like closes #XYZW to the PR description and/or commits.
  • If AI agents were used, they are credited in Co-authored-by commit trailers.
  • Create a new changelog file in the changelog directory.
  • Add yourself to AUTHORS in alphabetical order.

`Mark` is private and warns when instantiated directly, which left no
supported way to build the `default` argument. Accept a `MarkDecorator`
such as `pytest.mark.foo(1)` and unwrap it to its `Mark`.

Closes pytest-dev#13354

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Aug 4, 2026
@ace2016

ace2016 commented Aug 4, 2026

Copy link
Copy Markdown
Author

@RonnyPfannschmidt could you please take a look when you have the time? thank you

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.

Node.get_closest_marker default kwarg deprecation

2 participants