diff options
Diffstat (limited to 'gi')
-rw-r--r-- | gi/Makefile.in | 3 | ||||
-rw-r--r-- | gi/gimodule.c | 2 | ||||
-rw-r--r-- | gi/module.py | 22 | ||||
-rw-r--r-- | gi/overrides/GIMarshallingTests.py | 2 | ||||
-rw-r--r-- | gi/overrides/Gdk.py | 2 | ||||
-rw-r--r-- | gi/overrides/Gtk.py | 548 | ||||
-rw-r--r-- | gi/overrides/Makefile.in | 3 | ||||
-rw-r--r-- | gi/overrides/__init__.py | 43 | ||||
-rw-r--r-- | gi/pygi-argument.c | 17 | ||||
-rw-r--r-- | gi/pygi-foreign-cairo.c | 62 | ||||
-rw-r--r-- | gi/pygi-foreign.c | 5 | ||||
-rw-r--r-- | gi/pygi-info.c | 136 | ||||
-rw-r--r-- | gi/pygi-info.h | 7 | ||||
-rw-r--r-- | gi/pygi-invoke.c | 25 | ||||
-rw-r--r-- | gi/pygi.h | 12 | ||||
-rw-r--r-- | gi/repository/Makefile.in | 3 | ||||
-rw-r--r-- | gi/types.py | 10 |
17 files changed, 828 insertions, 74 deletions
diff --git a/gi/Makefile.in b/gi/Makefile.in index 1aecd0a..f0dd624 100644 --- a/gi/Makefile.in +++ b/gi/Makefile.in @@ -244,6 +244,8 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLATFORM = @PLATFORM@ PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ PYCAIRO_LIBS = @PYCAIRO_LIBS@ @@ -301,7 +303,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ diff --git a/gi/gimodule.c b/gi/gimodule.c index 89caf4e..f7624ae 100644 --- a/gi/gimodule.c +++ b/gi/gimodule.c @@ -328,7 +328,7 @@ PYGLIB_MODULE_START(_gi, "_gi") _pygi_boxed_register_types (module); _pygi_argument_init(); - api = PyCObject_FromVoidPtr ( (void *) &CAPI, NULL); + api = PYGLIB_CPointer_WrapPointer ( (void *) &CAPI, "gi._API"); if (api == NULL) { return; } diff --git a/gi/module.py b/gi/module.py index 819fcc6..c7b6557 100644 --- a/gi/module.py +++ b/gi/module.py @@ -25,6 +25,8 @@ from __future__ import absolute_import import os import gobject +from .overrides import registry + from ._gi import \ Repository, \ FunctionInfo, \ @@ -47,7 +49,6 @@ from .types import \ repository = Repository.get_default() - def get_parent_for_object(object_info): parent_object_info = object_info.get_parent() @@ -85,6 +86,7 @@ class IntrospectionModule(object): self.__name__ = 'gi.repository.' + namespace repository.require(self._namespace, self.version) + self.__path__ = repository.get_typelib_path(self._namespace) if self.version is None: self.version = repository.get_version(self._namespace) @@ -172,6 +174,9 @@ class IntrospectionModule(object): path = repository.get_typelib_path(self._namespace) return "<IntrospectionModule %r from %r>" % (self._namespace, path) + def __dir__ (self): + attribs_list = repository.get_infos(self._namespace) + return list(map(lambda x: x.get_name(), attribs_list)) class DynamicGObjectModule(IntrospectionModule): """Wrapper for the GObject module @@ -222,6 +227,7 @@ class DynamicModule(object): overrides_modules = __import__('gi.overrides', fromlist=[self._namespace]) self._overrides_module = getattr(overrides_modules, self._namespace, None) + self.__path__ = repository.get_typelib_path(self._namespace) def __getattr__(self, name): if self.introspection_module is None: @@ -231,5 +237,19 @@ class DynamicModule(object): override_exports = getattr(self._overrides_module, '__all__', ()) if name in override_exports: return getattr(self._overrides_module, name, None) + else: + # check the registry just in case the module hasn't loaded yet + # TODO: Only gtypes are registered in the registry right now + # but it would be nice to register all overrides and + # get rid of the module imports. We might actually see a + # speedup. + key = '%s.%s' % (self._namespace, name) + if key in registry: + return registry[key] return getattr(self.introspection_module, name) + + def __dir__ (self): + repository.require(self._namespace, self._version) + attribs_list = repository.get_infos(self._namespace) + return list(map(lambda x: x.get_name(), attribs_list)) diff --git a/gi/overrides/GIMarshallingTests.py b/gi/overrides/GIMarshallingTests.py index ee01495..25a882f 100644 --- a/gi/overrides/GIMarshallingTests.py +++ b/gi/overrides/GIMarshallingTests.py @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA -from ..types import override +from ..overrides import override from ..importer import modules GIMarshallingTests = modules['GIMarshallingTests'].introspection_module diff --git a/gi/overrides/Gdk.py b/gi/overrides/Gdk.py index 23a9d8e..08141d7 100644 --- a/gi/overrides/Gdk.py +++ b/gi/overrides/Gdk.py @@ -19,7 +19,7 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA -from ..types import override +from ..overrides import override from ..importer import modules Gdk = modules['Gdk'].introspection_module diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py index 1f6901c..a2f38ac 100644 --- a/gi/overrides/Gtk.py +++ b/gi/overrides/Gtk.py @@ -23,7 +23,7 @@ import sys import gobject from gi.repository import Gdk from gi.repository import GObject -from ..types import override +from ..overrides import override from ..importer import modules if sys.version_info >= (3, 0): @@ -36,6 +36,44 @@ else: Gtk = modules['Gtk'].introspection_module __all__ = [] +class Widget(Gtk.Widget): + + def translate_coordinates(self, dest_widget, src_x, src_y): + success, dest_x, dest_y = super(Widget, self).translate_coordinates( + dest_widget, src_x, src_y) + if success: + return (dest_x, dest_y,) + +Widget = override(Widget) +__all__.append('Widget') + +class Container(Gtk.Container, Widget): + + def get_focus_chain(self): + success, widgets = super(Container, self).get_focus_chain() + if success: + return widgets + +Container = override(Container) +__all__.append('Container') + +class Editable(Gtk.Editable): + + def insert_text(self, text, position): + pos = super(Editable, self).insert_text(text, -1, position) + + return pos + + def get_selection_bounds(self): + success, start_pos, end_pos = super(Editable, self).get_selection_bounds() + if success: + return (start_pos, end_pos,) + else: + return tuple() + +Editable = override(Editable) +__all__.append("Editable") + class ActionGroup(Gtk.ActionGroup): def add_actions(self, entries, user_data=None): """ @@ -202,6 +240,16 @@ class UIManager(Gtk.UIManager): UIManager = override(UIManager) __all__.append('UIManager') +class ComboBox(Gtk.ComboBox, Container): + + def get_active_iter(self): + success, aiter = super(ComboBox, self).get_active_iter() + if success: + return aiter + +ComboBox = override(ComboBox) +__all__.append('ComboBox') + class Builder(Gtk.Builder): def connect_signals(self, obj_or_map): @@ -252,10 +300,24 @@ class Builder(Gtk.Builder): Builder = override(Builder) __all__.append('Builder') -class Dialog(Gtk.Dialog): - def __init__(self, title=None, parent=None, flags=0, buttons=None): - Gtk.Dialog.__init__(self) +class Dialog(Gtk.Dialog, Container): + + def __init__(self, + title=None, + parent=None, + flags=0, + buttons=None, + _buttons_property=None, + **kwds): + + # buttons is overloaded by PyGtk so we have to do the same here + # this breaks some subclasses of Dialog so add a _buttons_property + # keyword to work around this + if _buttons_property is not None: + kwds['buttons'] = _buttons_property + + Gtk.Dialog.__init__(self, **kwds) if title: self.set_title(title) if parent: @@ -272,7 +334,7 @@ class Dialog(Gtk.Dialog): except AttributeError: pass - if buttons: + if buttons is not None: self.add_buttons(*buttons) def add_buttons(self, *args): @@ -287,15 +349,14 @@ class Dialog(Gtk.Dialog): will add "Open" and "Close" buttons to dialog. """ - - def buttons(b): + def _button(b): while b: t, r = b[0:2] b = b[2:] yield t, r try: - for text, response in buttons(args): + for text, response in _button(args): self.add_button(text, response) except (IndexError): raise TypeError('Must pass an even number of arguments') @@ -303,6 +364,124 @@ class Dialog(Gtk.Dialog): Dialog = override(Dialog) __all__.append('Dialog') +class MessageDialog(Gtk.MessageDialog, Dialog): + def __init__(self, + parent=None, + flags=0, + type=Gtk.MessageType.INFO, + buttons=Gtk.ButtonsType.NONE, + message_format=None, + **kwds): + + if message_format != None: + kwds['text'] = message_format + Gtk.MessageDialog.__init__(self, + _buttons_property=buttons, + **kwds) + Dialog.__init__(self, parent=parent, flags=flags) + +MessageDialog = override(MessageDialog) +__all__.append('MessageDialog') + +class AboutDialog(Gtk.AboutDialog, Dialog): + def __init__(self, **kwds): + Gtk.AboutDialog.__init__(self, **kwds) + Dialog.__init__(self) + +AboutDialog = override(AboutDialog) +__all__.append('AboutDialog') + +class ColorSelectionDialog(Gtk.ColorSelectionDialog, Dialog): + def __init__(self, title=None, **kwds): + Gtk.ColorSelectionDialog.__init__(self, **kwds) + Dialog.__init__(self, title=title) + +ColorSelectionDialog = override(ColorSelectionDialog) +__all__.append('ColorSelectionDialog') + +class FileChooserDialog(Gtk.FileChooserDialog, Dialog): + def __init__(self, + title=None, + parent=None, + action=Gtk.FileChooserAction.OPEN, + buttons=None, + **kwds): + Gtk.FileChooserDialog.__init__(self, + action=action, + **kwds) + Dialog.__init__(self, + title=title, + parent=parent, + buttons=buttons) + +FileChooserDialog = override(FileChooserDialog) +__all__.append('FileChooserDialog') + +class FontSelectionDialog(Gtk.FontSelectionDialog, Dialog): + def __init__(self, title=None, **kwds): + Gtk.FontSelectionDialog.__init__(self, **kwds) + Dialog.__init__(self, title=title) + +FontSelectionDialog = override(FontSelectionDialog) +__all__.append('FontSelectionDialog') + +class RecentChooserDialog(Gtk.RecentChooserDialog, Dialog): + def __init__(self, + title=None, + parent=None, + manager=None, + buttons=None, + **kwds): + + Gtk.RecentChooserDialog.__init__(self, recent_manager=manager, **kwds) + Dialog.__init__(self, + title=title, + parent=parent, + buttons=buttons) + +RecentChooserDialog = override(RecentChooserDialog) +__all__.append('RecentChooserDialog') + +class IconView(Gtk.IconView): + + def get_item_at_pos(self, x, y): + success, path, cell = super(IconView, self).get_item_at_pos(x, y) + if success: + return (path, cell,) + + def get_visible_range(self): + success, start_path, end_path = super(IconView, self).get_visible_range() + if success: + return (start_path, end_path,) + + def get_dest_item_at_pos(self, drag_x, drag_y): + success, path, pos = super(IconView, self).get_dest_item_at_pos(drag_x, drag_y) + if success: + return path, pos + +IconView = override(IconView) +__all__.append('IconView') + +class IMContext(Gtk.IMContext): + + def get_surrounding(self): + success, text, cursor_index = super(IMContext, self).get_surrounding() + if success: + return (text, cursor_index,) + +IMContext = override(IMContext) +__all__.append('IMContext') + +class RecentInfo(Gtk.RecentInfo): + + def get_application_info(self, app_name): + success, app_exec, count, time = super(RecentInfo, self).get_application_info(app_name) + if success: + return (app_exec, count, time,) + +RecentInfo = override(RecentInfo) +__all__.append('RecentInfo') + class TextBuffer(Gtk.TextBuffer): def _get_or_create_tag_table(self): table = self.get_tag_table() @@ -351,23 +530,121 @@ class TextBuffer(Gtk.TextBuffer): length = len(text) Gtk.TextBuffer.insert_at_cursor(self, text, length) + def get_selection_bounds(self): + success, start, end = super(TextBuffer, self).get_selection_bounds(string, + flags, limit) + return (start, end) + TextBuffer = override(TextBuffer) __all__.append('TextBuffer') +class TextIter(Gtk.TextIter): + + def forward_search(self, string, flags, limit): + success, match_start, match_end = super(TextIter, self).forward_search(string, + flags, limit) + return (match_start, match_end,) + + def backward_search(self, string, flags, limit): + success, match_start, match_end = super(TextIter, self).backward_search(string, + flags, limit) + return (match_start, match_end,) + +TextIter = override(TextIter) +__all__.append('TextIter') + class TreeModel(Gtk.TreeModel): def __len__(self): return self.iter_n_children(None) -TreeModel = override(TreeModel) -__all__.append('TreeModel') + def __bool__(self): + return True + + # alias for Python 2.x object protocol + __nonzero__ = __bool__ + + def __getitem__(self, key): + if isinstance(key, Gtk.TreeIter): + return TreeModelRow(self, key) + elif isinstance(key, int) and key < 0: + index = len(self) + key + if index < 0: + raise IndexError("row index is out of bounds: %d" % key) + try: + aiter = self.get_iter(index) + except ValueError: + raise IndexError("could not find tree path '%s'" % key) + return TreeModelRow(self, aiter) + else: + try: + aiter = self.get_iter(key) + except ValueError: + raise IndexError("could not find tree path '%s'" % key) + return TreeModelRow(self, aiter) -class ListStore(Gtk.ListStore, TreeModel): - def __init__(self, *column_types): - Gtk.ListStore.__init__(self) - self.set_column_types(column_types) + def __iter__(self): + return TreeModelRowIter(self, self.get_iter_first()) - def append(self, row): - treeiter = Gtk.ListStore.append(self) + def get_iter(self, path): + if isinstance(path, Gtk.TreePath): + pass + elif isinstance(path, (int, str,)): + path = self._tree_path_from_string(str(path)) + elif isinstance(path, tuple): + path_str = ":".join(str(val) for val in path) + path = self._tree_path_from_string(path_str) + else: + raise TypeError("tree path must be one of Gtk.TreeIter, Gtk.TreePath, \ + int, str or tuple, not %s" % type(path).__name__) + + success, aiter = super(TreeModel, self).get_iter(path) + if not success: + raise ValueError("invalid tree path '%s'" % path) + return aiter + + def _tree_path_from_string(self, path): + if len(path) == 0: + raise TypeError("could not parse subscript '%s' as a tree path" % path) + try: + return TreePath.new_from_string(path) + except TypeError: + raise TypeError("could not parse subscript '%s' as a tree path" % path) + + def get_iter_first(self): + success, aiter = super(TreeModel, self).get_iter_first() + if success: + return aiter + + def get_iter_from_string(self, path_string): + success, aiter = super(TreeModel, self).get_iter_from_string(path_string) + if not success: + raise ValueError("invalid tree path '%s'" % path_string) + return aiter + + def iter_next(self, aiter): + next_iter = aiter.copy() + success = super(TreeModel, self).iter_next(next_iter) + if success: + return next_iter + + def iter_children(self, aiter): + success, child_iter = super(TreeModel, self).iter_children(aiter) + if success: + return child_iter + + def iter_nth_child(self, parent, n): + success, child_iter = super(TreeModel, self).iter_nth_child(parent, n) + if success: + return child_iter + + def iter_parent(self, aiter): + success, parent_iter = super(TreeModel, self).iter_parent(aiter) + if success: + return parent_iter + + def set_row(self, treeiter, row): + # TODO: Accept a dictionary for row + # model.append(None,{COLUMN_ICON: icon, COLUMN_NAME: name}) n_columns = self.get_n_columns(); if len(row) != n_columns: @@ -377,34 +654,236 @@ class ListStore(Gtk.ListStore, TreeModel): if row[i] is not None: self.set_value(treeiter, i, row[i]) +TreeModel = override(TreeModel) +__all__.append('TreeModel') + +class TreeSortable(Gtk.TreeSortable, ): + + def get_sort_column_id(self): + success, sort_column_id, order = super(TreeSortable, self).get_sort_column_id() + if success: + return (sort_column_id, order,) + else: + return (None, None,) + +TreeSortable = override(TreeSortable) +__all__.append('TreeSortable') + +class ListStore(Gtk.ListStore, TreeModel, TreeSortable): + def __init__(self, *column_types): + Gtk.ListStore.__init__(self) + self.set_column_types(column_types) + + def append(self, row=None): + treeiter = Gtk.ListStore.append(self) + + if row is not None: + self.set_row(treeiter, row) + + return treeiter + + def insert(self, position, row=None): + treeiter = Gtk.ListStore.insert(self, position) + + if row is not None: + self.set_row(treeiter, row) + + return treeiter + + def insert_before(self, sibling, row=None): + treeiter = Gtk.ListStore.insert_before(self, sibling) + + if row is not None: + self.set_row(treeiter, row) + return treeiter + + def insert_after(self, sibling, row=None): + treeiter = Gtk.ListStore.insert_after(self, sibling) + + if row is not None: + self.set_row(treeiter, row) + + return treeiter + + ListStore = override(ListStore) __all__.append('ListStore') -class TreeStore(Gtk.TreeStore, TreeModel): +class TreeModelRow(object): + + def __init__(self, model, iter_or_path): + if not isinstance(model, Gtk.TreeModel): + raise TypeError("expected Gtk.TreeModel, %s found" % type(model).__name__) + self.model = model + if isinstance(iter_or_path, Gtk.TreePath): + self.iter = model.get_iter(iter_or_path) + elif isinstance(iter_or_path, Gtk.TreeIter): + self.iter = iter_or_path + else: + raise TypeError("expected Gtk.TreeIter or Gtk.TreePath, \ + %s found" % type(iter_or_path).__name__) + + @property + def path(self): + return self.model.get_path(self.iter) + + @property + def next(self): + return self.get_next() + + @property + def parent(self): + return self.get_parent() + + def get_next(self): + next_iter = self.model.iter_next(self.iter) + if next_iter: + return TreeModelRow(self.model, next_iter) + + def get_parent(self): + parent_iter = self.model.iter_parent(self.iter) + if parent_iter: + return TreeModelRow(self.model, parent_iter) + + def __getitem__(self, key): + if isinstance(key, int): + if key >= self.model.get_n_columns(): + raise IndexError("column index is out of bounds: %d" % key) + elif key < 0: + key = self._convert_negative_index(key) + return self.model.get_value(self.iter, key) + else: + raise TypeError("indices must be integers, not %s" % type(key).__name__) + + def __setitem__(self, key, value): + if isinstance(key, int): + if key >= self.model.get_n_columns(): + raise IndexError("column index is out of bounds: %d" % key) + elif key < 0: + key = self._convert_negative_index(key) + return self.model.set_value(self.iter, key, value) + else: + raise TypeError("indices must be integers, not %s" % type(key).__name__) + + def _convert_negative_index(self, index): + new_index = self.model.get_n_columns() + index + if new_index < 0: + raise IndexError("column index is out of bounds: %d" % index) + return new_index + + def iterchildren(self): + child_iter = self.model.iter_children(self.iter) + return TreeModelRowIter(self.model, child_iter) + +__all__.append('TreeModelRow') + +class TreeModelRowIter(object): + + def __init__(self, model, aiter): + self.model = model + self.iter = aiter + + def __next__(self): + if not self.iter: + raise StopIteration + row = TreeModelRow(self.model, self.iter) + self.iter = self.model.iter_next(self.iter) + return row + + # alias for Python 2.x object protocol + next = __next__ + + def __iter__(self): + return self + +__all__.append('TreeModelRowIter') + +class TreePath(Gtk.TreePath): + + def __str__(self): + return self.to_string() + + def __lt__(self, other): + return self.compare(other) < 0 + + def __le__(self, other): + return self.compare(other) <= 0 + + def __eq__(self, other): + return self.compare(other) == 0 + + def __ne__(self, other): + return self.compare(other) != 0 + + def __gt__(self, other): + return self.compare(other) > 0 + + def __ge__(self, other): + return self.compare(other) >= 0 + +TreePath = override(TreePath) +__all__.append('TreePath') + +class TreeStore(Gtk.TreeStore, TreeModel, TreeSortable): def __init__(self, *column_types): Gtk.TreeStore.__init__(self) self.set_column_types(column_types) - def append(self, parent, row): - + def append(self, parent, row=None): treeiter = Gtk.TreeStore.append(self, parent) - n_columns = self.get_n_columns(); - if len(row) != n_columns: - raise ValueError('row sequence has the incorrect number of elements') + if row is not None: + self.set_row(treeiter, row) - for i in range(n_columns): - if row[i] is not None: - self.set_value(treeiter, i, row[i]) + return treeiter + + def insert(self, parent, position, row=None): + treeiter = Gtk.TreeStore.insert(self, parent, position) + + if row is not None: + self.set_row(treeiter, row) return treeiter + def insert_before(self, parent, sibling, row=None): + treeiter = Gtk.TreeStore.insert_before(self, parent, sibling) + + if row is not None: + self.set_row(treeiter, row) + + return treeiter + + + def insert_after(self, parent, sibling, row=None): + treeiter = Gtk.TreeStore.insert_after(self, parent, sibling) + + if row is not None: + self.set_row(treeiter, row) + + return treeiter + + TreeStore = override(TreeStore) __all__.append('TreeStore') +class TreeView(Gtk.TreeView, Container): + + def get_path_at_pos(self, x, y): + success, path, column, cell_x, cell_y = super(TreeView, self).get_path_at_pos(x, y) + if success: + return (path, column, cell_x, cell_y,) + + def get_dest_row_at_pos(self, drag_x, drag_y): + success, path, pos = super(TreeView, self).get_dest_row_at_pos(drag_x, drag_y) + if success: + return (path, pos,) + +TreeView = override(TreeView) +__all__.append('TreeView') + class TreeViewColumn(Gtk.TreeViewColumn): def __init__(self, title='', cell_renderer=None, @@ -416,10 +895,27 @@ class TreeViewColumn(Gtk.TreeViewColumn): for (name, value) in attributes.items(): self.add_attribute(cell_renderer, name, value) + def cell_get_position(self, cell_renderer): + success, start_pos, width = super(TreeViewColumn, self).cell_get_position(cell_renderer) + if success: + return (start_pos, width,) + TreeViewColumn = override(TreeViewColumn) __all__.append('TreeViewColumn') -class Button(Gtk.Button): +class TreeSelection(Gtk.TreeSelection): + + def get_selected(self): + success, model, aiter = super(TreeSelection, self).get_selected() + if success: + return (model, aiter) + else: + return (model, None) + +TreeSelection = override(TreeSelection) +__all__.append('TreeSelection') + +class Button(Gtk.Button, Container): def __init__(self, label=None, stock=None, use_underline=False): if stock: label = stock diff --git a/gi/overrides/Makefile.in b/gi/overrides/Makefile.in index 630735c..d0a78be 100644 --- a/gi/overrides/Makefile.in +++ b/gi/overrides/Makefile.in @@ -157,6 +157,8 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLATFORM = @PLATFORM@ PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ PYCAIRO_LIBS = @PYCAIRO_LIBS@ @@ -214,7 +216,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ diff --git a/gi/overrides/__init__.py b/gi/overrides/__init__.py index e69de29..d4cd80b 100644 --- a/gi/overrides/__init__.py +++ b/gi/overrides/__init__.py @@ -0,0 +1,43 @@ +import gobject + +registry = None +class _Registry(dict): + def __setitem__(self, key, value): + '''We do checks here to make sure only submodules of the override + module are added. Key and value should be the same object and come + from the gi.override module. + + We add the override to the dict as "override_module.name". For instance + if we were overriding Gtk.Button you would retrive it as such: + registry['Gtk.Button'] + ''' + if not key == value: + raise KeyError('You have tried to modify the registry. This should only be done by the override decorator') + + info = getattr(value, '__info__') + if info == None: + raise KeyError('Can not override a type %s, which is not in a gobject introspection typelib' % value.__name__) + + if not value.__module__.startswith('gi.overrides'): + raise KeyError('You have tried to modify the registry outside of the overrides module. This is not allowed') + + g_type = info.get_g_type() + assert g_type != gobject.TYPE_NONE + if g_type != gobject.TYPE_INVALID: + g_type.pytype = value + + # strip gi.overrides from module name + module = value.__module__[13:] + key = "%s.%s" % (module, value.__name__) + super(_Registry, self).__setitem__(key, value) + + def register(self, override_class): + self[override_class] = override_class + +registry = _Registry() + +def override(type_): + '''Decorator for registering an override''' + registry.register(type_) + return type_ + diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index e3dd8c3..b768e9e 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -222,22 +222,17 @@ _pygi_g_type_interface_check_object (GIBaseInfo *info, /* Handle special cases. */ type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); - if (g_type_is_a (type, G_TYPE_VALUE)) { - GType object_type; - object_type = pyg_type_from_object ( (PyObject *) object->ob_type); - if (object_type == G_TYPE_INVALID) { - PyErr_Format (PyExc_TypeError, "Must be of a known GType, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - } else if (g_type_is_a (type, G_TYPE_CLOSURE)) { + if (g_type_is_a (type, G_TYPE_CLOSURE)) { if (!PyCallable_Check (object)) { PyErr_Format (PyExc_TypeError, "Must be callable, not %s", object->ob_type->tp_name); retval = 0; } break; + } else if (g_type_is_a (type, G_TYPE_VALUE)) { + /* we can't check g_values because we don't have + * enough context so just pass them through */ + break; } /* Fallback. */ @@ -904,7 +899,7 @@ array_item_error: GType object_type; gint retval; - object_type = pyg_type_from_object ( (PyObject *) object->ob_type); + object_type = pyg_type_from_object_strict ( (PyObject *) object->ob_type, FALSE); if (object_type == G_TYPE_INVALID) { PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType"); break; diff --git a/gi/pygi-foreign-cairo.c b/gi/pygi-foreign-cairo.c index 095f6cb..6326397 100644 --- a/gi/pygi-foreign-cairo.c +++ b/gi/pygi-foreign-cairo.c @@ -22,6 +22,7 @@ */ #include <cairo.h> +#include <Python.h> #if PY_VERSION_HEX < 0x03000000 #include <pycairo.h> @@ -111,6 +112,58 @@ cairo_surface_release (GIBaseInfo *base_info, Py_RETURN_NONE; } +#ifdef PycairoRectangleInt_FromRectangleInt +PyObject * +cairo_rectangle_int_to_arg (PyObject *value, + GITypeInfo *type_info, + GITransfer transfer, + GIArgument *arg) +{ + cairo_rectangle_int_t *rect; + + rect = ( (PycairoRectangleInt *) value)->rectangle_int; + if (!rect) { + PyErr_SetString (PyExc_ValueError, "RectangleInt instance wrapping a NULL pointer"); + return NULL; + } + + if (transfer == GI_TRANSFER_EVERYTHING) { + unsigned int size = sizeof(cairo_rectangle_int_t); + cairo_rectangle_int_t *transfer = malloc(size); + if (!transfer) { + PyErr_NoMemory(); + return NULL; + } + + memcpy(transfer, rect, size); + rect = transfer; + } + + arg->v_pointer = rect; + Py_RETURN_NONE; +} + +PyObject * +cairo_rectangle_int_from_arg (GITypeInfo *type_info, GIArgument *arg) +{ + cairo_rectangle_int_t *rect = (cairo_rectangle_int_t*) arg; + + if (rect) + return PycairoRectangleInt_FromRectangleInt (rect); + else { + cairo_rectangle_int_t temp = {}; + return PycairoRectangleInt_FromRectangleInt (&temp); + } +} + +PyObject * +cairo_rectangle_int_release (GIBaseInfo *base_info, + gpointer struct_) +{ + g_free (struct_); + Py_RETURN_NONE; +} +#endif static PyMethodDef _gi_cairo_functions[] = {}; PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo") @@ -130,5 +183,14 @@ PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo") cairo_surface_to_arg, cairo_surface_from_arg, cairo_surface_release); + +#ifdef PycairoRectangleInt_FromRectangleInt + pygi_register_foreign_struct ("cairo", + "RectangleInt", + cairo_rectangle_int_to_arg, + cairo_rectangle_int_from_arg, + cairo_rectangle_int_release); +#endif + } PYGLIB_MODULE_END; diff --git a/gi/pygi-foreign.c b/gi/pygi-foreign.c index f80b43c..75d5bb9 100644 --- a/gi/pygi-foreign.c +++ b/gi/pygi-foreign.c @@ -22,10 +22,13 @@ * IN THE SOFTWARE. */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + #include "pygi-foreign.h" #include "pygi-foreign-gvariant.h" -#include <config.h> #include <girepository.h> typedef struct { diff --git a/gi/pygi-info.c b/gi/pygi-info.c index feeccf7..33f71c1 100644 --- a/gi/pygi-info.c +++ b/gi/pygi-info.c @@ -57,6 +57,34 @@ _base_info_repr (PyGIBaseInfo *self) (void *) self); } +static PyObject * +_base_info_richcompare (PyGIBaseInfo *self, PyObject *other, int op) +{ + PyObject *res; + GIBaseInfo *other_info; + + if (!PyObject_TypeCheck(other, &PyGIBaseInfo_Type)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + other_info = ((PyGIBaseInfo *)other)->info; + + switch (op) { + case Py_EQ: + res = g_base_info_equal (self->info, other_info) ? Py_True : Py_False; + break; + case Py_NE: + res = g_base_info_equal (self->info, other_info) ? Py_False : Py_True; + break; + default: + res = Py_NotImplemented; + break; + } + Py_INCREF(res); + return res; +} + static PyMethodDef _PyGIBaseInfo_methods[]; PYGLIB_DEFINE_TYPE("gi.BaseInfo", PyGIBaseInfo_Type, PyGIBaseInfo); @@ -113,14 +141,14 @@ _pygi_info_new (GIBaseInfo *info) type = &PyGIFunctionInfo_Type; break; case GI_INFO_TYPE_CALLBACK: - PyErr_SetString (PyExc_NotImplementedError, "GICallbackInfo bindings not implemented"); - return NULL; + type = &PyGICallbackInfo_Type; + break; case GI_INFO_TYPE_STRUCT: type = &PyGIStructInfo_Type; break; case GI_INFO_TYPE_BOXED: - PyErr_SetString (PyExc_NotImplementedError, "GIBoxedInfo bindings not implemented"); - return NULL; + type = &PyGIBoxedInfo_Type; + break; case GI_INFO_TYPE_ENUM: case GI_INFO_TYPE_FLAGS: type = &PyGIEnumInfo_Type; @@ -135,8 +163,8 @@ _pygi_info_new (GIBaseInfo *info) type = &PyGIConstantInfo_Type; break; case GI_INFO_TYPE_ERROR_DOMAIN: - PyErr_SetString (PyExc_NotImplementedError, "GIErrorDomainInfo bindings not implemented"); - return NULL; + type = &PyGIErrorDomainInfo_Type; + break; case GI_INFO_TYPE_UNION: type = &PyGIUnionInfo_Type; break; @@ -144,23 +172,23 @@ _pygi_info_new (GIBaseInfo *info) type = &PyGIValueInfo_Type; break; case GI_INFO_TYPE_SIGNAL: - PyErr_SetString (PyExc_NotImplementedError, "GISignalInfo bindings not implemented"); - return NULL; + type = &PyGISignalInfo_Type; + break; case GI_INFO_TYPE_VFUNC: type = &PyGIVFuncInfo_Type; break; case GI_INFO_TYPE_PROPERTY: - PyErr_SetString (PyExc_NotImplementedError, "GIPropertyInfo bindings not implemented"); - return NULL; + type = &PyGIPropertyInfo_Type; + break; case GI_INFO_TYPE_FIELD: type = &PyGIFieldInfo_Type; break; case GI_INFO_TYPE_ARG: - PyErr_SetString (PyExc_NotImplementedError, "GIArgInfo bindings not implemented"); - return NULL; + type = &PyGIArgInfo_Type; + break; case GI_INFO_TYPE_TYPE: - PyErr_SetString (PyExc_NotImplementedError, "GITypeInfo bindings not implemented"); - return NULL; + type = &PyGITypeInfo_Type; + break; case GI_INFO_TYPE_UNRESOLVED: type = &PyGIUnresolvedInfo_Type; break; @@ -210,6 +238,55 @@ static PyMethodDef _PyGICallableInfo_methods[] = { { NULL, NULL, 0 } }; +/* CallbackInfo */ +PYGLIB_DEFINE_TYPE ("gi.CallbackInfo", PyGICallbackInfo_Type, PyGIBaseInfo); + +static PyMethodDef _PyGICallbackInfo_methods[] = { + { NULL, NULL, 0 } +}; + +/* BoxedInfo */ +PYGLIB_DEFINE_TYPE ("gi.BoxedInfo", PyGIBoxedInfo_Type, PyGIBaseInfo); + +static PyMethodDef _PyGIBoxedInfo_methods[] = { + { NULL, NULL, 0 } +}; + +/* ErrorDomainInfo */ +PYGLIB_DEFINE_TYPE ("gi.ErrorDomainInfo", PyGIErrorDomainInfo_Type, PyGIBaseInfo); + +static PyMethodDef _PyGIErrorDomainInfo_methods[] = { + { NULL, NULL, 0 } +}; + +/* SignalInfo */ +PYGLIB_DEFINE_TYPE ("gi.SignalInfo", PyGISignalInfo_Type, PyGIBaseInfo); + +static PyMethodDef _PyGISignalInfo_methods[] = { + { NULL, NULL, 0 } +}; + +/* PropertyInfo */ +PYGLIB_DEFINE_TYPE ("gi.PropertyInfo", PyGIPropertyInfo_Type, PyGIBaseInfo); + +static PyMethodDef _PyGIPropertyInfo_methods[] = { + { NULL, NULL, 0 } +}; + +/* ArgInfo */ +PYGLIB_DEFINE_TYPE ("gi.ArgInfo", PyGIArgInfo_Type, PyGIBaseInfo); + +static PyMethodDef _PyGIArgInfo_methods[] = { + { NULL, NULL, 0 } +}; + +/* TypeInfo */ +PYGLIB_DEFINE_TYPE ("gi.TypeInfo", PyGITypeInfo_Type, PyGIBaseInfo); + +static PyMethodDef _PyGITypeInfo_methods[] = { + { NULL, NULL, 0 } +}; + /* FunctionInfo */ PYGLIB_DEFINE_TYPE ("gi.FunctionInfo", PyGIFunctionInfo_Type, PyGIBaseInfo); @@ -1276,7 +1353,23 @@ static PyMethodDef _PyGIUnresolvedInfo_methods[] = { /* GIVFuncInfo */ PYGLIB_DEFINE_TYPE ("gi.VFuncInfo", PyGIVFuncInfo_Type, PyGIBaseInfo); +static PyObject * +_wrap_g_vfunc_info_get_invoker (PyGIBaseInfo *self) +{ + PyObject *result = Py_None; + GIBaseInfo *info; + + info = (GIBaseInfo *) g_vfunc_info_get_invoker ( (GIVFuncInfo *) self->info ); + if (info) + result = _pygi_info_new(info); + else + Py_INCREF(Py_None); + + return result; +} + static PyMethodDef _PyGIVFuncInfo_methods[] = { + { "get_invoker", (PyCFunction) _wrap_g_vfunc_info_get_invoker, METH_NOARGS }, { NULL, NULL, 0 } }; @@ -1413,6 +1506,7 @@ _pygi_info_register_types (PyObject *m) PyGIBaseInfo_Type.tp_traverse = (traverseproc) _base_info_traverse; PyGIBaseInfo_Type.tp_weaklistoffset = offsetof(PyGIBaseInfo, inst_weakreflist); PyGIBaseInfo_Type.tp_methods = _PyGIBaseInfo_methods; + PyGIBaseInfo_Type.tp_richcompare = (richcmpfunc)_base_info_richcompare; if (PyType_Ready(&PyGIBaseInfo_Type)) return; @@ -1424,6 +1518,8 @@ _pygi_info_register_types (PyObject *m) PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGICallableInfo_Type, CallableInfo, PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGICallbackInfo_Type, CallbackInfo, + PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIFunctionInfo_Type, FunctionInfo, PyGICallableInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIRegisteredTypeInfo_Type, RegisteredTypeInfo, @@ -1446,6 +1542,18 @@ _pygi_info_register_types (PyObject *m) PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIUnionInfo_Type, UnionInfo, PyGIRegisteredTypeInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIBoxedInfo_Type, BoxedInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIErrorDomainInfo_Type, ErrorDomainInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGISignalInfo_Type, SignalInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIPropertyInfo_Type, PropertyInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIArgInfo_Type, ArgInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGITypeInfo_Type, TypeInfo, + PyGIBaseInfo_Type); #undef _PyGI_REGISTER_TYPE diff --git a/gi/pygi-info.h b/gi/pygi-info.h index 0d2bade..afd65dc 100644 --- a/gi/pygi-info.h +++ b/gi/pygi-info.h @@ -35,6 +35,7 @@ gboolean pygi_g_struct_info_is_simple (GIStructInfo *struct_info); extern PyTypeObject PyGIBaseInfo_Type; extern PyTypeObject PyGICallableInfo_Type; +extern PyTypeObject PyGICallbackInfo_Type; extern PyTypeObject PyGIFunctionInfo_Type; extern PyTypeObject PyGIRegisteredTypeInfo_Type; extern PyTypeObject PyGIStructInfo_Type; @@ -47,6 +48,12 @@ extern PyTypeObject PyGIFieldInfo_Type; extern PyTypeObject PyGIUnresolvedInfo_Type; extern PyTypeObject PyGIVFuncInfo_Type; extern PyTypeObject PyGIUnionInfo_Type; +extern PyTypeObject PyGIBoxedInfo_Type; +extern PyTypeObject PyGIErrorDomainInfo_Type; +extern PyTypeObject PyGISignalInfo_Type; +extern PyTypeObject PyGIPropertyInfo_Type; +extern PyTypeObject PyGIArgInfo_Type; +extern PyTypeObject PyGITypeInfo_Type; #define PyGIBaseInfo_GET_GI_INFO(object) g_base_info_ref(((PyGIBaseInfo *)object)->info) diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c index 64b3f31..71d5859 100644 --- a/gi/pygi-invoke.c +++ b/gi/pygi-invoke.c @@ -343,9 +343,20 @@ _prepare_invocation_state (struct invocation_state *state, /* if caller allocates only use one level of indirection */ state->out_args[out_args_pos].v_pointer = NULL; state->args[i] = &state->out_args[out_args_pos]; - if (g_type_is_a (g_registered_type_info_get_g_type (info), G_TYPE_BOXED)) + if (g_type_is_a (g_registered_type_info_get_g_type (info), G_TYPE_BOXED)) { state->args[i]->v_pointer = _pygi_boxed_alloc (info, NULL); - else { + } else if (g_struct_info_is_foreign((GIStructInfo *) info) ) { + PyObject *foreign_struct = + pygi_struct_foreign_convert_from_g_argument(state->arg_type_infos[i], NULL); + + pygi_struct_foreign_convert_to_g_argument( + foreign_struct, + state->arg_type_infos[i], + GI_TRANSFER_EVERYTHING, + state->args[i]); + + Py_DECREF(foreign_struct); + } else { gssize size = g_struct_info_get_size ( (GIStructInfo *) info); state->args[i]->v_pointer = g_malloc0 (size); } @@ -548,8 +559,16 @@ _invoke_function (struct invocation_state *state, error = NULL; + pyg_begin_allow_threads; retval = g_function_info_invoke ( (GIFunctionInfo *) function_info, - state->in_args, state->n_in_args, state->out_args, state->n_out_args, &state->return_arg, &error); + state->in_args, + state->n_in_args, + state->out_args, + state->n_out_args, + &state->return_arg, + &error); + pyg_end_allow_threads; + if (!retval) { g_assert (error != NULL); /* TODO: raise the right error, out of the error domain. */ @@ -22,8 +22,11 @@ #ifndef __PYGI_H__ #define __PYGI_H__ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + #define NO_IMPORT_PYGOBJECT -#include <config.h> #include <pygobject.h> #if ENABLE_INTROSPECTION @@ -83,8 +86,11 @@ _pygi_import (void) if (PyGI_API != NULL) { return 1; } - +#if PY_VERSION_HEX >= 0x03000000 + PyGI_API = (struct PyGI_API*) PyCapsule_Import("gi._API", FALSE); +#else PyGI_API = (struct PyGI_API*) PyCObject_Import("gi", "_API"); +#endif if (PyGI_API == NULL) { return -1; } @@ -152,7 +158,7 @@ static inline PyObject * pygi_get_property_value (PyGObject *instance, const gchar *attr_name) { - return -1; + return NULL; } static inline gint diff --git a/gi/repository/Makefile.in b/gi/repository/Makefile.in index 7b36c15..7f0ef44 100644 --- a/gi/repository/Makefile.in +++ b/gi/repository/Makefile.in @@ -157,6 +157,8 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLATFORM = @PLATFORM@ PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ PYCAIRO_LIBS = @PYCAIRO_LIBS@ @@ -214,7 +216,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ diff --git a/gi/types.py b/gi/types.py index 0a8768c..18b4013 100644 --- a/gi/types.py +++ b/gi/types.py @@ -100,7 +100,7 @@ class MetaClassHelper(object): for vfunc_info in base.__info__.get_vfuncs(): vfunc = getattr(cls, 'do_' + vfunc_info.get_name(), None) if vfunc is None and isinstance(base.__info__, InterfaceInfo) and \ - not hasattr(cls, vfunc_info.get_name()): + (not hasattr(cls, vfunc_info.get_name()) and not vfunc_info.get_invoker()): raise TypeError('Class implementing %s.%s should implement ' 'the method do_%s()' % (base.__info__.get_namespace(), base.__info__.get_name(), @@ -162,14 +162,6 @@ class StructMeta(type, MetaClassHelper): cls._setup_methods() cls._setup_constructors() - -def override(type_): - g_type = type_.__info__.get_g_type() - assert g_type != gobject.TYPE_NONE - if g_type != gobject.TYPE_INVALID: - g_type.pytype = type_ - return type_ - class Enum(int): __info__ = None def __init__(self, value): |