get ready for class methods

This commit is contained in:
John Cupitt 2014-09-07 09:36:34 +01:00
parent 7ca9121c32
commit a26df2a8a9
3 changed files with 73 additions and 13 deletions

24
TODO
View File

@ -1,8 +1,32 @@
- python: - python:
- can we override __getattr__ on a type object?
Vips.Image.black
AttributeError: type object 'Image' has no attribute 'black'
we'd like to attack black as a class method, or override __getattr__
to let us patch class methods in
looks like defining a metaclass might do it, but
Vips.Image.__metaclass__ = ImageType
setattr(Vips.Image, '__metaclass__', ImageType)
setattr(Vips.Image, '__metaclass__', classmethod(ImageType))
don't work, nor any other obvious variations
we could walk all vips operators and paste in ones without an
image instance arg as class methods, but that would be very slow and
wouldn't work for loading plugins
- how about the in-place things? draw a circle? - how about the in-place things? draw a circle?
- try getting / setting / deleting metadata such as an ICC profile or
an exif tag
- try vips benchmark in vips8 python, how much slower? - try vips benchmark in vips8 python, how much slower?
- could import like this: - could import like this:

View File

@ -2,16 +2,15 @@
import sys import sys
#import logging import logging
#logging.basicConfig(level = logging.DEBUG) logging.basicConfig(level = logging.DEBUG)
from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Vips from gi.repository import Vips
from vips8 import vips from vips8 import vips
a = Vips.Image.black(100, 100) a = Vips.Image.black(100, 100)
b = Vips.Image.new_memory() a.write_to_file("x.v")
a.write(b)
b.write_to_file("x.v")

View File

@ -4,12 +4,10 @@ import sys
import logging import logging
from gi.repository import GLib
from gi.repository import GObject
# you might need this in your .bashrc # you might need this in your .bashrc
# export GI_TYPELIB_PATH=$VIPSHOME/lib/girepository-1.0 # export GI_TYPELIB_PATH=$VIPSHOME/lib/girepository-1.0
from gi.repository import Vips
from gi.repository import GLib, GObject, Vips
# start up vips! # start up vips!
Vips.init(sys.argv[0]) Vips.init(sys.argv[0])
@ -19,6 +17,8 @@ vips_type_array_int = GObject.GType.from_name("VipsArrayInt")
vips_type_array_double = GObject.GType.from_name("VipsArrayDouble") vips_type_array_double = GObject.GType.from_name("VipsArrayDouble")
vips_type_array_image = GObject.GType.from_name("VipsArrayImage") vips_type_array_image = GObject.GType.from_name("VipsArrayImage")
vips_type_blob = GObject.GType.from_name("VipsBlob") vips_type_blob = GObject.GType.from_name("VipsBlob")
vips_type_image = GObject.GType.from_name("VipsImage")
vips_type_operation = GObject.GType.from_name("VipsOperation")
class Error(Exception): class Error(Exception):
@ -83,8 +83,8 @@ class Argument:
# turn VipsBlobs into strings # turn VipsBlobs into strings
# FIXME ... this will involve a copy, we should use # FIXME ... this will involve a copy, we should use
# buffer() instead # buffer() instead
# if isinstance(value, Vips.Blob): if isinstance(value, Vips.Blob):
# value = value.get() value = value.get()
return value return value
@ -244,6 +244,10 @@ def vips_image_new_from_array(cls, array, scale = 1, offset = 0):
return image return image
# this is a class method
def vips_black(cls, width, height, **kwargs):
return _call_base("black", [width, height], kwargs)
def vips_image_getattr(self, name): def vips_image_getattr(self, name):
logging.debug('Image.__getattr__ %s' % name) logging.debug('Image.__getattr__ %s' % name)
@ -392,6 +396,39 @@ setattr(Vips.Image, 'new_from_file', classmethod(vips_image_new_from_file))
setattr(Vips.Image, 'new_from_buffer', classmethod(vips_image_new_from_buffer)) setattr(Vips.Image, 'new_from_buffer', classmethod(vips_image_new_from_buffer))
setattr(Vips.Image, 'new_from_array', classmethod(vips_image_new_from_array)) setattr(Vips.Image, 'new_from_array', classmethod(vips_image_new_from_array))
# yuk, we should run these via a metaclass somehow
setattr(Vips.Image, 'black', classmethod(vips_black))
# Search for all VipsOperation which don't have an input image object ... these
# become class methods
def vips_image_class_method(name, args, kwargs):
logging.debug('vips_image_class_method %s' % name)
return _call_instance(None, name, args, kwargs)
def define_class_methods(cls):
if len(cls.children) > 0:
for child in cls.children:
# not easy to get at the deprecated flag in an abtract type?
if cls.name != 'VipsWrap7':
define_class_methods(child)
elif cls.is_instantiatable():
op = Vips.Operation.new(cls.name)
found = False
for prop in op.props:
flags = op.get_argument_flags(prop.name)
if flags & Vips.ArgumentFlags.INPUT and flags & Vips.ArgumentFlags.REQUIRED:
if GObject.type_is_a(vips_type_image, prop.value_type):
found = True
break
if not found:
print 'operation %s has no input image args' % cls.name
setattr(Vips.Image, cls.name, classmethod(lambda *args, **kwargs: vips_image_class_method(cls.name, args, kwargs)))
define_class_methods(vips_type_operation)
# instance methods # instance methods
Vips.Image.write_to_file = vips_image_write_to_file Vips.Image.write_to_file = vips_image_write_to_file
Vips.Image.write_to_buffer = vips_image_write_to_buffer Vips.Image.write_to_buffer = vips_image_write_to_buffer