If you open a svgsurface with sys.stdout when you call .finish(), then you get TypeError: must be str, not bytes The docs says "fobj (None, str, file or file-like object) – a filename or writable file object. None may be used to specify no output. " which sys.stdout is
The bug in is _write_func at src/surface.c:127
sys.stdout is a file-like object, but in Python 3 there are now 2 types of file objects - text-mode and bytes-mode objects. The Python 2 sys.stdout was equivalent to the Python 3 bytes-mode objects and you could write binary data to sys.stdout. The Python 3 sys.stdout is a text-mode object and you can no longer write binary data to it. So the old method no longer works. SVG files use XML format and are text-mode files. So I changed the SVG write_func to use text-mode. So writing to sys.stdout is working again. Fixed in the git repo.
note to self: fixed in commit 9576b3d77034d91f456a5b199a9fc9cc2fde3c08
I think this is the wrong way to fix this bug: it helps with SVGSurface(sys.stdout, foo, bar) but not with PDFSurface(sys.stdout, foo, bar) and others. The generated SVG files have a `<?xml version="1.0" encoding="UTF-8"?>` header, which mean they are bytes, not unicode. For that reason and for consistency with other surface types, I think that SVGSurface should always emit bytes. The documentation clarification are good, but the changes to surface.c in commit 9576b3d7703 should be reverted. This shouldn’t cause much compatibility problem since the change never was in a release. The fix for the original issue is easy: to write bytes to the standard output in Python 3, use sys.stdout.buffer. See http://docs.python.org/3/library/sys.html#sys.stdout For code that runs on both Python 2 and 3, use .buffer if it exists: bytes_stdout = sys.stdout.buffer if hasattr(sys.stdout, 'buffer') else sys.stdout # Or shorter: bytes_stdout = getattr(sys.stdout, 'buffer', sys.stdout) cairo.SVGSurface(stdout foo, bar) cairo.PDFSurface(stdout foo, bar) For an in-memory file object, always use io.BytesIO(). It’s available since Python 2.6.
Created attachment 71790 [details] [review] Revert SVGSurface to bytes-mode This reverts some changes in 9576b3d77034d91f456a5b199a9fc9cc2fde3c08 as described in comment 4, but keeps the documentation clarifications. Generated with 'git format-patch', should be ready for 'git am'. Also available here: https://github.com/SimonSapin/pycairo/commit/c682c4df83a29bd9c2fd7f7c92c19f1c42de8b61
The mentioned commit was never part of pycairo 1.11, which is based on the Python 2 version, so closing.
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.