added class methods to python

we now have Vips.Image.black(w, h), woo
This commit is contained in:
John Cupitt 2014-09-08 14:53:37 +01:00
parent a26df2a8a9
commit 84e55b86e6
5 changed files with 34 additions and 27 deletions

21
TODO
View File

@ -1,27 +1,6 @@
- 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

View File

@ -618,6 +618,7 @@ void *vips_type_map( GType base, VipsTypeMap2Fn fn, void *a, void *b );
void *vips_type_map_all( GType base, VipsTypeMapFn fn, void *a );
int vips_type_depth( GType type );
GType vips_type_find( const char *basename, const char *nickname );
const char *vips_nickname_find( GType type );
void *vips_class_map_all( GType base, VipsClassMapFn fn, void *a );
VipsObjectClass *vips_class_find( const char *basename, const char *nickname );

View File

@ -2746,6 +2746,29 @@ vips_type_find( const char *basename, const char *nickname )
return( type );
}
/**
* vips_nickname_find:
* @type: #GType to search for
*
* Return the VIPS nickanme for a %GType. Handy for language bindings.
*
* Returns: (transfer none): the class nickname.
*/
const char *
vips_nickname_find( GType type )
{
gpointer p;
VipsObjectClass *class;
if( type &&
(p = g_type_class_ref( type )) &&
VIPS_IS_OBJECT_CLASS( p ) &&
(class = VIPS_OBJECT_CLASS( p )) )
return( class->nickname );
return( NULL );
}
/* The vips_object_local() macro uses this as its callback.
*/
void

View File

@ -5,8 +5,6 @@ import sys
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

View File

@ -397,7 +397,7 @@ 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))
#setattr(Vips.Image, 'black', classmethod(vips_black))
# Search for all VipsOperation which don't have an input image object ... these
# become class methods
@ -405,7 +405,10 @@ setattr(Vips.Image, 'black', classmethod(vips_black))
def vips_image_class_method(name, args, kwargs):
logging.debug('vips_image_class_method %s' % name)
return _call_instance(None, name, args, kwargs)
# the first arg is the class we are called from ... drop it
args = tuple(list(args)[1::])
return _call_base(name, args, kwargs)
def define_class_methods(cls):
if len(cls.children) > 0:
@ -424,8 +427,11 @@ def define_class_methods(cls):
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)))
gtype = Vips.type_find("VipsOperation", cls.name)
nickname = Vips.nickname_find(gtype)
logging.debug('adding %s as a class method' % nickname)
method = lambda *args, **kwargs: vips_image_class_method( nickname, args, kwargs)
setattr(Vips.Image, nickname, classmethod(method))
define_class_methods(vips_type_operation)