gh-135801: Improve filtering by module in warn_explicit() without module argument (GH-140151)

* Try to match the module name pattern with module names constructed
  starting from different parent directories of the filename.
  E.g., for "/path/to/package/module" try to match with
  "path.to.package.module", "to.package.module", "package.module" and
  "module".
* Ignore trailing "/__init__.py".
* Ignore trailing ".pyw" on Windows.
* Keep matching with the full filename (without optional ".py" extension)
  for compatibility.
* Only ignore the case of the ".py" extension on Windows.
This commit is contained in:
Serhiy Storchaka 2025-10-30 15:55:39 +02:00 committed by GitHub
parent efc37ba49e
commit 6826166280
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 243 additions and 73 deletions

View file

@ -487,7 +487,14 @@ Available Functions
ignored. ignored.
*module*, if supplied, should be the module name. *module*, if supplied, should be the module name.
If no module is passed, the filename with ``.py`` stripped is used. If no module is passed, the module regular expression in
:ref:`warnings filter <warning-filter>` will be tested against the module
names constructed from the path components starting from all parent
directories (with ``/__init__.py``, ``.py`` and, on Windows, ``.pyw``
stripped) and against the filename with ``.py`` stripped.
For example, when the filename is ``'/path/to/package/module.py'``, it will
be tested against ``'path.to.package.module'``, ``'to.package.module'``
``'package.module'``, ``'module'``, and ``'/path/to/package/module'``.
*registry*, if supplied, should be the ``__warningregistry__`` dictionary *registry*, if supplied, should be the ``__warningregistry__`` dictionary
of the module. of the module.
@ -506,6 +513,10 @@ Available Functions
.. versionchanged:: 3.6 .. versionchanged:: 3.6
Add the *source* parameter. Add the *source* parameter.
.. versionchanged:: next
If no module is passed, test the filter regular expression against
module names created from the path, not only the path itself.
.. function:: showwarning(message, category, filename, lineno, file=None, line=None) .. function:: showwarning(message, category, filename, lineno, file=None, line=None)

View file

@ -611,6 +611,18 @@ unittest
(Contributed by Garry Cairns in :gh:`134567`.) (Contributed by Garry Cairns in :gh:`134567`.)
warnings
--------
* Improve filtering by module in :func:`warnings.warn_explicit` if no *module*
argument is passed.
It now tests the module regular expression in the warnings filter not only
against the filename with ``.py`` stripped, but also against module names
constructed starting from different parent directories of the filename
(with ``/__init__.py``, ``.py`` and, on Windows, ``.pyw`` stripped).
(Contributed by Serhiy Storchaka in :gh:`135801`.)
venv venv
---- ----

View file

