Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f38046b

Browse files
author
pwuertz
committed
backend_pgf: rework of the latex communication process for python3
1 parent 354721b commit f38046b

File tree

1 file changed

+45
-47
lines changed

1 file changed

+45
-47
lines changed

lib/matplotlib/backends/backend_pgf.py

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -220,15 +220,33 @@ def _build_latex_header():
220220
# Create LaTeX header with some content, else LaTeX will load some
221221
# math fonts later when we don't expect the additional output on stdout.
222222
# TODO: is this sufficient?
223-
latex_header = u"""\\documentclass{minimal}
224-
%s
225-
%s
226-
\\begin{document}
227-
text $math \mu$ %% force latex to load fonts now
228-
\\typeout{pgf_backend_query_start}
229-
""" % (latex_preamble, latex_fontspec)
223+
latex_header = [r"\documentclass{minimal}",
224+
latex_preamble,
225+
latex_fontspec,
226+
r"\begin{document}",
227+
r"text $math \mu$", # force latex to load fonts now
228+
r"\typeout{pgf_backend_query_start}"]
229+
return "\n".join(latex_header)
230+
231+
def _stdin_writeln(self, s):
232+
self.latex_stdin_utf8.write(s)
233+
self.latex_stdin_utf8.write("\n")
234+
self.latex_stdin_utf8.flush()
235+
236+
def _expect(self, s):
237+
exp = s.encode("utf8")
238+
buf = bytearray()
239+
while True:
240+
b = self.latex.stdout.read(1)
241+
buf += b
242+
if buf[-len(exp):] == exp:
243+
break
244+
if not len(b):
245+
raise LatexError("LaTeX process halted", buf.decode("utf8"))
246+
return buf.decode("utf8")
230247

231-
return latex_header
248+
def _expect_prompt(self):
249+
return self._expect("\n*")
232250

233251
def __init__(self):
234252
self.texcommand = get_texcommand()
@@ -238,27 +256,23 @@ def __init__(self):
238256
# test the LaTeX setup to ensure a clean startup of the subprocess
239257
latex = subprocess.Popen([self.texcommand, "-halt-on-error"],
240258
stdin=subprocess.PIPE,
241-
stdout=subprocess.PIPE,
242-
universal_newlines=True)
243-
stdout, stderr = latex.communicate(self.latex_header + latex_end)
259+
stdout=subprocess.PIPE)
260+
test_input = self.latex_header + latex_end
261+
stdout, stderr = latex.communicate(test_input.encode("utf-8"))
244262
if latex.returncode != 0:
245263
raise LatexError("LaTeX returned an error, probably missing font or error in preamble:\n%s" % stdout)
246264

247-
# open LaTeX process
265+
# open LaTeX process for real work
248266
latex = subprocess.Popen([self.texcommand, "-halt-on-error"],
249267
stdin=subprocess.PIPE,
250-
stdout=subprocess.PIPE,
251-
universal_newlines=True)
252-
latex.stdin.write(self.latex_header)
253-
latex.stdin.flush()
254-
# read all lines until our 'pgf_backend_query_start' token appears
255-
while not latex.stdout.readline().startswith("*pgf_backend_query_start"):
256-
pass
257-
while latex.stdout.read(1) != '*':
258-
pass
268+
stdout=subprocess.PIPE)
259269
self.latex = latex
260-
self.latex_stdin = codecs.getwriter("utf-8")(latex.stdin)
261-
self.latex_stdout = codecs.getreader("utf-8")(latex.stdout)
270+
self.latex_stdin_utf8 = codecs.getwriter("utf8")(self.latex.stdin)
271+
# write header with 'pgf_backend_query_start' token
272+
self._stdin_writeln(self._build_latex_header())
273+
# read all lines until our 'pgf_backend_query_start' token appears
274+
self._expect("*pgf_backend_query_start")
275+
self._expect_prompt()
262276

263277
# cache for strings already processed
264278
self.str_cache = {}
@@ -277,19 +291,6 @@ def __del__(self):
277291
except:
278292
pass
279293

280-
def _wait_for_prompt(self):
281-
"""
282-
Read all bytes from LaTeX stdout until a new line starts with a *.
283-
"""
284-
buf = [""]
285-
while True:
286-
buf.append(self.latex_stdout.read(1))
287-
if buf[-1] == "*" and buf[-2] == "\n":
288-
break
289-
if buf[-1] == "":
290-
raise LatexError("LaTeX process halted", u"".join(buf))
291-
return "".join(buf)
292-
293294
def get_width_height_descent(self, text, prop):
294295
"""
295296
Get the width, total height and descent for a text typesetted by the
@@ -298,30 +299,27 @@ def get_width_height_descent(self, text, prop):
298299

299300
# apply font properties and define textbox
300301
prop_cmds = _font_properties_str(prop)
301-
textbox = u"\\sbox0{%s %s}\n" % (prop_cmds, text)
302+
textbox = "\\sbox0{%s %s}" % (prop_cmds, text)
302303

303304
# check cache
304305
if textbox in self.str_cache:
305306
return self.str_cache[textbox]
306307

307308
# send textbox to LaTeX and wait for prompt
308-
self.latex_stdin.write(unicode(textbox))
309-
self.latex_stdin.flush()
309+
self._stdin_writeln(textbox)
310310
try:
311-
self._wait_for_prompt()
311+
self._expect_prompt()
312312
except LatexError as e:
313-
msg = u"Error processing '%s'\nLaTeX Output:\n%s" % (text, e.latex_output)
313+
msg = "Error processing '%s'\nLaTeX Output:\n%s" % (text, e.latex_output)
314314
raise ValueError(msg)
315315

316316
# typeout width, height and text offset of the last textbox
317-
query = "\\typeout{\\the\\wd0,\\the\\ht0,\\the\\dp0}\n"
318-
self.latex_stdin.write(query)
319-
self.latex_stdin.flush()
317+
self._stdin_writeln(r"\typeout{\the\wd0,\the\ht0,\the\dp0}")
320318
# read answer from latex and advance to the next prompt
321319
try:
322-
answer = self._wait_for_prompt()
320+
answer = self._expect_prompt()
323321
except LatexError as e:
324-
msg = u"Error processing '%s'\nLaTeX Output:\n%s" % (text, e.latex_output)
322+
msg = "Error processing '%s'\nLaTeX Output:\n%s" % (text, e.latex_output)
325323
raise ValueError(msg)
326324

327325
# parse metrics from the answer string
@@ -712,7 +710,7 @@ def print_pdf(self, filename, *args, **kwargs):
712710
texcommand = get_texcommand()
713711
cmdargs = [texcommand, "-interaction=nonstopmode", "-halt-on-error", "figure.tex"]
714712
try:
715-
stdout = subprocess.check_output(cmdargs, universal_newlines=True, stderr=subprocess.STDOUT)
713+
stdout = subprocess.check_output(cmdargs, stderr=subprocess.STDOUT)
716714
except:
717715
raise RuntimeError("%s was not able to process your file.\n\nFull log:\n%s" % (texcommand, stdout))
718716
shutil.copyfile("figure.pdf", target)

0 commit comments

Comments
 (0)