summaryrefslogtreecommitdiffstats
path: root/girepository/module.py
diff options
context:
space:
mode:
Diffstat (limited to 'girepository/module.py')
-rw-r--r--girepository/module.py224
1 files changed, 224 insertions, 0 deletions
diff --git a/girepository/module.py b/girepository/module.py
new file mode 100644
index 0000000..2a87816
--- /dev/null
+++ b/girepository/module.py
@@ -0,0 +1,224 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+#
+# Copyright (C) 2007 Johan Dahlin <johan@gnome.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+import os
+
+import gobject
+from gobject import GEnum
+
+from .btypes import Function, BaseBlob, buildType
+from .repo import EnumInfo, FunctionInfo, ObjectInfo, UnresolvedInfo, \
+ InterfaceInfo, StructInfo, BoxedInfo
+from .repository import repository
+
+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):
+ return self._namespace
+
+ @property
+ def __name__(self):
+ return self._namespace
+
+ @property
+ def __path__(self):
+ return [os.path.dirname(self.__file__)]
+
+ def __repr__(self):
+ 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:
+ raise AttributeError("%r object has no attribute %r" % (
+ self.__class__.__name__, name))
+
+ value = self._create_attribute(name, type_info)
+ self.__dict__[name] = value
+ return value
+
+ @property
+ def __members__(self):
+ r = []
+ for type_info in repository.get_infos(self._namespace):
+ if type_info is None:
+ continue
+ 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
+ boxed_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 = (BaseBlob,)
+ if isinstance(boxed_info, BoxedInfo):
+ bases += gobject.Boxed
+
+ klass = buildType(boxed_info, bases)
+ if gtype is not None:
+ klass.__gtype__ = gtype
+ gtype.pytype = klass
+ self.__dict__[name] = klass
+
+ return klass
+