@ -520,20 +520,50 @@ def warn(message, category=None, stacklevel=1, source=None,
) )
def _match_filename(pattern, filename, *, MS_WINDOWS=(sys.platform == 'win32')):
if not filename:
return pattern.match('<unknown>') is not None
if filename[0] == '<' and filename[-1] == '>':
return pattern.match(filename) is not None
is_py = (filename[-3:].lower() == '.py'
if MS_WINDOWS else
filename.endswith('.py'))
if is_py:
filename = filename[:-3]
if pattern.match(filename): # for backward compatibility
return True
if MS_WINDOWS:
if not is_py and filename[-4:].lower() == '.pyw':
filename = filename[:-4]
is_py = True
if is_py and filename[-9:].lower() in (r'\__init__', '/__init__'):
filename = filename[:-9]
filename = filename.replace('\\', '/')
else:
if is_py and filename.endswith('/__init__'):
filename = filename[:-9]
filename = filename.replace('/', '.')
i = 0
while True:
if pattern.match(filename, i):
return True
i = filename.find('.', i) + 1
if not i:
return False
def warn_explicit(message, category, filename, lineno, def warn_explicit(message, category, filename, lineno,
module=None, registry=None, module_globals=None, module=None, registry=None, module_globals=None,
source=None): source=None):
lineno = int(lineno) lineno = int(lineno)
if module is None:
module = filename or "<unknown>"
if module[-3:].lower() == ".py":
module = module[:-3] # XXX What about leading pathname?
if isinstance(message, Warning): if isinstance(message, Warning):
text = str(message) text = str(message)
category = message.__class__ category = message.__class__
else: else:
text = message text = message
message = category(message) message = category(message)
modules = None
key = (text, category, lineno) key = (text, category, lineno)
with _wm._lock: with _wm._lock:
if registry is None: if registry is None:
@ -549,9 +579,11 @@ def warn_explicit(message, category, filename, lineno,
action, msg, cat, mod, ln = item action, msg, cat, mod, ln = item
if ((msg is None or msg.match(text)) and if ((msg is None or msg.match(text)) and
issubclass(category, cat) and issubclass(category, cat) and
(mod is None or mod.match(module)) and (ln == 0 or lineno == ln) and
(ln == 0 or lineno == ln)): (mod is None or (_match_filename(mod, filename)
break if module is None else
mod.match(module)))):
break
else: else:
action = _wm.defaultaction action = _wm.defaultaction
# Early exit actions # Early exit actions

View file

@ -13,6 +13,7 @@
import textwrap import textwrap
import types import types
import unittest import unittest
import warnings
import weakref import weakref
from io import StringIO from io import StringIO
from pathlib import Path from pathlib import Path
@ -1069,6 +1070,19 @@ def test_tstring(self):
self.assertIsInstance(tree.body[0].value.values[0], ast.Constant) self.assertIsInstance(tree.body[0].value.values[0], ast.Constant)
self.assertIsInstance(tree.body[0].value.values[1], ast.Interpolation) self.assertIsInstance(tree.body[0].value.values[1], ast.Interpolation)
def test_filter_syntax_warnings_by_module(self):
filename = support.findfile('test_import/data/syntax_warnings.py')
with open(filename, 'rb') as f:
source = f.read()
with warnings.catch_warnings(record=True) as wlog:
warnings.simplefilter('error')
warnings.filterwarnings('always', module=r'<unknown>\z')
ast.parse(source)
self.assertEqual(sorted(wm.lineno for wm in wlog), [4, 7, 10])
for wm in wlog:
self.assertEqual(wm.filename, '<unknown>')
self.assertIs(wm.category, SyntaxWarning)
class CopyTests(unittest.TestCase): class CopyTests(unittest.TestCase):
"""Test copying and pickling AST nodes.""" """Test copying and pickling AST nodes."""

View file

@ -1088,6 +1088,28 @@ def four_freevars():
three_freevars.__globals__, three_freevars.__globals__,
closure=my_closure) closure=my_closure)
def test_exec_filter_syntax_warnings_by_module(self):
filename = support.findfile('test_import/data/syntax_warnings.py')
with open(filename, 'rb') as f:
source = f.read()
with warnings.catch_warnings(record=True) as wlog:
warnings.simplefilter('error')
warnings.filterwarnings('always', module=r'<string>\z')
exec(source, {})
self.assertEqual(sorted(wm.lineno for wm in wlog), [4, 7, 10, 13, 14, 21])
for wm in wlog:
self.assertEqual(wm.filename, '<string>')
self.assertIs(wm.category, SyntaxWarning)
with warnings.catch_warnings(record=True) as wlog:
warnings.simplefilter('error')
warnings.filterwarnings('always', module=r'<string>\z')
exec(source, {'__name__': 'package.module', '__file__': filename})
self.assertEqual(sorted(wm.lineno for wm in wlog), [4, 7, 10, 13, 14, 21])
for wm in wlog:
self.assertEqual(wm.filename, '<string>')
self.assertIs(wm.category, SyntaxWarning)
def test_filter(self): def test_filter(self):
self.assertEqual(list(filter(lambda c: 'a' <= c <= 'z', 'Hello World')), list('elloorld')) self.assertEqual(list(filter(lambda c: 'a' <= c <= 'z', 'Hello World')), list('elloorld'))

