Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit73b5101

Browse files
authored
Merge pull request#18408 from tacaswell/fix_pgf_draw
FIX/API: `fig.canvas.draw` always updates internal state
2 parentsc152045 +22e84f6 commit73b5101

File tree

9 files changed

+123
-35
lines changed

9 files changed

+123
-35
lines changed

‎lib/matplotlib/backend_bases.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,12 @@ def _draw(renderer): raise Done(renderer)
15841584
figure.canvas=orig_canvas
15851585

15861586

1587+
def_no_output_draw(figure):
1588+
renderer=_get_renderer(figure)
1589+
withrenderer._draw_disabled():
1590+
figure.draw(renderer)
1591+
1592+
15871593
def_is_non_interactive_terminal_ipython(ip):
15881594
"""
15891595
Return whether we are in a a terminal IPython, but non interactive.
@@ -1621,7 +1627,9 @@ def _check_savefig_extra_args(func=None, extra_kwargs=()):
16211627
@functools.wraps(func)
16221628
defwrapper(*args,**kwargs):
16231629
name='savefig'# Reasonable default guess.
1624-
public_api=re.compile(r'^savefig|print_[A-Za-z0-9]+$')
1630+
public_api=re.compile(
1631+
r'^savefig|print_[A-Za-z0-9]+|_no_output_draw$'
1632+
)
16251633
seen_print_figure=False
16261634
forframe,lineintraceback.walk_stack(None):
16271635
ifframeisNone:
@@ -1632,8 +1640,9 @@ def wrapper(*args, **kwargs):
16321640
frame.f_globals.get('__name__','')):
16331641
ifpublic_api.match(frame.f_code.co_name):
16341642
name=frame.f_code.co_name
1635-
ifname=='print_figure':
1643+
ifnamein ('print_figure','_no_output_draw'):
16361644
seen_print_figure=True
1645+
16371646
else:
16381647
break
16391648

@@ -2021,7 +2030,14 @@ def release_mouse(self, ax):
20212030
self.mouse_grabber=None
20222031

20232032
defdraw(self,*args,**kwargs):
2024-
"""Render the `.Figure`."""
2033+
"""
2034+
Render the `.Figure`.
2035+
2036+
It is important that this method actually walk the artist tree
2037+
even if not output is produced because this will trigger
2038+
deferred work (like computing limits auto-limits and tick
2039+
values) that users may want access to before saving to disk.
2040+
"""
20252041

20262042
defdraw_idle(self,*args,**kwargs):
20272043
"""

‎lib/matplotlib/backends/backend_pdf.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
frommatplotlib._pylab_helpersimportGcf
2929
frommatplotlib.backend_basesimport (
3030
_Backend,_check_savefig_extra_args,FigureCanvasBase,FigureManagerBase,
31-
GraphicsContextBase,RendererBase)
31+
GraphicsContextBase,RendererBase,_no_output_draw)
3232
frommatplotlib.backends.backend_mixedimportMixedModeRenderer
3333
frommatplotlib.figureimportFigure
3434
frommatplotlib.font_managerimportfindfont,get_font
@@ -2730,6 +2730,10 @@ def print_pdf(self, filename, *,
27302730
else:# we opened the file above; now finish it off
27312731
file.close()
27322732

2733+
defdraw(self):
2734+
_no_output_draw(self.figure)
2735+
returnsuper().draw()
2736+
27332737

27342738
FigureManagerPdf=FigureManagerBase
27352739

‎lib/matplotlib/backends/backend_pgf.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
frommatplotlibimport_api,cbook,font_managerasfm
2020
frommatplotlib.backend_basesimport (
2121
_Backend,_check_savefig_extra_args,FigureCanvasBase,FigureManagerBase,
22-
GraphicsContextBase,RendererBase)
22+
GraphicsContextBase,RendererBase,_no_output_draw
23+
)
2324
frommatplotlib.backends.backend_mixedimportMixedModeRenderer
2425
frommatplotlib.backends.backend_pdfimport (
2526
_create_pdf_info_dict,_datetime_to_pdf)
@@ -906,6 +907,10 @@ def print_png(self, fname_or_fh, *args, **kwargs):
906907
defget_renderer(self):
907908
returnRendererPgf(self.figure,None)
908909

910+
defdraw(self):
911+
_no_output_draw(self.figure)
912+
returnsuper().draw()
913+
909914

910915
FigureManagerPgf=FigureManagerBase
911916

