Skip to content

Commit 9fa9bd1

Browse files
committed
Remove 3.8 deprecations in backends
1 parent da2f549 commit 9fa9bd1

File tree

14 files changed

+88
-214
lines changed

14 files changed

+88
-214
lines changed

doc/api/next_api_changes/removals/28874-ES.rst

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,66 @@
1+
Auto-closing of figures when switching backend
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
Allowable backend switches (i.e. those that do not swap a GUI event loop with another
5+
one) will not close existing figures. If necessary, call ``plt.close("all")`` before
6+
switching.
7+
8+
9+
``FigureCanvasBase.switch_backends``
10+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11+
12+
... has been removed with no replacement.
13+
14+
15+
Accessing ``event.guiEvent`` after event handlers return
16+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17+
18+
... is no longer supported, and ``event.guiEvent`` will be set to None once the event
19+
handlers return. For some GUI toolkits, it is unsafe to use the event, though you may
20+
separately stash the object at your own risk.
21+
22+
23+
``PdfPages(keep_empty=True)``
24+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25+
26+
A zero-page PDF is not valid, thus passing ``keep_empty=True`` to `.backend_pdf.PdfPages`
27+
and `.backend_pgf.PdfPages`, and the ``keep_empty`` attribute of these classes, is no
28+
longer allowed, and empty PDF files will not be created.
29+
30+
Furthermore, `.backend_pdf.PdfPages` no longer immediately creates the target file upon
31+
instantiation, but only when the first figure is saved. To fully control file creation,
32+
directly pass an opened file object as argument (``with open(path, "wb") as file,
33+
PdfPages(file) as pdf: ...``).
34+
35+
36+
``backend_ps.psDefs``
37+
~~~~~~~~~~~~~~~~~~~~~
38+
39+
The ``psDefs`` module-level variable in ``backend_ps`` has been removed with no
40+
replacement.
41+
42+
43+
Automatic papersize selection in PostScript
44+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45+
46+
Setting :rc:`ps.papersize` to ``'auto'`` or passing ``papersize='auto'`` to
47+
`.Figure.savefig` is no longer supported. Either pass an explicit paper type name, or
48+
omit this parameter to use the default from the rcParam.
49+
50+
51+
``RendererAgg.tostring_rgb`` and ``FigureCanvasAgg.tostring_rgb``
52+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53+
54+
... have been remove with no direct replacement. Consider using ``buffer_rgba`` instead,
55+
which should cover most use cases.
56+
57+
58+
``NavigationToolbar2QT.message`` has been removed
59+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
60+
61+
... with no replacement.
62+
63+
164
``axes_grid1`` API changes
265
~~~~~~~~~~~~~~~~~~~~~~~~~~
366

lib/matplotlib/backend_bases.py

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,26 +1178,12 @@ class Event:
11781178
def __init__(self, name, canvas, guiEvent=None):
11791179
self.name = name
11801180
self.canvas = canvas
1181-
self._guiEvent = guiEvent
1182-
self._guiEvent_deleted = False
1181+
self.guiEvent = guiEvent
11831182

11841183
def _process(self):
11851184
"""Process this event on ``self.canvas``, then unset ``guiEvent``."""
11861185
self.canvas.callbacks.process(self.name, self)
1187-
self._guiEvent_deleted = True
1188-
1189-
@property
1190-
def guiEvent(self):
1191-
# After deprecation elapses: remove _guiEvent_deleted; make guiEvent a plain
1192-
# attribute set to None by _process.
1193-
if self._guiEvent_deleted:
1194-
_api.warn_deprecated(
1195-
"3.8", message="Accessing guiEvent outside of the original GUI event "
1196-
"handler is unsafe and deprecated since %(since)s; in the future, the "
1197-
"attribute will be set to None after quitting the event handler. You "
1198-
"may separately record the value of the guiEvent attribute at your own "
1199-
"risk.")
1200-
return self._guiEvent
1186+
self.guiEvent = None
12011187

12021188

