summaryrefslogtreecommitdiff
path: root/gi/module.py
diff options
context:
space:
mode:
Diffstat (limited to 'gi/module.py')
-rw-r--r--gi/module.py167
1 files changed, 167 insertions, 0 deletions
diff --git a/gi/module.py b/gi/module.py
new file mode 100644
index 00000000..1a549712
--- /dev/null
+++ b/gi/module.py
@@ -0,0 +1,167 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# vim: tabstop=4 shiftwidth=4 expandtab
+#
+# Copyright (C) 2007-2009 Johan Dahlin <johan@gnome.org>
+#
+# module.py: dynamic module for introspected libraries.
+#
+# 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
+
+from __future__ import absolute_import
+
+import os
+import gobject
+
+from ._gi import \
+ Repository, \
+ FunctionInfo, \
+ RegisteredTypeInfo, \
+ EnumInfo, \
+ ObjectInfo, \
+ InterfaceInfo, \
+ ConstantInfo, \
+ StructInfo, \
+ Struct, \
+ enum_add, \
+ flags_add
+from .types import \
+ GObjectMeta, \
+ StructMeta, \
+ Boxed, \
+ Function
+
+repository = Repository.get_default()
+
+
+def get_parent_for_object(object_info):
+ parent_object_info = object_info.get_parent()
+
+ if not parent_object_info:
+ return object
+
+ namespace = parent_object_info.get_namespace()
+ name = parent_object_info.get_name()
+
+ # Workaround for GObject.Object and GObject.InitiallyUnowned.
+ if namespace == 'GObject' and name == 'Object' or name == 'InitiallyUnowned':
+ return gobject.GObject
+
+ module = __import__('gi.repository.%s' % namespace, fromlist=[name])
+ return getattr(module, name)
+
+def get_interfaces_for_object(object_info):
+ interfaces = []
+ for interface_info in object_info.get_interfaces():
+ namespace = interface_info.get_namespace()
+ name = interface_info.get_name()
+
+ module = __import__('gi.repository.%s' % namespace, fromlist=[name])
+ interfaces.append(getattr(module, name))
+ return interfaces
+
+
+class DynamicModule(object):
+
+ def __str__(self):
+ path = repository.get_typelib_path(self.__namespace__)
+ return "<dynamic module %r from %r>" % (self.__name__, path)
+
+ def __getattr__(self, name):
+ if self.__dict__.has_key(name):
+ return self.__dict__[name]
+
+ info = repository.find_by_name(self.__namespace__, name)
+ if not info:
+ raise AttributeError("%r object has no attribute %r" % (
+ self.__class__.__name__, name))
+
+ if isinstance(info, EnumInfo):
+ g_type = info.get_g_type()
+ value = g_type.pytype
+
+ if value is None:
+ if g_type.is_a(gobject.TYPE_ENUM):
+ value = enum_add(g_type)
+ else:
+ value = flags_add(g_type)
+
+ value.__info__ = info
+ value.__module__ = info.get_namespace()
+
+ for value_info in info.get_values():
+ name = value_info.get_name().upper()
+ setattr(value, name, value(value_info.get_value()))
+
+ elif isinstance(info, RegisteredTypeInfo):
+ g_type = info.get_g_type()
+
+ # Check if there is already a Python wrapper.
+ if g_type != gobject.TYPE_NONE:
+ type_ = g_type.pytype
+ if type_ is not None:
+ self.__dict__[name] = type_
+ return type_
+
+ # Create a wrapper.
+ if isinstance(info, ObjectInfo):
+ parent = get_parent_for_object(info)
+ interfaces = tuple(interface for interface in get_interfaces_for_object(info)
+ if not issubclass(parent, interface))
+ bases = (parent,) + interfaces
+ metaclass = GObjectMeta
+ elif isinstance(info, InterfaceInfo):
+ bases = (gobject.GInterface,)
+ metaclass = GObjectMeta
+ elif isinstance(info, StructInfo):
+ if g_type.is_a(gobject.TYPE_BOXED):
+ bases = (Boxed,)
+ elif g_type.is_a(gobject.TYPE_POINTER) or g_type == gobject.TYPE_NONE:
+ bases = (Struct,)
+ else:
+ raise TypeError, "unable to create a wrapper for %s.%s" % (info.get_namespace(), info.get_name())
+ metaclass = StructMeta
+ else:
+ raise NotImplementedError(info)
+
+ name = info.get_name()
+ dict_ = {
+ '__info__': info,
+ '__module__': self.__namespace__,
+ '__gtype__': g_type
+ }
+ value = metaclass(name, bases, dict_)
+
+ # Register the new Python wrapper.
+ if g_type != gobject.TYPE_NONE:
+ g_type.pytype = value
+
+ elif isinstance(info, FunctionInfo):
+ value = Function(info)
+ elif isinstance(info, ConstantInfo):
+ value = info.get_value()
+ else:
+ raise NotImplementedError(info)
+
+ self.__dict__[name] = value
+ return value
+
+ @property
+ def __members__(self):
+ r = []
+ for type_info in repository.get_infos(self.__namespace__):
+ r.append(type_info.get_name())
+ return r
+