pyx-project / pyx

Repository of PyX, a Python package for the creation of PostScript, PDF, and SVG files.
https://pyx-project.org/
GNU General Public License v2.0
109 stars 18 forks source link

fix t1 extension with Python 3.10 #35

Closed mjg closed 2 years ago

mjg commented 2 years ago

For all # variants of formats (s#, y#, etc.), the macro PY_SSIZE_T_CLEAN must be defined before including Python.h. On Python 3.9 and older, the type of the length argument is Py_ssize_t if the PY_SSIZE_T_CLEAN macro is defined, or int otherwise. [https://docs.python.org/3.10/c-api/arg.html]

So, on Python 3.9, PyX worked because PY_SSIZE_T_CLEAN was not defined (even though it was recommended), so that the deprecated return type of int was used.

Python 3.10 finally pulls the trigger on the ints, so finally adjust to that announced change.

mjg commented 2 years ago
from pyx import *

c = canvas.canvas()

c.text(0, 0, "Hello")

c.writePDFfile()

gives the following with Python 3.10 (Fedora 35):

Traceback (most recent call last):
  File "/home/mjg/fedora-scm/PyX/t.py", line 7, in <module>
    c.writePDFfile()
  File "/usr/lib64/python3.10/site-packages/pyx/canvas.py", line 50, in wrappedindocument
    return method(d, file, **write_kwargs)
  File "/usr/lib64/python3.10/site-packages/pyx/document.py", line 193, in writePDFfile
    pdfwriter.PDFwriter(self, f, **kwargs)
  File "/usr/lib64/python3.10/site-packages/pyx/pdfwriter.py", line 334, in __init__
    registry.write(file, self, catalog)
  File "/usr/lib64/python3.10/site-packages/pyx/pdfwriter.py", line 78, in write
    object.write(file, writer, self)
  File "/usr/lib64/python3.10/site-packages/pyx/font/font.py", line 278, in write
    self.t1file.getstrippedfont(self.glyphnames, self.charcodes).outputPDF(file, writer)
  File "/usr/lib64/python3.10/site-packages/pyx/font/t1file.py", line 1019, in getstrippedfont
    self.gatherglyphcalls(glyph, seacglyphs, subrs, T1context(self))
  File "/usr/lib64/python3.10/site-packages/pyx/font/t1file.py", line 900, in gatherglyphcalls
    self.gathercalls(self.getglyphcmds(glyph), seacglyphs, subrs, context)
  File "/usr/lib64/python3.10/site-packages/pyx/font/t1file.py", line 859, in getglyphcmds
    self._data2decode()
  File "/usr/lib64/python3.10/site-packages/pyx/font/t1file.py", line 721, in _data2decode
    self._data2 = self._eexecdecode(self._data2eexec)
  File "/usr/lib64/python3.10/site-packages/pyx/font/t1file.py", line 670, in _eexecdecode
    return decoder(code, self.eexecr, 4)
SystemError: PY_SSIZE_T_CLEAN macro must be defined for '#' formats

With the suggested patch, t.py works a expected. (This also works without using the extension, of course.)

joerg-lehmann commented 2 years ago

Thanks for the patch, Michael! Looks good.

Would you like to add a CHANGES entry for completeness?

mjg commented 2 years ago

Thanks for the patch, Michael! Looks good.

Would you like to add a CHANGES entry for completeness?

Sure, I'll rebase on master then. The current patch is on 0.15 (as packaged in Fedora) where a CHANGES change does not make much sense, unless you intend to branch for a hotfix.

joerg-lehmann commented 2 years ago

Sure, please rebase on the master. No need for a hot-fix for this issue. Distros compiling the extension module and using Python 3.10 should backport this fix if needed.

joerg-lehmann commented 2 years ago

Thanks, again. Just merged the fix.