[pygobject/gsoc2009: 30/160] Large refactoring of Python code and more
- From: Simon van der Linden <svdlinden src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [pygobject/gsoc2009: 30/160] Large refactoring of Python code and more
- Date: Fri, 14 Aug 2009 21:24:37 +0000 (UTC)
commit b7cabdb9cdc9146c5c173357f4c7b24f50418a6c
Author: Simon van der Linden <svdlinden src gnome org>
Date: Thu Jul 9 17:20:37 2009 +0200
Large refactoring of Python code and more
Make the non-default constructors work, even for subclasses.
Add instance checking for methods.
Add class checking for constructors.
Add tests for Python subclassing.
girepository/bank-info.c | 195 ++++++++++++++++++++++++--------
girepository/btypes.py | 237 +++++++++++++--------------------------
girepository/module.py | 251 ++++++++++++++---------------------------
girepository/overrides/Gdk.py | 5 +-
girepository/overrides/Gtk.py | 5 +-
tests/test_girepository.py | 154 ++++++++++++++++++++-----
6 files changed, 439 insertions(+), 408 deletions(-)
---
diff --git a/girepository/bank-info.c b/girepository/bank-info.c
index 2a63274..b3fcebe 100644
--- a/girepository/bank-info.c
+++ b/girepository/bank-info.c
@@ -21,6 +21,8 @@
#include "bank.h"
#include <pygobject.h>
+static PyTypeObject *PyGObject_Type = NULL;
+
static void pyg_base_info_dealloc(PyGIBaseInfo *self);
static void pyg_base_info_free(PyObject *op);
static PyObject* pyg_base_info_repr(PyGIBaseInfo *self);
@@ -469,8 +471,133 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
}
/* Check argument types. */
- py_args_pos = (is_method || is_constructor) ? 1 : 0;
- /* TODO: check the methods' first argument. */
+ py_args_pos = 0;
+ if (is_constructor) {
+ PyObject *py_arg;
+
+ g_assert(n_py_args > 0);
+ py_arg = PyTuple_GetItem(args, py_args_pos);
+ g_assert(py_arg != NULL);
+
+ if (PyGObject_Type == NULL) {
+ PyObject *module;
+ if ((module = PyImport_ImportModule("gobject")) != NULL) {
+ PyGObject_Type = (PyTypeObject *)PyObject_GetAttrString(module, "GObject");
+ }
+ }
+
+ if (!PyType_Check(py_arg)) {
+ PyErr_Format(PyExc_TypeError, "%s.%s() argument %zd: Must be type, not %s",
+ g_base_info_get_namespace(self->info), g_base_info_get_name(self->info),
+ py_args_pos, ((PyTypeObject *)py_arg)->tp_name);
+ } else if (!PyType_IsSubtype((PyTypeObject *)py_arg, PyGObject_Type)) {
+ PyErr_Format(PyExc_TypeError, "%s.%s() argument %zd: Must be a non-strict subclass of %s",
+ g_base_info_get_namespace(self->info), g_base_info_get_name(self->info),
+ py_args_pos, PyGObject_Type->tp_name);
+ } else {
+ GIBaseInfo *interface_info;
+ GType interface_g_type;
+ GType arg_g_type;
+
+ interface_info = g_type_info_get_interface(return_info);
+
+ interface_g_type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)interface_info);
+ arg_g_type = pyg_type_from_object(py_arg);
+
+ if (!g_type_is_a(arg_g_type, interface_g_type)) {
+ PyErr_Format(PyExc_TypeError, "%s.%s() argument %zd: Must be a non-strict subclass of %s",
+ g_base_info_get_namespace(self->info), g_base_info_get_name(self->info),
+ py_args_pos, g_type_name(interface_g_type));
+ }
+
+ g_base_info_unref(interface_info);
+ }
+
+ if (PyErr_Occurred()) {
+ g_base_info_unref((GIBaseInfo *)return_info);
+ return NULL;
+ }
+
+ py_args_pos += 1;
+ } else if (is_method) {
+ PyObject *py_arg;
+ GIBaseInfo *container_info;
+ GIInfoType container_info_type;
+
+ g_assert(n_py_args > 0);
+ py_arg = PyTuple_GetItem(args, py_args_pos);
+ g_assert(py_arg != NULL);
+
+ container_info = g_base_info_get_container(self->info);
+ container_info_type = g_base_info_get_type(container_info);
+
+ /* FIXME: this could take place in pyg_argument_from_pyobject, but we need to create an
+ independant function because it needs a GITypeInfo to be passed. */
+
+ switch(container_info_type) {
+ case GI_INFO_TYPE_OBJECT:
+ {
+ PyObject *py_type;
+ GType container_g_type;
+ GType arg_g_type;
+
+ py_type = PyObject_Type(py_arg);
+ g_assert(py_type != NULL);
+
+ container_g_type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)container_info);
+ arg_g_type = pyg_type_from_object(py_arg);
+
+ /* Note: If the first argument is not an instance, its type hasn't got a gtype. */
+ if (!g_type_is_a(arg_g_type, container_g_type)) {
+ PyErr_Format(PyExc_TypeError, "%s.%s() argument %zd: Must be %s, not %s",
+ g_base_info_get_namespace(self->info), g_base_info_get_name(self->info),
+ py_args_pos, g_base_info_get_name(container_info), ((PyTypeObject *)py_type)->tp_name);
+ }
+
+ Py_DECREF(py_type);
+
+ break;
+ }
+ case GI_INFO_TYPE_BOXED:
+ case GI_INFO_TYPE_STRUCT:
+ {
+ GIBaseInfo *info;
+
+ info = pyg_base_info_from_object(py_arg);
+ if (info == NULL || !g_base_info_equals(info, container_info)) {
+ PyObject *py_type;
+
+ py_type = PyObject_Type(py_arg);
+ g_assert(py_type != NULL);
+
+ PyErr_Format(PyExc_TypeError, "%s.%s() argument %zd: Must be %s, not %s",
+ g_base_info_get_namespace(self->info), g_base_info_get_name(self->info),
+ py_args_pos, g_base_info_get_name(container_info), ((PyTypeObject *)py_type)->tp_name);
+
+ Py_DECREF(py_type);
+ }
+
+ if (info != NULL) {
+ g_base_info_unref(info);
+ }
+
+ break;
+ }
+ case GI_INFO_TYPE_UNION:
+ /* TODO */
+ default:
+ /* The other info types haven't got methods. */
+ g_assert_not_reached();
+ }
+
+ g_base_info_unref(container_info);
+
+ if (PyErr_Occurred()) {
+ return NULL;
+ }
+
+ py_args_pos += 1;
+ }
for (i = 0; i < n_args; i++) {
GIArgInfo *arg_info;
GITypeInfo *type_info;
@@ -758,58 +885,32 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
g_assert(return_value != NULL);
} else {
- /* Wrap the return value inside the first argument. */
+ /* Instanciate the class passed as first argument and attach the GObject instance. */
+ PyTypeObject *py_type;
+ PyGObject *self;
g_assert(n_py_args > 0);
- return_value = PyTuple_GetItem(args, 0);
- g_assert(return_value != NULL);
-
- Py_INCREF(return_value);
-
- if (return_tag == GI_TYPE_TAG_INTERFACE) {
- GIBaseInfo *interface_info;
- GIInfoType interface_info_type;
-
- interface_info = g_type_info_get_interface(return_info);
- interface_info_type = g_base_info_get_type(interface_info);
-
- if (interface_info_type == GI_INFO_TYPE_STRUCT || interface_info_type == GI_INFO_TYPE_BOXED) {
- /* FIXME: We should reuse this. Perhaps by separating the
- * wrapper creation from the binding to the wrapper.
- */
- GIStructInfo *struct_info;
- gsize size;
- PyObject *buffer;
- int retval;
-
- struct_info = g_interface_info_get_iface_struct((GIInterfaceInfo *)interface_info);
-
- size = g_struct_info_get_size (struct_info);
- g_assert(size > 0);
+ py_type = (PyTypeObject *)PyTuple_GetItem(args, 0);
+ g_assert(py_type != NULL);
- buffer = PyBuffer_FromReadWriteMemory(return_arg.v_pointer, size);
-
- retval = PyObject_SetAttrString(return_value, "__buffer__", buffer);
- g_assert(retval != -1);
+ if (py_type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
+ Py_INCREF(py_type);
+ }
+ self = PyObject_GC_New(PyGObject, py_type);
+ self->inst_dict = NULL;
+ self->weakreflist = NULL;
+ self->private_flags.flags = 0;
- g_base_info_unref((GIBaseInfo *)struct_info);
- } else {
- PyGObject *gobject;
+ self->obj = return_arg.v_pointer;
- gobject = (PyGObject *) return_value;
- gobject->obj = return_arg.v_pointer;
+ if (g_object_is_floating(self->obj)) {
+ g_object_ref_sink(self->obj);
+ }
+ pygobject_register_wrapper((PyObject *)self);
- g_object_ref(gobject->obj);
- pygobject_register_wrapper(return_value);
- }
+ PyObject_GC_Track((PyObject *)self);
- g_base_info_unref(interface_info);
- } else {
- /* TODO */
- g_base_info_unref((GIBaseInfo *)return_info);
- PyErr_SetString(PyExc_NotImplementedError, "constructor return_tag != GI_TYPE_TAG_INTERFACE");
- return NULL;
- }
+ return_value = (PyObject *)self;
}
} else {
return_value = NULL;
diff --git a/girepository/btypes.py b/girepository/btypes.py
index 54b5268..f4673bd 100644
--- a/girepository/btypes.py
+++ b/girepository/btypes.py
@@ -19,200 +19,117 @@
import gobject
-import new
+from new import instancemethod
from . import repo
-
+from .repo import InterfaceInfo, ObjectInfo, StructInfo, EnumInfo
from .repository import repository
-class Callable(object):
-
- # Types of callables
- INSTANCE_METHOD = 'method'
- STATIC_METHOD = 'static'
- CLASS_METHOD = 'class'
- FUNTION = 'function'
- def __init__(self, info):
- self.info = info
- self.call_type = None
+def Function(info):
- def __call__(self, *args, **kwargs):
- # TODO: put the kwargs in their right positions
- totalInArgs = args + tuple(kwargs.values())
+ def function(*args):
+ return info.invoke(*args)
+ function.__info__ = info
+ function.__name__ = info.getName()
+ function.__module__ = info.getNamespace()
- retval = self.info.invoke(*totalInArgs)
+ return function
- if self.info.isConstructor():
- return None
- return retval
+class Field(object):
-class Function(Callable):
def __init__(self, info):
- Callable.__init__(self, info)
self.info = info
- self.static = True
-
- def __repr__(self):
- return "<function %s>" % (self.info.getName(),)
-
-class Method(Callable):
+ def __get__(self, instance, owner):
+ return self.info.getValue(instance)
- def __init__(self, info, className, call_type=Callable.INSTANCE_METHOD):
- Callable.__init__(self, info)
- self.object = None
- self.className = className
- self.call_type = call_type
- self.__name__ = info.getName()
- self.__module__ = info.getNamespace()
+ def __set__(self, instance, value):
+ return self.info.setValue(instance, value)
- def newType(self, retval, type_info=None):
- if type_info == None:
- type_info = self.info.getReturnType()
- info = type_info.getInterface()
- klass = getClass(info)
- obj = klass.__new__(klass)
- obj._object = retval
- return obj
+class GObjectIntrospectionMeta(gobject.GObjectMeta):
- #def __get__(self, instance, type):
- #if instance is None:
- #return self
-
- #def wrapper(*args, **kwargs):
- #return self(instance, *args, **kwargs)
-
- #return wrapper
-
- def __repr__(self):
- return "<method %s of %s.%s object>" % (
- self.__name__,
- self.__module__,
- self.className)
-
-class FieldDescriptor(object):
- def __init__(self, info):
- self._info = info
-
- def __get__(self, obj, klass=None):
- return self._info.getValue(obj)
-
- def __set__(self, obj, value):
- return self._info.setValue(obj, value)
-
-class PyBankMeta(gobject.GObjectMeta):
def __init__(cls, name, bases, dict_):
- gobject.GObjectMeta.__init__(cls, name, bases, dict_)
+ super(GObjectIntrospectionMeta, cls).__init__(name, bases, dict_)
if hasattr(cls, '__gtype__'):
repo.setObjectHasNewConstructor(cls.__gtype__)
- # Only set up the wrapper methods and fields in their base classes
- if name == cls.__info__.getName():
- needs_constructor = not '__init__' in dict_
- cls._setup_methods(needs_constructor)
+ # Only set up the wrapper methods and fields in their base classes.
+ if cls.__name__ == cls.__info__.getName():
+ if isinstance(cls.__info__, InterfaceInfo):
+ cls._setup_methods()
- if hasattr(cls.__info__, 'getFields'):
+ if isinstance(cls.__info__, ObjectInfo):
cls._setup_fields()
+ cls._setup_methods()
- def _setup_methods(cls, needs_constructor):
- info = cls.__info__
- constructors = []
- static_methods = []
- for method in info.getMethods():
- name = method.getName()
-
- if method.isConstructor():
- constructors.append(method)
- elif method.isMethod():
- func = Method(method, cls.__name__)
- setattr(cls, name, new.instancemethod(func, None, cls))
- else:
- static_methods.append(method)
-
- if hasattr(info, 'getInterfaces'):
- for interface in info.getInterfaces():
- for method in interface.getMethods():
- name = method.getName()
- if method.isMethod():
- func = Method(method, interface.getName())
- setattr(cls, name, new.instancemethod(func, None, cls))
- else:
- static_methods.append(method)
-
- winner = None
- if needs_constructor:
- if len(constructors) == 1:
- winner = constructors[0]
+ if isinstance(cls.__info__, StructInfo):
+ cls._setup_fields()
+ cls._setup_methods()
+
+ if isinstance(cls.__info__, EnumInfo):
+ cls._setup_values()
+
+ def _setup_methods(cls):
+ constructor_infos = []
+ method_infos = cls.__info__.getMethods()
+ if hasattr(cls.__info__, 'getInterfaces'):
+ method_infos += reduce(lambda x, y: x + y, [interface_info.getMethods() for interface_info in cls.__info__.getInterfaces()], ())
+
+ for method_info in method_infos:
+ name = method_info.getName()
+ function = Function(method_info)
+ if method_info.isMethod():
+ method = instancemethod(function, None, cls)
+ elif method_info.isConstructor():
+ method = classmethod(function)
else:
- for constructor in constructors:
- if constructor.getName() == 'new':
- winner = constructor
- break
-
- if winner is not None:
- func = Method(winner, cls.__name__, call_type=Method.CLASS_METHOD)
- func.__name__ = '__init__'
- func.__orig_name__ = winner.getName()
- cls.__init__ = new.instancemethod(func, None, cls)
- # TODO: do we want the constructor as a static method?
- #constructors.remove(winner)
-
- static_methods.extend(constructors)
- for static_method in static_methods:
- func = Method(static_method, cls.__name__, call_type=Method.STATIC_METHOD)
- setattr(cls, static_method.getName(), staticmethod(func))
+ method = staticmethod(function)
+ setattr(cls, name, method)
+
+ if method_info.isConstructor():
+ constructor_infos.append(method_info)
+
+ default_constructor_info = None
+ if len(constructor_infos) == 1:
+ (default_constructor_info,) = constructor_infos
+ else:
+ for constructor_info in constructor_infos:
+ if constructor_info.getName() == 'new':
+ default_constructor_info = constructor_info
+ break
+
+ if default_constructor_info is not None:
+ function = Function(default_constructor_info)
+ cls.__new__ = staticmethod(function)
+ # Override the initializer because of the constructor's arguments
+ cls.__init__ = lambda self, *args, **kwargs: super(cls, self).__init__()
def _setup_fields(cls):
- info = cls.__info__
- for field in info.getFields():
- name = field.getName().replace('-', '_')
- setattr(cls, name, FieldDescriptor(field))
-
-_classDict = {}
-
-def getClass(info):
- className = info.getName()
- namespaceName = info.getNamespace()
- fullName = namespaceName + '.' + className
-
- klass = _classDict.get(fullName)
- if klass is None:
- module = repository.get_module(info.getNamespace())
- klass = getattr(module, className)
- return klass
-
-def buildType(info, bases):
- className = info.getName()
- namespaceName = info.getNamespace()
- fullName = namespaceName + '.' + className
-
- if _classDict.has_key(fullName):
- return _classDict[fullName]
+ for field_info in cls.__info__.getFields():
+ name = field_info.getName().replace('-', '_')
+ setattr(cls, name, Field(field_info))
- namespace = {}
- namespace['__info__'] = info
- namespace['__module__'] = namespaceName
- newType = PyBankMeta(className, bases, namespace)
+ def _setup_values(cls):
+ for value_info in cls.__info__.getValues():
+ name = value_info.getName().upper()
+ setattr(cls, name, value_info.getValue())
- _classDict[fullName] = newType
- return newType
+class GIStruct(object):
-class BaseBlob(object):
- """Base class for Struct, Boxed and Union.
- """
- def __init__(self, buf=None):
- if buf is None:
- buf = self.__info__.newBuffer()
- self.__buffer__ = buf
+ def __init__(self, buffer=None):
+ if buffer is None:
+ buffer = self.__info__.newBuffer()
+ self.__buffer__ = buffer
def __eq__(self, other):
- for field in self.__info__.getFields():
- if getattr(self, field.getName()) != getattr(other, field.getName()):
+ for field_info in self.__info__.getFields():
+ name = field_info.getName()
+ if getattr(self, name) != getattr(other, name):
return False
return True
diff --git a/girepository/module.py b/girepository/module.py
index 6b6b875..d8a086f 100644
--- a/girepository/module.py
+++ b/girepository/module.py
@@ -20,19 +20,54 @@
import os
import gobject
-from gobject import GEnum
+from gobject import \
+ GObject, \
+ GInterface, \
+ GEnum
-from .btypes import Function, BaseBlob, buildType
-from .repo import EnumInfo, FunctionInfo, ObjectInfo, UnresolvedInfo, \
- InterfaceInfo, StructInfo, BoxedInfo
from .repository import repository
+from .btypes import \
+ GObjectIntrospectionMeta, \
+ GIStruct, \
+ Function
+from .repo import \
+ UnresolvedInfo, \
+ FunctionInfo, \
+ RegisteredTypeInfo, \
+ EnumInfo, \
+ ObjectInfo, \
+ InterfaceInfo, \
+ StructInfo, \
+ BoxedInfo
+
+
+def get_parent_for_object(object_info):
+ parent_object_info = object_info.getParent()
+
+ if not parent_object_info:
+ return object
+
+ namespace = parent_object_info.getNamespace()
+ if isinstance(parent_object_info, UnresolvedInfo):
+ # Import the module and try again.
+ __import__(namespace)
+ parent_object_info = object_info.getParent()
+
+ module = repository.get_module(namespace)
+ name = parent_object_info.getName()
+ # Workaround for gobject.Object.
+ if module == gobject and name == 'Object' or name == 'InitiallyUnowned':
+ return GObject
+
+ return getattr(module, name)
+
class DynamicModule(object):
+
def __init__(self, namespace, path):
self._namespace = namespace
self._path = path
repository.register(self, namespace, path)
- self.created()
@property
def __file__(self):
@@ -50,12 +85,53 @@ class DynamicModule(object):
return "<dyn-module %r from %r>" % (self._namespace, self._path)
def __getattr__(self, name):
- type_info = repository.get_by_name(self._namespace, name)
- if not type_info:
+ info = repository.get_by_name(self._namespace, name)
+ if not info:
raise AttributeError("%r object has no attribute %r" % (
self.__class__.__name__, name))
- value = self._create_attribute(name, type_info)
+ if isinstance(info, StructInfo):
+ # FIXME: This could be wrong for structures that are registered (like GValue or GClosure).
+ bases = (GIStruct,)
+ name = info.getName()
+ dict_ = {
+ '__info__': info,
+ '__module__': info.getNamespace()
+ }
+ value = GObjectIntrospectionMeta(name, bases, dict_)
+ elif isinstance(info, RegisteredTypeInfo):
+ # Check if there is already a Python wrapper.
+ gtype = info.getGType()
+ if gtype.pytype is not None:
+ self.__dict__[name] = gtype.pytype
+ return
+
+ # Create a wrapper.
+ if isinstance(info, ObjectInfo):
+ parent = get_parent_for_object(info)
+ bases = (parent,)
+ elif isinstance(info, InterfaceInfo):
+ bases = (GInterface,)
+ elif isinstance(info, EnumInfo):
+ bases = (GEnum,)
+ elif isinstance(info, BoxedInfo):
+ bases = (GBoxed,)
+ else:
+ raise NotImplementedError(info)
+
+ name = info.getName()
+ dict_ = {
+ '__info__': info,
+ '__module__': info.getNamespace(),
+ '__gtype__': gtype
+ }
+ value = GObjectIntrospectionMeta(name, bases, dict_)
+ gtype.pytype = value
+ elif isinstance(info, FunctionInfo):
+ value = Function(info)
+ else:
+ raise NotImplementedError(info)
+
self.__dict__[name] = value
return value
@@ -68,162 +144,3 @@ class DynamicModule(object):
r.append(type_info.getName())
return r
-
-
- # Override this in a subclass
-
- def created(self):
- pass
-
- # Private API
-
- def _create_attribute(self, attr, type_info):
- if isinstance(type_info, ObjectInfo):
- return self._create_object(type_info)
- elif isinstance(type_info, EnumInfo):
- return self._create_enum(type_info)
- elif isinstance(type_info, FunctionInfo):
- return self._create_function(type_info)
- elif isinstance(type_info, InterfaceInfo):
- return self._create_interface(type_info)
- elif isinstance(type_info, StructInfo) or \
- isinstance(type_info, BoxedInfo):
- return self._create_boxed(type_info)
- else:
- raise NotImplementedError(type_info)
-
- def _get_parent_for_object(self, object_info):
- parent_info = object_info.getParent()
-
- if isinstance(parent_info, UnresolvedInfo):
- namespace = parent_info.getNamespace()
- __import__(namespace)
- parent_info = object_info.getParent()
-
- if not parent_info:
- parent = object
- else:
- namespace = parent_info.getNamespace()
- module = repository.get_module(namespace)
- name = parent_info.getName()
- try:
- # Hack for gobject.Object
- if module == gobject and name == 'Object':
- name = 'GObject'
- parent = getattr(module, name)
- except AttributeError:
- return self._get_parent_for_object(parent_info)
-
- if parent is None:
- parent = object
- return parent
-
- def _create_object(self, object_info):
- name = object_info.getName()
-
- namespace = repository.get_c_prefix(object_info.getNamespace())
- full_name = namespace + name
- object_info.getGType()
- gtype = None
- try:
- gtype = gobject.GType.from_name(full_name)
- except RuntimeError:
- pass
- else:
- if gtype.pytype is not None:
- return gtype.pytype
- # Check if the klass is already created, eg
- # present in our namespace, this is necessary since we're
- # not always entering here through the __getattr__ hook.
- klass = self.__dict__.get(name)
- if klass:
- return klass
-
- parent = self._get_parent_for_object(object_info)
- klass = buildType(object_info, (parent,))
- if gtype is not None:
- klass.__gtype__ = gtype
- gtype.pytype = klass
- self.__dict__[name] = klass
-
- return klass
-
- def _create_enum(self, enum_info):
- ns = dict(__name__=enum_info.getName(),
- __module__=enum_info.getNamespace())
- for value in enum_info.getValues():
- ns[value.getName().upper()] = value.getValue()
- return type(enum_info.getName(), (GEnum,), ns)
-
- def _create_function(self, function_info):
- return Function(function_info)
-
- def _create_interface(self, interface_info):
- name = interface_info.getName()
-
- namespace = repository.get_c_prefix(interface_info.getNamespace())
- full_name = namespace + name
- interface_info.getGType()
- gtype = None
- try:
- gtype = gobject.GType.from_name(full_name)
- except RuntimeError:
- pass
- else:
- if gtype.pytype is not None:
- return gtype.pytype
- # Check if the klass is already created, eg
- # present in our namespace, this is necessary since we're
- # not always entering here through the __getattr__ hook.
- klass = self.__dict__.get(name)
- if klass:
- return klass
-
- bases = (gobject.GInterface,)
- klass = buildType(interface_info, bases)
- if gtype is not None:
- klass.__gtype__ = gtype
- gtype.pytype = klass
- interface_info.register()
- self.__dict__[name] = klass
-
- return klass
-
- def _create_boxed(self, boxed_info):
- name = boxed_info.getName()
-
- namespace = repository.get_c_prefix(boxed_info.getNamespace())
- full_name = namespace + name
-
- gtype = None
- try:
- gtype = gobject.GType.from_name(full_name)
- except RuntimeError:
- pass
- else:
- if gtype.pytype is not None:
- return gtype.pytype
-
- # Check if the klass is already created, eg
- # present in our namespace, this is necessary since we're
- # not always entering here through the __getattr__ hook.
- klass = self.__dict__.get(name)
- if klass:
- return klass
-
- bases = (BaseBlob,)
- if isinstance(boxed_info, BoxedInfo):
- bases += gobject.Boxed
-
- klass = buildType(boxed_info, bases)
-
- if gtype is None:
- gtype = boxed_info.getGType()
-
- klass.__gtype__ = gtype
- gtype.pytype = klass
-
- self.__dict__[name] = klass
-
- return klass
-
diff --git a/girepository/overrides/Gdk.py b/girepository/overrides/Gdk.py
index 304817b..94b0eaf 100644
--- a/girepository/overrides/Gdk.py
+++ b/girepository/overrides/Gdk.py
@@ -3,7 +3,10 @@ import sys
from girepository.module import DynamicModule
class GdkModule(DynamicModule):
- def created(self):
+
+ def __init__(self, *args):
+ super(GdkModule, self).__init__(*args)
+
initialized, argv = self.init_check(tuple(sys.argv))
if not initialized:
raise RuntimeError("Gdk couldn't be initialized")
diff --git a/girepository/overrides/Gtk.py b/girepository/overrides/Gtk.py
index a819183..51c93f8 100644
--- a/girepository/overrides/Gtk.py
+++ b/girepository/overrides/Gtk.py
@@ -3,7 +3,10 @@ import sys
from girepository.module import DynamicModule
class GtkModule(DynamicModule):
- def created(self):
+
+ def __init__(self, *args):
+ super(GtkModule, self).__init__(*args)
+
initialized, argv = self.init_check(tuple(sys.argv))
if not initialized:
raise RuntimeError("Gtk couldn't be initialized")
diff --git a/tests/test_girepository.py b/tests/test_girepository.py
index d489949..a9cbdb0 100644
--- a/tests/test_girepository.py
+++ b/tests/test_girepository.py
@@ -426,6 +426,9 @@ class TestGIEverything(unittest.TestCase):
self.assertRaises(TypeError, o.connect, 'invalid-signal', signal_handler)
self.assertRaises(TypeError, o.emit, 'invalid-signal')
+
+# Structures
+
def testStructA(self):
a = createStructA()
self.assertEquals(a.some_int, 3)
@@ -441,6 +444,9 @@ class TestGIEverything(unittest.TestCase):
a.clone(a_out)
self.assertEquals(a, a_out)
+ # Test instance checking by passing a wrong instance.
+ self.assertRaises(TypeError, Everything.TestStructA.clone, 'a', a_out)
+
def testStructB(self):
b = Everything.TestStructB()
b.some_int8 = 3
@@ -448,9 +454,9 @@ class TestGIEverything(unittest.TestCase):
b.nested_a = a
self.assertEquals(a, b.nested_a)
+ # Test assignment checking.
self.assertRaises(TypeError, setattr, b, 'nested_a', 'a')
- # FIXME: Doesn't work because there is no other GType than Void associated with non-boxed structures.
- #self.assertRaises(TypeError, setattr, b, 'nested_a', Everything.TestStructB())
+ self.assertRaises(TypeError, setattr, b, 'nested_a', Everything.TestStructB())
b_out = Everything.TestStructB()
b.clone(b_out)
@@ -479,6 +485,11 @@ class TestGIEverything(unittest.TestCase):
self.assertTrue(a.equals(a_out))
self.assertEquals(a, a_out)
+ # Test instance checking by passing a wrong instance.
+ self.assertRaises(TypeError, Everything.TestSimpleBoxedA.copy, 'a')
+ self.assertRaises(TypeError, Everything.TestSimpleBoxedA.copy, gobject.GObject())
+
+ # Test boxed as return value.
a_const = Everything.test_simple_boxed_a_const_return()
self.assertEquals(5, a_const.some_int)
self.assertEquals(6, a_const.some_int8)
@@ -499,58 +510,137 @@ class TestGIEverything(unittest.TestCase):
self.assertEquals(b, b_out)
- def testInterface(self):
- self.assertTrue(issubclass(Everything.TestInterface, gobject.GInterface))
- self.assertRaises(NotImplementedError, Everything.TestInterface)
- self.assertEquals(Everything.TestInterface.__gtype__.name, 'EverythingTestInterface')
+# GObject
+
+ def testObj(self):
+ # Test inheritance.
+ self.assertTrue(issubclass(Everything.TestObj, gobject.GObject))
+ self.assertEquals(Everything.TestObj.__gtype__, Everything.TestObj.__info__.getGType())
- def testConstructor(self):
- self.assertTrue(isinstance(Everything.TestObj("foo"), Everything.TestObj))
+ def testDefaultConstructor(self):
+ # Test instanciation.
+ obj = Everything.TestObj('foo')
+ self.assertTrue(isinstance(obj, Everything.TestObj))
+
+ # Test the argument count.
self.assertRaises(TypeError, Everything.TestObj)
- self.assertRaises(TypeError, Everything.TestObj.__init__, None, 'foo')
self.assertRaises(TypeError, Everything.TestObj, 'foo', 'bar')
- self.assertRaises(TypeError, Everything.TestObj, 42)
+
+ def testAlternateConstructor(self):
+ # Test instanciation.
+ obj = Everything.TestObj.new_from_file('foo')
+ self.assertTrue(isinstance(obj, Everything.TestObj))
+
+ obj = obj.new_from_file('foo')
+ self.assertTrue(isinstance(obj, Everything.TestObj))
+
+ # Test the argument count.
+ self.assertRaises(TypeError, Everything.TestObj.new_from_file)
+ self.assertRaises(TypeError, Everything.TestObj.new_from_file, 'foo', 'bar')
def testInstanceMethod(self):
- o = Everything.TestObj('foo')
- self.assertEquals(-1, o.instance_method())
- self.assertRaises(TypeError, o.instance_method, 'foo')
- self.assertRaises(TypeError, Everything.TestObj.instance_method, gobject.GObject())
+ obj = Everything.TestObj('foo')
- def testlVirtualMethod(self):
- o = Everything.TestObj('foo')
- self.assertEquals(42, o.do_matrix('matrix'))
- self.assertRaises(TypeError, o.do_matrix)
- self.assertRaises(TypeError, o.do_matrix, 'matrix', 'foo')
+ # Test call.
+ self.assertEquals(-1, obj.instance_method())
+
+ # Test argument count.
+ self.assertRaises(TypeError, obj.instance_method, 'foo')
+
+ # Test instance checking by passing a wrong instance.
+ obj = gobject.GObject()
+ self.assertRaises(TypeError, Everything.TestObj.instance_method)
+
+ def testVirtualMethod(self):
+ obj = Everything.TestObj('foo')
+
+ # Test call.
+ self.assertEquals(42, obj.do_matrix('matrix'))
+
+ # Test argument count.
+ self.assertRaises(TypeError, obj.do_matrix)
+ self.assertRaises(TypeError, obj.do_matrix, 'matrix', 'foo')
self.assertRaises(TypeError, Everything.TestObj.do_matrix, 'matrix')
- self.assertRaises(TypeError, Everything.TestObj.do_matrix, None, 'matrix')
+
+ # Test instance checking by passing a wrong instance.
+ obj = gobject.GObject()
+ self.assertRaises(TypeError, Everything.TestObj.do_matrix, obj, 'matrix')
def testStaticMethod(self):
+ obj = Everything.TestObj('foo')
+
+ # Test calls.
self.assertEquals(42, Everything.TestObj.static_method(42))
+ self.assertEquals(42, obj.static_method(42))
+
+ # Test argument count.
self.assertRaises(TypeError, Everything.TestObj.static_method)
- self.assertRaises(TypeError, Everything.TestObj.static_method, 'foo')
self.assertRaises(TypeError, Everything.TestObj.static_method, 'foo', 'bar')
- o = Everything.TestObj('foo')
- self.assertEquals(42, o.static_method(42))
+
+
+# Inheritance
def testSubObj(self):
+ # Test subclassing.
self.assertTrue(issubclass(Everything.TestSubObj, Everything.TestObj))
+
+ # Test static method.
self.assertEquals(42, Everything.TestSubObj.static_method(42))
- self.assertRaises(TypeError, Everything.TestSubObj, 'foo')
+ # Test constructor.
+ subobj = Everything.TestSubObj()
+ self.assertTrue(isinstance(subobj, Everything.TestSubObj))
+ self.assertTrue(isinstance(subobj, Everything.TestObj))
+
+ # Test alternate constructor.
+ subobj = Everything.TestSubObj.new_from_file('foo')
+ self.assertTrue(isinstance(subobj, Everything.TestSubObj))
+
+ # Test method inheritance.
+ self.assertTrue(hasattr(subobj, 'set_bare'))
+ self.assertEquals(42, subobj.do_matrix('foo'))
+
+ # Test method overriding.
+ self.assertEquals(0, subobj.instance_method())
+
+ # Test instance checking by passing a wrong instance.
+ obj = Everything.TestObj('foo')
+ self.assertRaises(TypeError, Everything.TestSubObj.instance_method, obj)
- s = Everything.TestSubObj()
- self.assertTrue(isinstance(s, Everything.TestSubObj))
- self.assertTrue(isinstance(s, Everything.TestObj))
+ def testPythonSubObj(self):
+ class PythonSubObj(Everything.TestObj):
+ def __new__(cls):
+ return super(PythonSubObj, cls).__new__(cls, 'foo')
+ gobject.type_register(PythonSubObj)
- self.assertTrue(hasattr(s, 'set_bare'))
+ # Test subclassing.
+ self.assertTrue(issubclass(PythonSubObj, Everything.TestObj))
+ self.assertTrue(PythonSubObj.__gtype__ != Everything.TestObj.__gtype__)
+ self.assertTrue(PythonSubObj.__gtype__.is_a(Everything.TestObj.__gtype__))
- self.assertEquals(42, s.do_matrix('foo'))
+ # Test static method.
+ self.assertEquals(42, PythonSubObj.static_method(42))
- self.assertTrue(hasattr(s, 'unset_bare'))
+ # Test instanciation.
+ subobj = PythonSubObj()
+ self.assertTrue(isinstance(subobj, PythonSubObj))
- self.assertEquals(0, s.instance_method())
- self.assertRaises(TypeError, Everything.TestObj.instance_method, Everything.TestObj('foo'))
+ subobj = PythonSubObj.new_from_file('foo')
+ self.assertTrue(isinstance(subobj, PythonSubObj))
+
+ # Test method inheritance.
+ self.assertTrue(hasattr(subobj, 'set_bare'))
+ self.assertEquals(42, subobj.do_matrix('foo'))
+
+
+# Interface
+
+ def testInterface(self):
+ self.assertTrue(issubclass(Everything.TestInterface, gobject.GInterface))
+ self.assertEquals(Everything.TestInterface.__gtype__.name, 'EverythingTestInterface')
+
+ # Test instanciation.
+ self.assertRaises(NotImplementedError, Everything.TestInterface)
if __name__ == '__main__':
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]