Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 843aadd

Browse filesBrowse files
authored
Merge pull request #28714 from QuLogic/py312-warning
Simplify _api.warn_external on Python 3.12+
2 parents 1b6bc17 + 9283ce5 commit 843aadd
Copy full SHA for 843aadd

File tree

Expand file treeCollapse file tree

2 files changed

+41
-20
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+41
-20
lines changed

‎lib/matplotlib/_api/__init__.py

Copy file name to clipboardExpand all lines: lib/matplotlib/_api/__init__.py
+23-13Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import functools
1414
import itertools
15+
import pathlib
1516
import re
1617
import sys
1718
import warnings
@@ -366,16 +367,25 @@ def warn_external(message, category=None):
366367
warnings.warn`` (or ``functools.partial(warnings.warn, stacklevel=2)``,
367368
etc.).
368369
"""
369-
frame = sys._getframe()
370-
for stacklevel in itertools.count(1):
371-
if frame is None:
372-
# when called in embedded context may hit frame is None
373-
break
374-
if not re.match(r"\A(matplotlib|mpl_toolkits)(\Z|\.(?!tests\.))",
375-
# Work around sphinx-gallery not setting __name__.
376-
frame.f_globals.get("__name__", "")):
377-
break
378-
frame = frame.f_back
379-
# preemptively break reference cycle between locals and the frame
380-
del frame
381-
warnings.warn(message, category, stacklevel)
370+
kwargs = {}
371+
if sys.version_info[:2] >= (3, 12):
372+
# Go to Python's `site-packages` or `lib` from an editable install.
373+
basedir = pathlib.Path(__file__).parents[2]
374+
kwargs['skip_file_prefixes'] = (str(basedir / 'matplotlib'),
375+
str(basedir / 'mpl_toolkits'))
376+
else:
377+
frame = sys._getframe()
378+
for stacklevel in itertools.count(1):
379+
if frame is None:
380+
# when called in embedded context may hit frame is None
381+
kwargs['stacklevel'] = stacklevel
382+
break
383+
if not re.match(r"\A(matplotlib|mpl_toolkits)(\Z|\.(?!tests\.))",
384+
# Work around sphinx-gallery not setting __name__.
385+
frame.f_globals.get("__name__", "")):
386+
kwargs['stacklevel'] = stacklevel
387+
break
388+
frame = frame.f_back
389+
# preemptively break reference cycle between locals and the frame
390+
del frame
391+
warnings.warn(message, category, **kwargs)

‎lib/matplotlib/tests/test_cbook.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_cbook.py
+18-7Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from __future__ import annotations
22

3-
import sys
43
import itertools
4+
import pathlib
55
import pickle
6+
import sys
67

78
from typing import Any
89
from unittest.mock import patch, Mock
@@ -478,6 +479,22 @@ def test_normalize_kwargs_pass(inp, expected, kwargs_to_norm):
478479
assert expected == cbook.normalize_kwargs(inp, **kwargs_to_norm)
479480

480481

482+
def test_warn_external(recwarn):
483+
_api.warn_external("oops")
484+
assert len(recwarn) == 1
485+
if sys.version_info[:2] >= (3, 12):
486+
# With Python 3.12, we let Python figure out the stacklevel using the
487+
# `skip_file_prefixes` argument, which cannot exempt tests, so just confirm
488+
# the filename is not in the package.
489+
basedir = pathlib.Path(__file__).parents[2]
490+
assert not recwarn[0].filename.startswith((str(basedir / 'matplotlib'),
491+
str(basedir / 'mpl_toolkits')))
492+
else:
493+
# On older Python versions, we manually calculated the stacklevel, and had an
494+
# exception for our own tests.
495+
assert recwarn[0].filename == __file__
496+
497+
481498
def test_warn_external_frame_embedded_python():
482499
with patch.object(cbook, "sys") as mock_sys:
483500
mock_sys._getframe = Mock(return_value=None)
@@ -784,12 +801,6 @@ def test_safe_first_element_pandas_series(pd):
784801
assert actual == 0
785802

786803

787-
def test_warn_external(recwarn):
788-
_api.warn_external("oops")
789-
assert len(recwarn) == 1
790-
assert recwarn[0].filename == __file__
791-
792-
793804
def test_array_patch_perimeters():
794805
# This compares the old implementation as a reference for the
795806
# vectorized one.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.