2

So I am trying to generate postscript from Python. Currently trying with PyX 0.14.1 on Python3.4.2, but I am open to suggestions, if you know something simpler.

I was following mostly the suggestions found on the PyX mailing list in this thread. This was Python2 and is quite old. The following shows my current code after many changes:

from pyx import *

text.set(cls=text.LatexRunner, texenc='utf-8')
text.preamble(r'\usepackage{ucs}')
text.preamble(r'\usepackage[utf8x]{inputenc}')

c = canvas.canvas()
c.text(5, 5, "Sören Sundstrøm".encode("utf8"))

p = document.page(c, paperformat=document.paperformat.A4,
    centered=0)
d = document.document([p])
d.writePSfile('test.ps')

PyX stops with a TexResultError. The interesting part of the error shows what's happening in TeX:

pyx.text.TexResultError: unhandled TeX response (might be an error)
The expression passed to TeX was:
  \ProcessPyXBox{b'S\xc3\xb6ren Sundstr\xc3\xb8m'%
  }{1}%
  \PyXInput{7}%
After parsing the return message from TeX, the following was left:
  *
  *! Undefined control sequence.
  <argument> b'S\xc 
                    3\xb 6ren Sundstr\xc 3\xb 8m'
  <*> }{1}
  (cut after 5 lines; use errordetail.full for all output)

So it looks like latex is receiving not utf-8, but an escaped representation of utf-8. My question: How do I pass the string to canvas.text correctly? Or is my preamble wrong?

I also tried to follow this answer by wobsta here on SO, but besides being much too complicated, it does not work for me either. (Looks like PyX does not understand a metafont message in this case).

Running latex directly on a simple utf-8 input file with the same preamble works fine by the way.

Community
  • 1
  • 1
mkiever
  • 894
  • 5
  • 13

1 Answers1

2

Looking into the PyX code revealed the problem. The text module prepares an io.TextIOWrapper with utf-8 encoding to be used for TeX input. The string parameters in text.preamble and canvas.text are passed verbatim to the wrapper, so in Python 3 you just pass a string without any encoding necessary. Encoding will be done by the wrapper.

My original unsimplified code had another problem which made it difficult to solve this first problem. So for completeness here's the second problem and its solution. My original code had this order of operations:

from pyx import *

c = canvas.canvas()
# doing other stuff with canvas

text.set(cls=text.LatexRunner, texenc='utf-8')
text.preamble(r'\usepackage{ucs}')
text.preamble(r'\usepackage[utf8x]{inputenc}')

c.text(5, 5, "Sören Sundstrøm")

p = document.page(c, paperformat=document.paperformat.A4,
    centered=0)
d = document.document([p])
d.writePSfile('test.ps')

This does not work either, because when a canvas is created it keeps a reference to a text.defaulttexrunner which is set up with the current settings of the text module. The changed text module settings never influence the canvas instance. So you have to set-up the text module before you create the canvas where you want to draw text into.

Thanks to anyone who looked into this.

mkiever
  • 894
  • 5
  • 13