View file

@ -810,6 +810,19 @@ def test_script_as_dev_fd(self):
out, err = p.communicate() out, err = p.communicate()
self.assertEqual(out, b"12345678912345678912345\n") self.assertEqual(out, b"12345678912345678912345\n")
def test_filter_syntax_warnings_by_module(self):
filename = support.findfile('test_import/data/syntax_warnings.py')
rc, out, err = assert_python_ok(
'-Werror',
'-Walways:::test.test_import.data.syntax_warnings',
filename)
self.assertEqual(err.count(b': SyntaxWarning: '), 6)
rc, out, err = assert_python_ok(
'-Werror',
'-Walways:::syntax_warnings',
filename)
self.assertEqual(err.count(b': SyntaxWarning: '), 6)
def tearDownModule(): def tearDownModule():

View file

@ -1745,6 +1745,20 @@ def test_compile_warning_in_finally(self):
self.assertEqual(wm.category, SyntaxWarning) self.assertEqual(wm.category, SyntaxWarning)
self.assertIn("\"is\" with 'int' literal", str(wm.message)) self.assertIn("\"is\" with 'int' literal", str(wm.message))
def test_filter_syntax_warnings_by_module(self):
filename = support.findfile('test_import/data/syntax_warnings.py')
with open(filename, 'rb') as f:
source = f.read()
module_re = r'test\.test_import\.data\.syntax_warnings\z'
with warnings.catch_warnings(record=True) as wlog:
warnings.simplefilter('error')
warnings.filterwarnings('always', module=module_re)
compile(source, filename, 'exec')
self.assertEqual(sorted(wm.lineno for wm in wlog), [4, 7, 10, 13, 14, 21])
for wm in wlog:
self.assertEqual(wm.filename, filename)
self.assertIs(wm.category, SyntaxWarning)
@support.subTests('src', [ @support.subTests('src', [
textwrap.dedent(""" textwrap.dedent("""
def f(): def f():

View file

@ -15,6 +15,7 @@
import os import os
import py_compile import py_compile
import random import random
import re
import shutil import shutil
import stat import stat
import subprocess import subprocess
@ -23,6 +24,7 @@
import threading import threading
import time import time
import types import types
import warnings
import unittest import unittest
from unittest import mock from unittest import mock
import _imp import _imp
@ -51,7 +53,7 @@
TESTFN, rmtree, temp_umask, TESTFN_UNENCODABLE) TESTFN, rmtree, temp_umask, TESTFN_UNENCODABLE)
from test.support import script_helper from test.support import script_helper
from test.support import threading_helper from test.support import threading_helper
from test.test_importlib.util import uncache from test.test_importlib.util import uncache, temporary_pycache_prefix
from types import ModuleType from types import ModuleType
try: try:
import _testsinglephase import _testsinglephase
@ -412,7 +414,6 @@ def test_from_import_missing_attr_path_is_canonical(self):
self.assertIsNotNone(cm.exception) self.assertIsNotNone(cm.exception)
def test_from_import_star_invalid_type(self): def test_from_import_star_invalid_type(self):
import re
with ready_to_import() as (name, path): with ready_to_import() as (name, path):
with open(path, 'w', encoding='utf-8') as f: with open(path, 'w', encoding='utf-8') as f:
f.write("__all__ = [b'invalid_type']") f.write("__all__ = [b'invalid_type']")
@ -1250,6 +1251,35 @@ class Spec2:
origin = "a\x00b" origin = "a\x00b"
_imp.create_dynamic(Spec2()) _imp.create_dynamic(Spec2())
def test_filter_syntax_warnings_by_module(self):
module_re = r'test\.test_import\.data\.syntax_warnings\z'
unload('test.test_import.data.syntax_warnings')
with (os_helper.temp_dir() as tmpdir,
temporary_pycache_prefix(tmpdir),
warnings.catch_warnings(record=True) as wlog):
warnings.simplefilter('error')
warnings.filterwarnings('always', module=module_re)
import test.test_import.data.syntax_warnings
self.assertEqual(sorted(wm.lineno for wm in wlog), [4, 7, 10, 13, 14, 21])
filename = test.test_import.data.syntax_warnings.__file__
for wm in wlog:
self.assertEqual(wm.filename, filename)
self.assertIs(wm.category, SyntaxWarning)
module_re = r'syntax_warnings\z'
unload('test.test_import.data.syntax_warnings')
with (os_helper.temp_dir() as tmpdir,
temporary_pycache_prefix(tmpdir),
warnings.catch_warnings(record=True) as wlog):
warnings.simplefilter('error')
warnings.filterwarnings('always', module=module_re)
import test.test_import.data.syntax_warnings
self.assertEqual(sorted(wm.lineno for wm in wlog), [4, 7, 10, 13, 14, 21])
filename = test.test_import.data.syntax_warnings.__file__
for wm in wlog:
self.assertEqual(wm.filename, filename)
self.assertIs(wm.category, SyntaxWarning)
@skip_if_dont_write_bytecode @skip_if_dont_write_bytecode
class FilePermissionTests(unittest.TestCase): class FilePermissionTests(unittest.TestCase):

View file

@ -0,0 +1,21 @@
# Syntax warnings emitted in different parts of the Python compiler.
# Parser/lexer/lexer.c
x = 1or 0 # line 4
# Parser/tokenizer/helpers.c
'\z' # line 7
# Parser/string_parser.c
'\400' # line 10
# _PyCompile_Warn() in Python/codegen.c
assert(x, 'message') # line 13
x is 1 # line 14
# _PyErr_EmitSyntaxWarning() in Python/ast_preprocess.c
def f():
try:
pass
finally:
return 42 # line 21

View file

@ -5,6 +5,7 @@
import re import re
import textwrap import textwrap
import symtable import symtable
import warnings
import unittest import unittest
from test import support from test import support
@ -586,6 +587,20 @@ def test__symtable_refleak(self):
# check error path when 'compile_type' AC conversion failed # check error path when 'compile_type' AC conversion failed
self.assertRaises(TypeError, symtable.symtable, '', mortal_str, 1) self.assertRaises(TypeError, symtable.symtable, '', mortal_str, 1)
def test_filter_syntax_warnings_by_module(self):
filename = support.findfile('test_import/data/syntax_warnings.py')
with open(filename, 'rb') as f:
source = f.read()
module_re = r'test\.test_import\.data\.syntax_warnings\z'
with warnings.catch_warnings(record=True) as wlog:
warnings.simplefilter('error')
warnings.filterwarnings('always', module=module_re)
symtable.symtable(source, filename, 'exec')
self.assertEqual(sorted(wm.lineno for wm in wlog), [4, 7, 10])
for wm in wlog:
self.assertEqual(wm.filename, filename)
self.assertIs(wm.category, SyntaxWarning)
class ComprehensionTests(unittest.TestCase): class ComprehensionTests(unittest.TestCase):
def get_identifiers_recursive(self, st, res): def get_identifiers_recursive(self, st, res):

View file

@ -249,10 +249,23 @@ def test_filter_module(self):
self.module.warn_explicit('msg', UserWarning, 'filename', 42, self.module.warn_explicit('msg', UserWarning, 'filename', 42,
module='package.module') module='package.module')
self.assertEqual(len(w), 1) self.assertEqual(len(w), 1)
self.module.warn_explicit('msg', UserWarning, '/path/to/package/module', 42)
self.assertEqual(len(w), 2)
self.module.warn_explicit('msg', UserWarning, '/path/to/package/module.py', 42)
self.assertEqual(len(w), 3)
self.module.warn_explicit('msg', UserWarning, '/path/to/package/module/__init__.py', 42)
self.assertEqual(len(w), 4)
with self.assertRaises(UserWarning): with self.assertRaises(UserWarning):
self.module.warn_explicit('msg', UserWarning, '/path/to/package/module', 42) self.module.warn_explicit('msg', UserWarning, '/path/to/package/module/__init__', 42)
with self.assertRaises(UserWarning): if MS_WINDOWS:
self.module.warn_explicit('msg', UserWarning, '/path/to/package/module.py', 42) self.module.warn_explicit('msg', UserWarning, r'C:\path\to\package\module.PY', 42)
self.assertEqual(len(w), 5)
self.module.warn_explicit('msg', UserWarning, r'C:\path\to\package\module\__INIT__.PY', 42)
self.assertEqual(len(w), 6)
self.module.warn_explicit('msg', UserWarning, r'C:\path\to\package\module.PYW', 42)
self.assertEqual(len(w), 7)
self.module.warn_explicit('msg', UserWarning, r'C:\path\to\package\module\__INIT__.PYW', 42)
self.assertEqual(len(w), 8)
with self.module.catch_warnings(record=True) as w: with self.module.catch_warnings(record=True) as w:
self.module.simplefilter('error') self.module.simplefilter('error')
@ -276,9 +289,8 @@ def test_filter_module(self):
with self.assertRaises(UserWarning): with self.assertRaises(UserWarning):
self.module.warn_explicit('msg', UserWarning, '/PATH/TO/PACKAGE/MODULE', 42) self.module.warn_explicit('msg', UserWarning, '/PATH/TO/PACKAGE/MODULE', 42)
if MS_WINDOWS: if MS_WINDOWS:
if self.module is py_warnings: self.module.warn_explicit('msg', UserWarning, r'/path/to/package/module.PY', 42)
self.module.warn_explicit('msg', UserWarning, r'/path/to/package/module.PY', 42) self.assertEqual(len(w), 3)
self.assertEqual(len(w), 3)
with self.assertRaises(UserWarning): with self.assertRaises(UserWarning):
self.module.warn_explicit('msg', UserWarning, r'/path/to/package/module/__init__.py', 42) self.module.warn_explicit('msg', UserWarning, r'/path/to/package/module/__init__.py', 42)
with self.assertRaises(UserWarning): with self.assertRaises(UserWarning):
@ -302,9 +314,8 @@ def test_filter_module(self):
self.assertEqual(len(w), 1) self.assertEqual(len(w), 1)
self.module.warn_explicit('msg', UserWarning, r'C:\path\to\package\module.py', 42) self.module.warn_explicit('msg', UserWarning, r'C:\path\to\package\module.py', 42)
self.assertEqual(len(w), 2) self.assertEqual(len(w), 2)
if self.module is py_warnings: self.module.warn_explicit('msg', UserWarning, r'C:\path\to\package\module.PY', 42)
self.module.warn_explicit('msg', UserWarning, r'C:\path\to\package\module.PY', 42) self.assertEqual(len(w), 3)
self.assertEqual(len(w), 3)
with self.assertRaises(UserWarning): with self.assertRaises(UserWarning):
self.module.warn_explicit('msg', UserWarning, r'C:\path\to\package\module.pyw', 42) self.module.warn_explicit('msg', UserWarning, r'C:\path\to\package\module.pyw', 42)
with self.assertRaises(UserWarning): with self.assertRaises(UserWarning):
@ -399,7 +410,7 @@ def test_message_matching(self):
def test_mutate_filter_list(self): def test_mutate_filter_list(self):
class X: class X:
def match(self, a): def match(self, a, start=0):
L[:] = [] L[:] = []
L = [("default",X(),UserWarning,X(),0) for i in range(2)] L = [("default",X(),UserWarning,X(),0) for i in range(2)]

View file

@ -0,0 +1,6 @@
Improve filtering by module in :func:`warnings.warn_explicit` if no *module*
argument is passed. It now tests the module regular expression in the
warnings filter not only against the filename with ``.py`` stripped, but
also against module names constructed starting from different parent
directories of the filename (with ``/__init__.py``, ``.py`` and, on Windows,
``.pyw`` stripped).

View file

@ -171,7 +171,7 @@ _PyWarnings_InitState(PyInterpreterState *interp)
/*************************************************************************/ /*************************************************************************/
static int static int
check_matched(PyInterpreterState *interp, PyObject *obj, PyObject *arg) check_matched(PyInterpreterState *interp, PyObject *obj, PyObject *arg, PyObject *arg2)
{ {
PyObject *result; PyObject *result;
int rc; int rc;
@ -182,6 +182,9 @@ check_matched(PyInterpreterState *interp, PyObject *obj, PyObject *arg)
/* An internal plain text default filter must match exactly */ /* An internal plain text default filter must match exactly */
if (PyUnicode_CheckExact(obj)) { if (PyUnicode_CheckExact(obj)) {
if (arg == NULL) {
return 0;
}
int cmp_result = PyUnicode_Compare(obj, arg); int cmp_result = PyUnicode_Compare(obj, arg);
if (cmp_result == -1 && PyErr_Occurred()) { if (cmp_result == -1 && PyErr_Occurred()) {
return -1; return -1;
@ -190,10 +193,19 @@ check_matched(PyInterpreterState *interp, PyObject *obj, PyObject *arg)
} }
/* Otherwise assume a regex filter and call its match() method */ /* Otherwise assume a regex filter and call its match() method */
result = PyObject_CallMethodOneArg(obj, &_Py_ID(match), arg); if (arg != NULL) {
result = PyObject_CallMethodOneArg(obj, &_Py_ID(match), arg);
}
else {
PyObject *match = PyImport_ImportModuleAttrString("_py_warnings", "_match_filename");
if (match == NULL) {
return -1;
}
result = PyObject_CallFunctionObjArgs(match, obj, arg2, NULL);
Py_DECREF(match);
}
if (result == NULL) if (result == NULL)
return -1; return -1;
rc = PyObject_IsTrue(result); rc = PyObject_IsTrue(result);
Py_DECREF(result); Py_DECREF(result);
return rc; return rc;
@ -423,7 +435,7 @@ get_default_action(PyInterpreterState *interp)
static bool static bool
filter_search(PyInterpreterState *interp, PyObject *category, filter_search(PyInterpreterState *interp, PyObject *category,
PyObject *text, Py_ssize_t lineno, PyObject *text, Py_ssize_t lineno,
PyObject *module, char *list_name, PyObject *filters, PyObject *module, PyObject *filename, char *list_name, PyObject *filters,
PyObject **item, PyObject **matched_action) { PyObject **item, PyObject **matched_action) {
bool result = true; bool result = true;
*matched_action = NULL; *matched_action = NULL;
@ -459,14 +471,14 @@ filter_search(PyInterpreterState *interp, PyObject *category,
break; break;
} }
good_msg = check_matched(interp, msg, text); good_msg = check_matched(interp, msg, text, NULL);
if (good_msg == -1) { if (good_msg == -1) {
Py_DECREF(tmp_item); Py_DECREF(tmp_item);
result = false; result = false;
break; break;
} }
good_mod = check_matched(interp, mod, module); good_mod = check_matched(interp, mod, module, filename);
if (good_mod == -1) { if (good_mod == -1) {
Py_DECREF(tmp_item); Py_DECREF(tmp_item);
result = false; result = false;
@ -504,7 +516,7 @@ filter_search(PyInterpreterState *interp, PyObject *category,
static PyObject* static PyObject*
get_filter(PyInterpreterState *interp, PyObject *category, get_filter(PyInterpreterState *interp, PyObject *category,
PyObject *text, Py_ssize_t lineno, PyObject *text, Py_ssize_t lineno,
PyObject *module, PyObject **item) PyObject *module, PyObject *filename, PyObject **item)
{ {
#ifdef Py_DEBUG #ifdef Py_DEBUG
WarningsState *st = warnings_get_state(interp); WarningsState *st = warnings_get_state(interp);
@ -522,7 +534,7 @@ get_filter(PyInterpreterState *interp, PyObject *category,
use_global_filters = true; use_global_filters = true;
} else { } else {
PyObject *context_action = NULL; PyObject *context_action = NULL;
if (!filter_search(interp, category, text, lineno, module, "_warnings_context _filters", if (!filter_search(interp, category, text, lineno, module, filename, "_warnings_context _filters",
context_filters, item, &context_action)) { context_filters, item, &context_action)) {
Py_DECREF(context_filters); Py_DECREF(context_filters);
return NULL; return NULL;
@ -541,7 +553,7 @@ get_filter(PyInterpreterState *interp, PyObject *category,
if (filters == NULL) { if (filters == NULL) {
return NULL; return NULL;
} }
if (!filter_search(interp, category, text, lineno, module, "filters", if (!filter_search(interp, category, text, lineno, module, filename, "filters",
filters, item, &action)) { filters, item, &action)) {
return NULL; return NULL;
} }
@ -612,39 +624,6 @@ already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key,
return 0; return 0;
} }
/* New reference. */
static PyObject *
normalize_module(PyObject *filename)
{
PyObject *module;
int kind;
const void *data;
Py_ssize_t len;
len = PyUnicode_GetLength(filename);
if (len < 0)
return NULL;
if (len == 0)
return PyUnicode_FromString("<unknown>");
kind = PyUnicode_KIND(filename);
data = PyUnicode_DATA(filename);
/* if filename.endswith(".py"): */
if (len >= 3 &&
PyUnicode_READ(kind, data, len-3) == '.' &&
PyUnicode_READ(kind, data, len-2) == 'p' &&
PyUnicode_READ(kind, data, len-1) == 'y')
{
module = PyUnicode_Substring(filename, 0, len-3);
}
else {
module = Py_NewRef(filename);
}
return module;
}
static int static int
update_registry(PyInterpreterState *interp, PyObject *registry, PyObject *text, update_registry(PyInterpreterState *interp, PyObject *registry, PyObject *text,
PyObject *category, int add_zero) PyObject *category, int add_zero)
@ -812,15 +791,6 @@ warn_explicit(PyThreadState *tstate, PyObject *category, PyObject *message,
return NULL; return NULL;
} }
/* Normalize module. */
if (module == NULL) {
module = normalize_module(filename);
if (module == NULL)
return NULL;
}
else
Py_INCREF(module);
/* Normalize message. */ /* Normalize message. */
Py_INCREF(message); /* DECREF'ed in cleanup. */ Py_INCREF(message); /* DECREF'ed in cleanup. */
if (PyObject_TypeCheck(message, (PyTypeObject *)PyExc_Warning)) { if (PyObject_TypeCheck(message, (PyTypeObject *)PyExc_Warning)) {
@ -858,7 +828,7 @@ warn_explicit(PyThreadState *tstate, PyObject *category, PyObject *message,
/* Else this warning hasn't been generated before. */ /* Else this warning hasn't been generated before. */
} }
action = get_filter(interp, category, text, lineno, module, &item); action = get_filter(interp, category, text, lineno, module, filename, &item);
if (action == NULL) if (action == NULL)
goto cleanup; goto cleanup;
@ -921,7 +891,6 @@ warn_explicit(PyThreadState *tstate, PyObject *category, PyObject *message,
Py_XDECREF(key); Py_XDECREF(key);
Py_XDECREF(text); Py_XDECREF(text);
Py_XDECREF(lineno_obj); Py_XDECREF(lineno_obj);
Py_DECREF(module);
Py_XDECREF(message); Py_XDECREF(message);
return result; /* Py_None or NULL. */ return result; /* Py_None or NULL. */
} }