RustPython/RustPython · error · TypeError
warnings.showwarning() must be set to a function or method
Error message
warnings.showwarning() must be set to a function or method
What it means
When a warning is emitted, _py_warnings._showwarnmsg reads warnings.showwarning; if it was replaced and is not callable (None, a string, a number), TypeError is raised at display time. The check applies only when the current showwarning differs from the original implementation, so any non-callable monkeypatch of warnings triggers it lazily on the next warn(), far from the assignment that caused it.
Source
Thrown at Lib/_py_warnings.py:227
f'allocation traceback\n')
return s
# Keep a reference to check if the function was replaced
_showwarning_orig = showwarning
def _showwarnmsg(msg):
"""Hook to write a warning to a file; replace if you like."""
try:
sw = _wm.showwarning
except AttributeError:
pass
else:
if sw is not _showwarning_orig:
# warnings.showwarning() was replaced
if not callable(sw):
raise TypeError("warnings.showwarning() must be set to a "
"function or method")
sw(msg.message, msg.category, msg.filename, msg.lineno,
msg.file, msg.line)
return
_wm._showwarnmsg_impl(msg)
# Keep a reference to check if the function was replaced
_formatwarning_orig = formatwarning
def _formatwarnmsg(msg):
"""Function to format a warning the standard way."""
try:
fw = _wm.formatwarning
except AttributeError:
passView on GitHub (pinned to aaeab4f754)
Solutions
- To silence warnings use the supported filter API: `warnings.filterwarnings('ignore')` - never assign to showwarning
- If you must replace it, assign a callable with signature (message, category, filename, lineno, file=None, line=None)
- Save and restore the original via warnings.catch_warnings() so state never leaks between tests
Example fix
# before
import warnings
warnings.showwarning = None # later: TypeError at warn() time
warnings.warn('deprecated')
# after
warnings.filterwarnings('ignore') # supported way to silence
warnings.warn('deprecated')
# or a proper replacement:
import logging
def _sw(message, category, filename, lineno, file=None, line=None):
logging.getLogger('py.warnings').warning('%s:%s: %s: %s', filename, lineno, category.__name__, message)
warnings.showwarning = _sw Defensive patterns
Strategy: validation
Validate before calling
import warnings
def showwarning_usable() -> bool:
return callable(getattr(warnings, 'showwarning', None)) Try / catch
try:
warnings.warn(msg)
except TypeError:
warnings.showwarning = warnings._showwarning_orig # restore default
warnings.warn(msg) Prevention
- Use filterwarnings, not assignment, to suppress warnings
- When monkeypatching, restore in finally or use warnings.catch_warnings
- Assert callable(warnings.showwarning) in test teardown
When it happens
Trigger: `warnings.showwarning = None` (a common but wrong attempt to silence warnings) followed by any `warnings.warn(...)`; assigning a logging format string or config dict to warnings.showwarning.
Common situations: Libraries trying to suppress warnings by clobbering showwarning; test harnesses monkeypatching warnings without restoring; serialized/restored module state that loses the function reference.
Related errors
- message must be a string
- category must be a Warning subclass
- module must be a string
- lineno must be an int
- category must be a Warning subclass, not '{:s}'
AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17).
Data as JSON: /api/errors/b5f6bf2bcf6466a4.
Report an issue: GitHub.