Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu@sugarlabs.org>2009-05-12 08:29:50 (GMT)
committer Tomeu Vizoso <tomeu@sugarlabs.org>2009-05-12 08:29:50 (GMT)
commit9576e2d88899d4dfc9c73eab333ac9819113f985 (patch)
tree4fc7dcd151aaf392e2e068f987a576196c6f7abc
parentf80b39aa1b969c7e7d4a8088e7fb55c755bace7d (diff)
Refactor type creation, use a metaclass derived from GObjectMeta
-rw-r--r--bank/btypes.py169
-rw-r--r--bank/module.py15
2 files changed, 63 insertions, 121 deletions
diff --git a/bank/btypes.py b/bank/btypes.py
index a07f5f4..c0ffa1c 100644
--- a/bank/btypes.py
+++ b/bank/btypes.py
@@ -116,24 +116,10 @@ class Callable(object):
retval = self.info.invoke(*args)
if self.info.isConstructor():
- if retval is None:
- raise AssertionError(
- "Invoked constructor %s.%s.%s returned NULL " % (
- self.__module__, self.className, self.info.getName()))
- print "mec %r" % retval
- return retval
-
- if type(retval).__name__ == 'PyCObject':
- rinfo = self.info.getReturnType()
- tag = rinfo.getTag()
- if tag == repo.TYPE_TAG_INTERFACE:
- retval = self.newType(retval)
- else:
- raise NotImplementedError
+ return None
return retval
-
class Function(Callable):
def __init__(self, info):
Callable.__init__(self, info)
@@ -179,6 +165,55 @@ class Method(Callable):
self.__module__,
self.className)
+class PyBankMeta(gobject.GObjectMeta):
+ def __init__(cls, name, bases, dict_):
+ print 'PyBankMeta() %r' % ((cls, name, bases, dict_),)
+
+ gobject.GObjectMeta.__init__(cls, name, bases, dict_)
+
+ needs_constructor = not '__init__' in dict_
+ cls._setup_methods(needs_constructor)
+
+ print 'dir(%s): %r' % (name, dir(cls))
+
+ 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)
+
+ winner = None
+ if needs_constructor:
+ if len(constructors) == 1:
+ winner = constructors[0]
+ 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)
+ print 'setting up %s as constructor of %s' % (winner.getName(), cls.__name__)
+ #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))
+
_classDict = {}
def getClass(info):
@@ -192,30 +227,7 @@ def getClass(info):
klass = getattr(module, className)
return klass
-def setupConstructors(className, cls, constructors):
- if not constructors:
- return
-
- if len(constructors) == 1:
- winner = constructors[0]
- else:
- winner = None
- for constructor in constructors:
- if constructor.getName() == 'new':
- winner = constructor
- break
-
- if winner != None:
- func = Method(winner, className, call_type=Method.CLASS_METHOD)
- cls.__init__ = func
- func.__name__ = "__init__"
- constructors.remove(winner)
-
- for constructor in constructors:
- func = Method(constructor, className, call_type=Method.STATIC_METHOD)
- setattr(cls, constructor.getName(), staticmethod(func))
-
-def buildClass(info, bases):
+def buildType(info, bases):
className = info.getName()
namespaceName = info.getNamespace()
fullName = namespaceName + '.' + className
@@ -226,51 +238,12 @@ def buildClass(info, bases):
namespace = {}
namespace['__info__'] = info
namespace['__module__'] = namespaceName
- newType = type(className, bases, namespace)
-
- constructors = []
- for method in info.getMethods():
- if method.isConstructor():
- constructors.append(method)
- elif method.isMethod():
- methodName = method.getName()
- setattr(newType, methodName, new.instancemethod(Method(method, className),
- None, newType))
- else: # probably a static method
- func = Method(method, className, call_type=Method.STATIC_METHOD)
- setattr(newType, method.getName(), staticmethod(func))
-
- setupConstructors(className, newType, constructors)
+ newType = PyBankMeta(className, bases, namespace)
_classDict[fullName] = newType
return newType
-def buildInterface(info):
- className = info.getName()
- namespaceName = info.getNamespace()
- fullName = namespaceName + '.' + className
-
- if _classDict.has_key(fullName):
- return _classDict[fullName]
-
- namespace = {}
- namespace['__info__'] = info
- namespace['__module__'] = namespaceName
- newType = type(className, (gobject.GInterface,), namespace)
-
- for method in info.getMethods():
- if method.isMethod():
- methodName = method.getName()
- setattr(newType, methodName, new.instancemethod(Method(method, className),
- None, newType))
- else:
- raise ValueError('Interfaces can only have regular methods')
-
- _classDict[fullName] = newType
-
- return newType
-
class BaseBlob(object):
"""Base class for Struct, Boxed and Union.
"""
@@ -283,7 +256,7 @@ class BaseBlob(object):
return self.__info__.getValue(self.__dict__['__buffer__'], name)
def __setattr__(self, name, value):
- print "__setattr__ %r %r" % (name, value)
+ print "__setattr__ %r %r %r" % (self, name, value)
self.__info__.setValue(self.__dict__['__buffer__'], name, value)
def __eq__(self, other):
@@ -292,39 +265,3 @@ class BaseBlob(object):
return False
return True
-def buildBoxed(info):
- className = info.getName()
- namespaceName = info.getNamespace()
- fullName = namespaceName + '.' + className
-
- if _classDict.has_key(fullName):
- return _classDict[fullName]
-
- namespace = {}
- namespace['__info__'] = info
- namespace['__module__'] = namespaceName
-
- bases = (BaseBlob,)
- if isinstance(info, repo.BoxedInfo):
- bases += gobject.Boxed
-
- newType = type(className, bases, namespace)
-
- constructors = []
- for method in info.getMethods():
- if method.isConstructor():
- constructors.append(method)
- elif method.isMethod():
- methodName = method.getName()
- setattr(newType, methodName, new.instancemethod(Method(method, className),
- None, newType))
- else: # probably a static method
- func = Method(method, className, call_type=Method.STATIC_METHOD)
- setattr(newType, method.getName(), staticmethod(func))
-
- setupConstructors(className, newType, constructors)
-
- _classDict[fullName] = newType
-
- return newType
-
diff --git a/bank/module.py b/bank/module.py
index 32d1986..65deea1 100644
--- a/bank/module.py
+++ b/bank/module.py
@@ -22,9 +22,9 @@ import os
import gobject
from gobject import GEnum
-from .btypes import Function, buildClass, buildInterface, buildBoxed
+from .btypes import Function, BaseBlob, buildType
from .repo import EnumInfo, FunctionInfo, ObjectInfo, UnresolvedInfo, \
- InterfaceInfo, StructInfo
+ InterfaceInfo, StructInfo, BoxedInfo
from .repository import repository
class DynamicModule(object):
@@ -140,7 +140,7 @@ class DynamicModule(object):
return klass
parent = self._get_parent_for_object(object_info)
- klass = buildClass(object_info, (parent,))
+ klass = buildType(object_info, (parent,))
if gtype is not None:
gtype.pytype = klass
self.__dict__[name] = klass
@@ -178,7 +178,8 @@ class DynamicModule(object):
if klass:
return klass
- klass = buildInterface(interface_info)
+ bases = (gobject.GInterface,)
+ klass = buildType(interface_info, bases)
if gtype is not None:
klass.__gtype__ = gtype
gtype.pytype = klass
@@ -207,7 +208,11 @@ class DynamicModule(object):
if klass:
return klass
- klass = buildBoxed(boxed_info)
+ bases = (BaseBlob,)
+ if isinstance(boxed_info, BoxedInfo):
+ bases += gobject.Boxed
+
+ klass = buildType(boxed_info, bases)
if gtype is not None:
gtype.pytype = klass
self.__dict__[name] = klass