‎lib/matplotlib/backends/backend_ps.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
frommatplotlib.afmimportAFM
2424
frommatplotlib.backend_basesimport (
2525
_Backend,_check_savefig_extra_args,FigureCanvasBase,FigureManagerBase,
26-
GraphicsContextBase,RendererBase)
26+
GraphicsContextBase,RendererBase,_no_output_draw)
2727
frommatplotlib.cbookimportis_writable_file_like,file_requires_unicode
2828
frommatplotlib.font_managerimportget_font
2929
frommatplotlib.ft2fontimportLOAD_NO_HINTING,LOAD_NO_SCALE
@@ -1129,6 +1129,10 @@ def _print_figure_tex(
11291129

11301130
_move_path_to_path_or_stream(tmpfile,outfile)
11311131

1132+
defdraw(self):
1133+
_no_output_draw(self.figure)
1134+
returnsuper().draw()
1135+
11321136

11331137
defconvert_psfrags(tmpfile,psfrags,font_preamble,custom_preamble,
11341138
paper_width,paper_height,orientation):

‎lib/matplotlib/backends/backend_svg.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
frommatplotlibimport_api,cbook
1818
frommatplotlib.backend_basesimport (
1919
_Backend,_check_savefig_extra_args,FigureCanvasBase,FigureManagerBase,
20-
RendererBase)
20+
RendererBase,_no_output_draw)
2121
frommatplotlib.backends.backend_mixedimportMixedModeRenderer
2222
frommatplotlib.colorsimportrgb2hex
2323
frommatplotlib.datesimportUTC
@@ -1363,6 +1363,10 @@ def _print_svg(self, filename, fh, *, dpi=None, bbox_inches_restore=None,
13631363
defget_default_filetype(self):
13641364
return'svg'
13651365

1366+
defdraw(self):
1367+
_no_output_draw(self.figure)
1368+
returnsuper().draw()
1369+
13661370

13671371
FigureManagerSVG=FigureManagerBase
13681372

‎lib/matplotlib/backends/backend_template.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,14 @@ class methods button_press_event, button_release_event,
191191
"""
192192

193193
defdraw(self):
194-
"""Draw the figure using the renderer."""
194+
"""
195+
Draw the figure using the renderer.
196+
197+
It is important that this method actually walk the artist tree
198+
even if not output is produced because this will trigger
199+
deferred work (like computing limits auto-limits and tick
200+
values) that users may want access to before saving to disk.
201+
"""
195202
renderer=RendererTemplate(self.figure.dpi)
196203
self.figure.draw(renderer)
197204

‎lib/matplotlib/testing/__init__.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
importlocale
66
importlogging
7+
importsubprocess
8+
frompathlibimportPath
9+
fromtempfileimportTemporaryDirectory
710

811
importmatplotlibasmpl
912
frommatplotlibimport_api
@@ -44,3 +47,31 @@ def setup():
4447
# are not necessarily the default values as specified in rcsetup.py.
4548
set_font_settings_for_testing()
4649
set_reproducibility_for_testing()
50+
51+
52+
defcheck_for_pgf(texsystem):
53+
"""
54+
Check if a given TeX system + pgf is available
55+
56+
Parameters
57+
----------
58+
texsystem : str
59+
The executable name to check
60+
"""
61+
withTemporaryDirectory()astmpdir:
62+
tex_path=Path(tmpdir,"test.tex")
63+
tex_path.write_text(r"""
64+
\documentclass{minimal}
65+
\usepackage{pgf}
66+
\begin{document}
67+
\typeout{pgfversion=\pgfversion}
68+
\makeatletter
69+
\@@end
70+
""")
71+
try:
72+
subprocess.check_call(
73+
[texsystem,"-halt-on-error",str(tex_path)],cwd=tmpdir,
74+
stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
75+
except (OSError,subprocess.CalledProcessError):
76+
returnFalse
77+
returnTrue

‎lib/matplotlib/tests/test_backend_bases.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
importre
22

3+
frommatplotlib.testingimportcheck_for_pgf
34
frommatplotlib.backend_basesimport (
45
FigureCanvasBase,LocationEvent,MouseButton,MouseEvent,
56
NavigationToolbar2,RendererBase)
@@ -13,6 +14,9 @@
1314
importnumpyasnp
1415
importpytest
1516

17+
needs_xelatex=pytest.mark.skipif(notcheck_for_pgf('xelatex'),
18+
reason='xelatex + pgf is required')
19+
1620

1721
deftest_uses_per_path():
1822
id=transforms.Affine2D()
@@ -183,3 +187,38 @@ def test_toolbar_zoompan():
183187
assertax.get_navigate_mode()=="ZOOM"
184188
ax.figure.canvas.manager.toolmanager.trigger_tool('pan')
185189
assertax.get_navigate_mode()=="PAN"
190+
191+
192+
@pytest.mark.parametrize(
193+
"backend", ['svg','ps','pdf',pytest.param('pgf',marks=needs_xelatex)]
194+
)
195+
deftest_draw(backend):
196+
frommatplotlib.figureimportFigure
197+
frommatplotlib.backends.backend_aggimportFigureCanvas
198+
test_backend=pytest.importorskip(
199+
f'matplotlib.backends.backend_{backend}'
200+
)
201+
TestCanvas=test_backend.FigureCanvas
202+
fig_test=Figure(constrained_layout=True)
203+
TestCanvas(fig_test)
204+
axes_test=fig_test.subplots(2,2)
205+
206+
# defaults to FigureCanvasBase
207+
fig_agg=Figure(constrained_layout=True)
208+
# put a backends.backend_agg.FigureCanvas on it
209+
FigureCanvas(fig_agg)
210+
axes_agg=fig_agg.subplots(2,2)
211+
212+
init_pos= [ax.get_position()foraxinaxes_test.ravel()]
213+
214+
fig_test.canvas.draw()
215+
fig_agg.canvas.draw()
216+
217+
layed_out_pos_test= [ax.get_position()foraxinaxes_test.ravel()]
218+
layed_out_pos_agg= [ax.get_position()foraxinaxes_agg.ravel()]
219+
220+
forinit,placedinzip(init_pos,layed_out_pos_test):
221+
assertnotnp.allclose(init,placed,atol=0.005)
222+
223+
forref,testinzip(layed_out_pos_agg,layed_out_pos_test):
224+
np.testing.assert_allclose(ref,test,atol=0.005)

‎lib/matplotlib/tests/test_backend_pgf.py

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
importdatetime
22
fromioimportBytesIO
33
importos
4-
frompathlibimportPath
54
importshutil
65
importsubprocess
7-
fromtempfileimportTemporaryDirectory
86

97
importnumpyasnp
108
importpytest
119

1210
importmatplotlibasmpl
1311
importmatplotlib.pyplotasplt
12+
frommatplotlib.testingimportcheck_for_pgf
1413
frommatplotlib.testing.compareimportcompare_images,ImageComparisonFailure
1514
frommatplotlib.backends.backend_pgfimportPdfPages,common_texification
1615
frommatplotlib.testing.decoratorsimport (_image_directories,
@@ -19,32 +18,11 @@
1918

2019
baseline_dir,result_dir=_image_directories(lambda:'dummy func')
2120

22-
23-
defcheck_for(texsystem):
24-
withTemporaryDirectory()astmpdir:
25-
tex_path=Path(tmpdir,"test.tex")
26-
tex_path.write_text(r"""
27-
\documentclass{minimal}
28-
\usepackage{pgf}
29-
\begin{document}
30-
\typeout{pgfversion=\pgfversion}
31-
\makeatletter
32-
\@@end
33-
""")
34-
try:
35-
subprocess.check_call(
36-
[texsystem,"-halt-on-error",str(tex_path)],cwd=tmpdir,
37-
stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
38-
except (OSError,subprocess.CalledProcessError):
39-
returnFalse
40-
returnTrue
41-
42-
43-
needs_xelatex=pytest.mark.skipif(notcheck_for('xelatex'),
21+
needs_xelatex=pytest.mark.skipif(notcheck_for_pgf('xelatex'),
4422
reason='xelatex + pgf is required')
45-
needs_pdflatex=pytest.mark.skipif(notcheck_for('pdflatex'),
23+
needs_pdflatex=pytest.mark.skipif(notcheck_for_pgf('pdflatex'),
4624
reason='pdflatex + pgf is required')
47-
needs_lualatex=pytest.mark.skipif(notcheck_for('lualatex'),
25+
needs_lualatex=pytest.mark.skipif(notcheck_for_pgf('lualatex'),
4826
reason='lualatex + pgf is required')
4927
needs_ghostscript=pytest.mark.skipif(
5028
"eps"notinmpl.testing.compare.converter,
@@ -338,7 +316,7 @@ def test_unknown_font(caplog):
338316
@pytest.mark.parametrize("texsystem", ("pdflatex","xelatex","lualatex"))
339317
@pytest.mark.backend("pgf")
340318
deftest_minus_signs_with_tex(fig_test,fig_ref,texsystem):
341-
ifnotcheck_for(texsystem):
319+
ifnotcheck_for_pgf(texsystem):
342320
pytest.skip(texsystem+' + pgf is required')
343321
mpl.rcParams["pgf.texsystem"]=texsystem
344322
fig_test.text(.5,.5,"$-1$")

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp