1# -*- coding: utf-8 -*- 2 3from __future__ import absolute_import, division, print_function 4 5import io 6import re 7import warnings 8 9import numpy as np 10import pytest 11import six 12 13import matplotlib 14import matplotlib.pyplot as plt 15from matplotlib import patheffects 16from matplotlib.testing.decorators import image_comparison 17from matplotlib.testing.determinism import (_determinism_source_date_epoch, 18 _determinism_check) 19 20 21with warnings.catch_warnings(): 22 warnings.simplefilter('ignore') 23 needs_ghostscript = pytest.mark.skipif( 24 matplotlib.checkdep_ghostscript()[0] is None, 25 reason="This test needs a ghostscript installation") 26 needs_usetex = pytest.mark.skipif( 27 not matplotlib.checkdep_usetex(True), 28 reason="This test needs a TeX installation") 29 30 31# This tests tends to hit a TeX cache lock on AppVeyor. 32@pytest.mark.flaky(reruns=3) 33@pytest.mark.parametrize('format, use_log, rcParams', [ 34 ('ps', False, {}), 35 pytest.param('ps', False, {'ps.usedistiller': 'ghostscript'}, 36 marks=needs_ghostscript), 37 pytest.param('ps', False, {'text.latex.unicode': True, 38 'text.usetex': True}, 39 marks=[needs_ghostscript, needs_usetex]), 40 ('eps', False, {}), 41 ('eps', True, {'ps.useafm': True}), 42 pytest.param('eps', False, {'text.latex.unicode': True, 43 'text.usetex': True}, 44 marks=[needs_ghostscript, needs_usetex]), 45], ids=[ 46 'ps', 47 'ps with distiller', 48 'ps with usetex', 49 'eps', 50 'eps afm', 51 'eps with usetex' 52]) 53def test_savefig_to_stringio(format, use_log, rcParams): 54 matplotlib.rcParams.update(rcParams) 55 56 fig, ax = plt.subplots() 57 buffers = [ 58 six.moves.StringIO(), 59 io.StringIO(), 60 io.BytesIO()] 61 62 if use_log: 63 ax.set_yscale('log') 64 65 ax.plot([1, 2], [1, 2]) 66 ax.set_title(u"Déjà vu") 67 for buffer in buffers: 68 fig.savefig(buffer, format=format) 69 70 values = [x.getvalue() for x in buffers] 71 72 if six.PY3: 73 values = [ 74 values[0].encode('ascii'), 75 values[1].encode('ascii'), 76 values[2]] 77 78 # Remove comments from the output. This includes things that 79 # could change from run to run, such as the time. 80 values = [re.sub(b'%%.*?\n', b'', x) for x in values] 81 82 assert values[0] == values[1] 83 assert values[1] == values[2].replace(b'\r\n', b'\n') 84 for buffer in buffers: 85 buffer.close() 86 87 88def test_patheffects(): 89 with matplotlib.rc_context(): 90 matplotlib.rcParams['path.effects'] = [ 91 patheffects.withStroke(linewidth=4, foreground='w')] 92 fig, ax = plt.subplots() 93 ax.plot([1, 2, 3]) 94 with io.BytesIO() as ps: 95 fig.savefig(ps, format='ps') 96 97 98@needs_usetex 99@needs_ghostscript 100def test_tilde_in_tempfilename(): 101 # Tilde ~ in the tempdir path (e.g. TMPDIR, TMP or TEMP on windows 102 # when the username is very long and windows uses a short name) breaks 103 # latex before https://github.com/matplotlib/matplotlib/pull/5928 104 import tempfile 105 import shutil 106 import os 107 import os.path 108 109 tempdir = None 110 old_tempdir = tempfile.tempdir 111 try: 112 # change the path for new tempdirs, which is used 113 # internally by the ps backend to write a file 114 tempdir = tempfile.mkdtemp() 115 base_tempdir = os.path.join(tempdir, "short~1") 116 os.makedirs(base_tempdir) 117 tempfile.tempdir = base_tempdir 118 119 # usetex results in the latex call, which does not like the ~ 120 plt.rc('text', usetex=True) 121 plt.plot([1, 2, 3, 4]) 122 plt.xlabel(r'\textbf{time} (s)') 123 output_eps = os.path.join(base_tempdir, 'tex_demo.eps') 124 # use the PS backend to write the file... 125 plt.savefig(output_eps, format="ps") 126 finally: 127 tempfile.tempdir = old_tempdir 128 if tempdir: 129 try: 130 shutil.rmtree(tempdir) 131 except Exception as e: 132 # do not break if this is not removable... 133 print(e) 134 135 136def test_source_date_epoch(): 137 """Test SOURCE_DATE_EPOCH support for PS output""" 138 # SOURCE_DATE_EPOCH support is not tested with text.usetex, 139 # because the produced timestamp comes from ghostscript: 140 # %%CreationDate: D:20000101000000Z00\'00\', and this could change 141 # with another ghostscript version. 142 _determinism_source_date_epoch( 143 "ps", b"%%CreationDate: Sat Jan 01 00:00:00 2000") 144 145 146def test_determinism_all(): 147 """Test for reproducible PS output""" 148 _determinism_check(format="ps") 149 150 151@needs_usetex 152@needs_ghostscript 153def test_determinism_all_tex(): 154 """Test for reproducible PS/tex output""" 155 _determinism_check(format="ps", usetex=True) 156 157 158@image_comparison(baseline_images=["empty"], extensions=["eps"]) 159def test_transparency(): 160 fig, ax = plt.subplots() 161 ax.set_axis_off() 162 ax.plot([0, 1], color="r", alpha=0) 163 ax.text(.5, .5, "foo", color="r", alpha=0) 164 165 166@needs_usetex 167def test_failing_latex(tmpdir): 168 """Test failing latex subprocess call""" 169 path = str(tmpdir.join("tmpoutput.ps")) 170 171 matplotlib.rcParams['text.usetex'] = True 172 173 # This fails with "Double subscript" 174 plt.xlabel("$22_2_2$") 175 with pytest.raises(RuntimeError): 176 plt.savefig(path) 177