Closed jy2wong closed 9 years ago
Ugh, the GdkPixbuf API varies so much from one {os, revision} to another.
Couple of things to try: does making the "backhanded" fix in https://github.com/mypaint/mypaint/blob/cf527fc2fa63d69591f2dcd27a3e68663ae0e57d/lib/pixbuf.py#L38 available for all systems fix the issue?
Also, here's the tool I use for deciding what is available in a given PyGI lib:
#!/usr/bin/python
import os.path
import sys
import gi
gi.require_version("Gdk", "3.0")
try:
gimodname = sys.argv[1]
substrings = sys.argv[2:]
except IndexError:
print "usage: %s GIMODNAME [SUBSTRINGS...]" % os.path.basename(sys.argv[0])
print
print "Imports gi.repository.GI.MOD.NAME and searches its contents",
print "for SUBSTRINGS."
print "If there are no SUBSTRINGS, all contents are listed."
sys.exit(1)
modbase = gimodname.split(".", 1)[0]
mod = __import__("gi.repository.%s" % modbase, {}, {}, [])
if substrings:
for substring in substrings:
print eval("[n for n in dir(gi.repository.%s) if %r in n.lower()]" %
(gimodname, substring.lower()))
else:
print eval("dir(gi.repository.%s)" % gimodname)
Use it as, e.g.
$ pygi-grep GdkPixbuf.Pixbuf save
['save_to_bufferv', 'save_to_callbackv', 'save_to_stream_finish', 'savev']
to see what you have available :/
Maybe I missed the link in the last thread, but https://trac.macports.org/ticket/46812 seems to confirm that it is indeed 2.31.2 to blame.
* jy2 >> pygi-grep GdkPixbuf.Pixbuf save
['save', 'save_to_buffer', 'save_to_callback', 'save_to_stream_finish']
so the previous backhanded fix won't work (and will stop working eventually even for its original purpose).
...what does work, however, is renaming savev
to save
without changing any parameters.
FWIW, MINGW-packages is using 2.31.1. Need to check what that supports, although .save_to_callbackv
must be in there.
I guess we should try hasattr(GdkPixbuf.Pixbuf, "savev")
first, because that name will always mean a vector version if it exists, and then try pixbuf.save()
in the hope that it takes two vectors?
What a mess. Upstream bug is https://bugzilla.gnome.org/show_bug.cgi?id=670372#c7 - perhaps we should just wait for that to unbreak the GdkPixbuf API.
I was thinking
try:
pixbuf.savev(...)
except AttributeError:
pixbuf.save(...)
which is basically the same thing.
I'm erring towards fixing it up now. The cruft is limited to an extra three lines all in one place, and if you happen to have the wrong version of gdk-pixbuf, mypaint is...very unusable.
GdkPixbuf save method summary:
OS | Distro | Version | Save method names |
---|---|---|---|
GNU/Linux | Ubuntu 12.04 | 2.30.7 | ['save_tobufferv', 'save_tocallbackv', 'save_to_stream_finish', 'savev'] |
Win7 | MSYS2 MINGW32 | 2.31.1 | ['save_to_bufferv', 'save_to_callbackv', 'save_to_stream_finish', |
GNU/Linux | Debian testing | 2.31.1 | ['save_tobufferv', 'save_tocallbackv', 'save_to_stream_finish', 'savev'] |
GNU/Linux | Rosa? | 2.31.2 | ['save', 'save_tobuffer', 'save_tocallback', 'save_to_stream_finish'] |
I've bolded any which I know work and take vector-style arguments, italicized any that look plausible as a workaround for this issue, and struck out any which just appear to be incorrectly annotated when run. For example, for the Windows example I tried
>>> from gi.repository import GdkPixbuf
>>> GdkPixbuf.PIXBUF_VERSION
'2.31.1'
>>> p = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 64, 64)
>>> p.savev_utf8("test1.png", "png", ["tEXt::greeting"], ["Hello, world"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Must be string, not list
>>> p.savev_utf8("test1.png", "png", "tEXt::greeting", "Hello, world")
/mingw32/bin/python2: line 6: 3344 Segmentation fault "$( dirname ${BASH_SOURCE[0]} )/python2.exe" "$@"
but it's supposed to work like just like the nonexistant savev()
, supposedly: in the C source it's just a macro alias:
https://git.gnome.org/browse/gdk-pixbuf/tree/gdk-pixbuf/gdk-pixbuf-core.h?id=2.31.1#n320
@jy2wong Can you confirm that save()
works and saves that tEXt chunk on your test system? If so, the patch you suggest looks good.
(I'd be quite happy to use the backhanded save_to_callback
[v
] approach on all systems too, to gain some measure of control over filesystem encoding issues, which are a recurring nightmare on Windows expecially. Reducing codepaths is a good idea. Perhaps:
try:
save_to_callbackv = pixbuf.save_to_callbackv
except AttributeError:
save_to_callbackv = pixbuf.save_to_callback
save_to_callbackv(...)
might be the right coordinated approach?)
Turns out my memory of "save" and no "savev" was from the PyGTK/GTK2 era, and it had sugared syntax in that old manual wrapping:
>>> from gtk import gdk
>>> [n for n in dir(gdk.Pixbuf) if "save" in n]
['save', 'save_to_callback']
>>> p = gdk.Pixbuf(gdk.COLORSPACE_RGB, True, 8, 64, 64)
>>> p.save("/tmp/test3.png", "png", {"tEXt::greeting": "Hello, world"})
>>>
We don't have to support this any more, so testing for "save" before "savev" would be just as legit.
Python 2.7.9 (default, Dec 11 2014, 04:42:00)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from gi.repository import GdkPixbuf
>>> GdkPixbuf.PIXBUF_VERSION
'2.31.2'
>>> p = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 64, 64)
>>> p.save("test1.png", "png", ["tEXt::greeting"], ["Hello, world"])
True
all seems fine.
I'm getting a no savev attribute error similar to the ones described in #202. I did a
scons
and agit submodule update
right before just in case, too. Everything's been fine from January 14th up until March 1st, which seems to be the day I updatedgdk-pixbuf2
to version 2.31.2. (and the day mypaint ate 20 minutes of tricky lineart fixes...)Nothing in the changelog jumps out to me as suspicious. http://upstream.rosalinux.ru/changelogs/gdk-pixbuf/2.31.2/changelog.html
I'll be investigating more today.
Steps to reproduce:
mypaint -c /tmp/fresh