From a26df2a8a91fa47069c749b45c1afed6f47ccee4 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 7 Sep 2014 09:36:34 +0100 Subject: [PATCH] get ready for class methods --- TODO | 24 ++++++++++++++++++++++ python/try9.py | 13 ++++++------ python/vips8/vips.py | 49 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/TODO b/TODO index 09d14f17..0ac5d7a5 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,32 @@ - 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? + - try getting / setting / deleting metadata such as an ICC profile or + an exif tag + - try vips benchmark in vips8 python, how much slower? - could import like this: diff --git a/python/try9.py b/python/try9.py index 691cb5d0..084115de 100755 --- a/python/try9.py +++ b/python/try9.py @@ -2,16 +2,15 @@ import sys -#import logging -#logging.basicConfig(level = logging.DEBUG) +import logging +logging.basicConfig(level = logging.DEBUG) +from gi.repository import GLib +from gi.repository import GObject from gi.repository import Vips + from vips8 import vips a = Vips.Image.black(100, 100) -b = Vips.Image.new_memory() - -a.write(b) - -b.write_to_file("x.v") +a.write_to_file("x.v") diff --git a/python/vips8/vips.py b/python/vips8/vips.py index 350ae994..229076c8 100644 --- a/python/vips8/vips.py +++ b/python/vips8/vips.py @@ -4,12 +4,10 @@ import sys import logging -from gi.repository import GLib -from gi.repository import GObject - # you might need this in your .bashrc # export GI_TYPELIB_PATH=$VIPSHOME/lib/girepository-1.0 -from gi.repository import Vips + +from gi.repository import GLib, GObject, Vips # start up vips! 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_image = GObject.GType.from_name("VipsArrayImage") 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): @@ -83,8 +83,8 @@ class Argument: # turn VipsBlobs into strings # FIXME ... this will involve a copy, we should use # buffer() instead -# if isinstance(value, Vips.Blob): -# value = value.get() + if isinstance(value, Vips.Blob): + value = value.get() return value @@ -244,6 +244,10 @@ def vips_image_new_from_array(cls, array, scale = 1, offset = 0): 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): 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_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 Vips.Image.write_to_file = vips_image_write_to_file Vips.Image.write_to_buffer = vips_image_write_to_buffer