Skip to content

Emit deprecations through WarningTemplate.warn; fix the instance #14931 missed - #15137

Draft
RonnyPfannschmidt wants to merge 1 commit into
pytest-dev:mainfrom
RonnyPfannschmidt:fix-14912-fresh-deprecation-warnings
Draft

RonnyPfannschmidt wants to merge 1 commit into
pytest-dev:mainfrom
RonnyPfannschmidt:fix-14912-fresh-deprecation-warnings

Conversation

@RonnyPfannschmidt

@RonnyPfannschmidt RonnyPfannschmidt commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Written by Claude Opus 5.5 via Claude Code for the pytest maintainers; I prompted it, it did the work, I read it.

Follow-up to #14931, which fixed #14912 by making the constants in _pytest.deprecated UnformattedWarnings, with each call site doing warnings.warn(X.format(), stacklevel=N).

Change

  • INI_STRING_TYPE_NON_STR_VALUE was still a shared PytestRemovedIn10Warning instance, so under -W error its traceback still grew with every raise. It is a template now.
  • UnformattedWarning becomes WarningTemplate, keeping the old name as an alias. WarningTemplate.warn(*, stacklevel=1, **kwargs) builds the fresh instance and accounts for its own frame, so call sites keep their stacklevel. It also hides that frame from tracebacks. All call sites use it.
  • format() runs str.format() only when kwargs are given, so constant messages may contain literal braces.

Tests

  • A guard walks every _pytest module and fails on any module-level Warning instance. It found the one above.
  • Context from an unrelated exception does not leak into a later emission.
  • Every template's placeholders are well formed.
  • warn() reports the caller's frame for each stacklevel.

Open question

  • Keep the UnformattedWarning alias? _pytest.warning_types is private.

@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Oct 5, 2026
Follow-up to pytest-dev#14931, which made every constant in _pytest.deprecated an
UnformattedWarning and had each call site do
warnings.warn(X.format(), stacklevel=N).

Rename UnformattedWarning to WarningTemplate, keeping the old name as an
alias, and give it warn(): it builds the fresh instance, absorbs the +1
stacklevel for its own frame so callers keep the stacklevel they had, and
hides that frame from tracebacks. format() only runs str.format() when
kwargs are given, so constant messages may carry literal braces.

A guard test walks every _pytest module for module-level Warning
instances. It found INI_STRING_TYPE_NON_STR_VALUE, which pytest-dev#14931 missed
and which still grew its traceback under -W error; it is a template now.

Co-Authored-By: Claude Opus 5.5 via Claude Code <noreply@anthropic.com>
@RonnyPfannschmidt
RonnyPfannschmidt force-pushed the fix-14912-fresh-deprecation-warnings branch from a70925f to 4cddffa Compare October 14, 2026 07:32
@RonnyPfannschmidt RonnyPfannschmidt changed the title Build deprecation warnings fresh per emission (#14912) Emit deprecations through WarningTemplate.warn; fix the instance #14931 missed Oct 14, 2026

This branch has not been deployed

No deployments
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.

Shared PytestWarning instances in deprecated.py accumulate tracebacks under -W error

1 participant