12031189
class DrawEvent(Event):
@@ -2097,12 +2083,6 @@ def print_figure(
20972083
if dpi == 'figure':
20982084
dpi = getattr(self.figure, '_original_dpi', self.figure.dpi)
20992085

2100-
if kwargs.get("papertype") == 'auto':
2101-
# When deprecation elapses, remove backend_ps._get_papertype & its callers.
2102-
_api.warn_deprecated(
2103-
"3.8", name="papertype='auto'", addendum="Pass an explicit paper type, "
2104-
"'figure', or omit the *papertype* argument entirely.")
2105-
21062086
# Remove the figure manager, if any, to avoid resizing the GUI widget.
21072087
with (cbook._setattr_cm(self, manager=None),
21082088
self._switch_canvas_and_return_print_method(format, backend)
@@ -2207,20 +2187,6 @@ def get_default_filename(self):
22072187
default_filetype = self.get_default_filetype()
22082188
return f'{default_basename}.{default_filetype}'
22092189

2210-
@_api.deprecated("3.8")
2211-
def switch_backends(self, FigureCanvasClass):
2212-
"""
2213-
Instantiate an instance of FigureCanvasClass
2214-
2215-
This is used for backend switching, e.g., to instantiate a
2216-
FigureCanvasPS from a FigureCanvasGTK. Note, deep copying is
2217-
not done, so any changes to one of the instances (e.g., setting
2218-
figure size or line props), will be reflected in the other
2219-
"""
2220-
newCanvas = FigureCanvasClass(self.figure)
2221-
newCanvas._is_saving = self._is_saving
2222-
return newCanvas
2223-
22242190
def mpl_connect(self, s, func):
22252191
"""
22262192
Bind function *func* to event *s*.

lib/matplotlib/backend_bases.pyi

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,13 +199,11 @@ class TimerBase:
199199
class Event:
200200
name: str
201201
canvas: FigureCanvasBase
202+
guiEvent: Any
202203
def __init__(
203204
self, name: str, canvas: FigureCanvasBase, guiEvent: Any | None = ...
204205
) -> None: ...
205206

206-
@property
207-
def guiEvent(self) -> Any: ...
208-
209207
class DrawEvent(Event):
210208
renderer: RendererBase
211209
def __init__(
@@ -348,7 +346,6 @@ class FigureCanvasBase:
348346
def get_default_filetype(cls) -> str: ...
349347
def get_default_filename(self) -> str: ...
350348
_T = TypeVar("_T", bound=FigureCanvasBase)
351-
def switch_backends(self, FigureCanvasClass: type[_T]) -> _T: ...
352349
def mpl_connect(self, s: str, func: Callable[[Event], Any]) -> int: ...
353350
def mpl_disconnect(self, cid: int) -> None: ...
354351
def new_timer(

lib/matplotlib/backends/backend_agg.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,6 @@ def buffer_rgba(self):
266266
def tostring_argb(self):
267267
return np.asarray(self._renderer).take([3, 0, 1, 2], axis=2).tobytes()
268268

269-
@_api.deprecated("3.8", alternative="buffer_rgba")
270-
def tostring_rgb(self):
271-
return np.asarray(self._renderer).take([0, 1, 2], axis=2).tobytes()
272-
273269
def clear(self):
274270
self._renderer.clear()
275271

@@ -398,16 +394,6 @@ def get_renderer(self):
398394
self._lastKey = key
399395
return self.renderer
400396

401-
@_api.deprecated("3.8", alternative="buffer_rgba")
402-
def tostring_rgb(self):
403-
"""
404-
Get the image as RGB `bytes`.
405-
406-
`draw` must be called at least once before this function will work and
407-
to update the renderer for any subsequent changes to the Figure.
408-
"""
409-
return self.renderer.tostring_rgb()
410-
411397
def tostring_argb(self):
412398
"""
413399
Get the image as ARGB `bytes`.

lib/matplotlib/backends/backend_pdf.py

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2663,9 +2663,9 @@ class PdfPages:
26632663
confusion when using `~.pyplot.savefig` and forgetting the format argument.
26642664
"""
26652665

2666-
_UNSET = object()
2667-
2668-
def __init__(self, filename, keep_empty=_UNSET, metadata=None):
2666+
@_api.delete_parameter("3.10", "keep_empty",
2667+
addendum="This parameter does nothing.")
2668+
def __init__(self, filename, keep_empty=None, metadata=None):
26692669
"""
26702670
Create a new PdfPages object.
26712671
@@ -2676,10 +2676,6 @@ def __init__(self, filename, keep_empty=_UNSET, metadata=None):
26762676
The file is opened when a figure is saved for the first time (overwriting
26772677
any older file with the same name).
26782678
2679-
keep_empty : bool, optional
2680-
If set to False, then empty pdf files will be deleted automatically
2681-
when closed.
2682-
26832679
metadata : dict, optional
26842680
Information dictionary object (see PDF reference section 10.2.1
26852681
'Document Information Dictionary'), e.g.:
@@ -2693,13 +2689,6 @@ def __init__(self, filename, keep_empty=_UNSET, metadata=None):
26932689
self._filename = filename
26942690
self._metadata = metadata
26952691
self._file = None
2696-
if keep_empty and keep_empty is not self._UNSET:
2697-
_api.warn_deprecated("3.8", message=(
2698-
"Keeping empty pdf files is deprecated since %(since)s and support "
2699-
"will be removed %(removal)s."))
2700-
self._keep_empty = keep_empty
2701-
2702-
keep_empty = _api.deprecate_privatize_attribute("3.8")
27032692

27042693
def __enter__(self):
27052694
return self
@@ -2721,11 +2710,6 @@ def close(self):
27212710
self._file.finalize()
27222711
self._file.close()
27232712
self._file = None
2724-
elif self._keep_empty: # True *or* UNSET.
2725-
_api.warn_deprecated("3.8", message=(
2726-
"Keeping empty pdf files is deprecated since %(since)s and support "
2727-
"will be removed %(removal)s."))
2728-
PdfFile(self._filename, metadata=self._metadata).close() # touch the file.
27292713

27302714
def infodict(self):
27312715
"""

lib/matplotlib/backends/backend_pgf.py

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from PIL import Image
1515

1616
import matplotlib as mpl
17-
from matplotlib import _api, cbook, font_manager as fm
17+
from matplotlib import cbook, font_manager as fm
1818
from matplotlib.backend_bases import (
1919
_Backend, FigureCanvasBase, FigureManagerBase, RendererBase
2020
)
@@ -898,9 +898,7 @@ class PdfPages:
898898
... pdf.savefig()
899899
"""
900900

901-
_UNSET = object()
902-
903-
def __init__(self, filename, *, keep_empty=_UNSET, metadata=None):
901+
def __init__(self, filename, *, metadata=None):
904902
"""
905903
Create a new PdfPages object.
906904
@@ -910,10 +908,6 @@ def __init__(self, filename, *, keep_empty=_UNSET, metadata=None):
910908
Plots using `PdfPages.savefig` will be written to a file at this
911909
location. Any older file with the same name is overwritten.
912910
913-
keep_empty : bool, default: True
914-
If set to False, then empty pdf files will be deleted automatically
915-
when closed.
916-
917911
metadata : dict, optional
918912
Information dictionary object (see PDF reference section 10.2.1
919913
'Document Information Dictionary'), e.g.:
@@ -929,17 +923,10 @@ def __init__(self, filename, *, keep_empty=_UNSET, metadata=None):
929923
"""
930924
self._output_name = filename
931925
self._n_figures = 0
932-
if keep_empty and keep_empty is not self._UNSET:
933-
_api.warn_deprecated("3.8", message=(
934-
"Keeping empty pdf files is deprecated since %(since)s and support "
935-
"will be removed %(removal)s."))
936-
self._keep_empty = keep_empty
937926
self._metadata = (metadata or {}).copy()
938927
self._info_dict = _create_pdf_info_dict('pgf', self._metadata)
939928
self._file = BytesIO()
940929

941-
keep_empty = _api.deprecate_privatize_attribute("3.8")
942-
943930
def _write_header(self, width_inches, height_inches):
944931
pdfinfo = ','.join(
945932
_metadata_to_str(k, v) for k, v in self._info_dict.items())
@@ -969,11 +956,6 @@ def close(self):
969956
self._file.write(rb'\end{document}\n')
970957
if self._n_figures > 0:
971958
self._run_latex()
972-
elif self._keep_empty:
973-
_api.warn_deprecated("3.8", message=(
974-
"Keeping empty pdf files is deprecated since %(since)s and support "
975-
"will be removed %(removal)s."))
976-
open(self._output_name, 'wb').close()
977959
self._file.close()
978960

979961
def _run_latex(self):

lib/matplotlib/backends/backend_ps.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,6 @@
3939
debugPS = False
4040

4141

42-
@_api.caching_module_getattr
43-
class __getattr__:
44-
# module-level deprecations
45-
psDefs = _api.deprecated("3.8", obj_type="")(property(lambda self: _psDefs))
46-
47-
4842
papersize = {'letter': (8.5, 11),
4943
'legal': (8.5, 14),
5044
'ledger': (11, 17),
@@ -72,15 +66,6 @@ class __getattr__:
7266
'b10': (1.26, 1.76)}
7367

7468

75-
def _get_papertype(w, h):
76-
for key, (pw, ph) in sorted(papersize.items(), reverse=True):
77-
if key.startswith('l'):
78-
continue
79-
if w < pw and h < ph:
80-
return key
81-
return 'a0'
82-
83-
8469
def _nums_to_str(*args, sep=" "):
8570
return sep.join(f"{arg:1.3f}".rstrip("0").rstrip(".") for arg in args)
8671

@@ -828,7 +813,7 @@ def _print_ps(
828813
if papertype is None:
829814
papertype = mpl.rcParams['ps.papersize']
830815
papertype = papertype.lower()
831-
_api.check_in_list(['figure', 'auto', *papersize], papertype=papertype)
816+
_api.check_in_list(['figure', *papersize], papertype=papertype)
832817

833818
orientation = _api.check_getitem(
834819
_Orientation, orientation=orientation.lower())
@@ -858,9 +843,6 @@ def _print_figure(
858843

859844
# find the appropriate papertype
860845
width, height = self.figure.get_size_inches()
861-
if papertype == 'auto':
862-
papertype = _get_papertype(*orientation.swap_if_landscape((width, height)))
863-
864846
if is_eps or papertype == 'figure':
865847
paper_width, paper_height = width, height
866848
else:
@@ -1041,8 +1023,6 @@ def _print_figure_tex(
10411023
paper_width, paper_height = orientation.swap_if_landscape(
10421024
self.figure.get_size_inches())
10431025
else:
1044-
if papertype == 'auto':
1045-
papertype = _get_papertype(width, height)
10461026
paper_width, paper_height = papersize[papertype]
10471027

10481028
psfrag_rotated = _convert_psfrags(

lib/matplotlib/backends/backend_qt.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -658,9 +658,6 @@ def set_window_title(self, title):
658658

659659

660660
class NavigationToolbar2QT(NavigationToolbar2, QtWidgets.QToolBar):
661-
_message = QtCore.Signal(str) # Remove once deprecation below elapses.
662-
message = _api.deprecate_privatize_attribute("3.8")
663-
664661
toolitems = [*NavigationToolbar2.toolitems]
665662
toolitems.insert(
666663
# Add 'customize' action after 'subplots'
@@ -783,7 +780,6 @@ def zoom(self, *args):
783780
self._update_buttons_checked()
784781

785782
def set_message(self, s):
786-
self._message.emit(s)
787783
if self.coordinates:
788784
self.locLabel.setText(s)
789785

lib/matplotlib/pyplot.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -514,14 +514,6 @@ def draw_if_interactive() -> None:
514514
# See https://github.com/matplotlib/matplotlib/issues/6092
515515
matplotlib.backends.backend = newbackend # type: ignore[attr-defined]
516516

517-
if not cbook._str_equal(old_backend, newbackend):
518-
if get_fignums():
519-
_api.warn_deprecated("3.8", message=(
520-
"Auto-close()ing of figures upon backend switching is deprecated since "
521-
"%(since)s and will be removed %(removal)s. To suppress this warning, "
522-
"explicitly call plt.close('all') first."))
523-
close("all")
524-
525517
# Make sure the repl display hook is installed in case we become interactive.
526518
install_repl_displayhook()
527519

0 commit comments

Comments
 (0)