diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-07-12 08:40:19 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-07-12 08:40:22 +0900 |
commit | 9e05f0b92b0d6cde13d729955af7b911f79ba833 (patch) | |
tree | e9bf82708776e0eb586bb1e26742ad4e1c7c5f85 /gi | |
parent | d7ab1229ba0f909c4a3ba445441a4c9f89d7b38d (diff) | |
download | pygobject2-9e05f0b92b0d6cde13d729955af7b911f79ba833.tar.gz pygobject2-9e05f0b92b0d6cde13d729955af7b911f79ba833.tar.bz2 pygobject2-9e05f0b92b0d6cde13d729955af7b911f79ba833.zip |
Imported Upstream version 3.11.4
Change-Id: I8c3c314d3446d81a7d958b4cbba28bf0e39e7616
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'gi')
-rw-r--r-- | gi/Makefile.am | 20 | ||||
-rw-r--r-- | gi/Makefile.in | 87 | ||||
-rw-r--r-- | gi/docstring.py | 157 | ||||
-rw-r--r-- | gi/module.py | 19 | ||||
-rw-r--r-- | gi/overrides/GLib.py | 5 | ||||
-rw-r--r-- | gi/overrides/GObject.py | 3 | ||||
-rw-r--r-- | gi/overrides/Gdk.py | 10 | ||||
-rw-r--r-- | gi/overrides/Gtk.py | 16 | ||||
-rw-r--r-- | gi/overrides/Pango.py | 9 | ||||
-rw-r--r-- | gi/overrides/__init__.py | 21 | ||||
-rw-r--r-- | gi/pygi-boxed.c | 17 | ||||
-rw-r--r-- | gi/pygi-info.c | 63 | ||||
-rw-r--r-- | gi/pygi-marshal-from-py.c | 16 | ||||
-rw-r--r-- | gi/pygi-struct.c | 41 | ||||
-rw-r--r-- | gi/pygi-type.c | 58 | ||||
-rw-r--r-- | gi/pygi-type.h | 2 | ||||
-rw-r--r-- | gi/types.py | 9 |
17 files changed, 246 insertions, 307 deletions
diff --git a/gi/Makefile.am b/gi/Makefile.am index fc11ff8..aa91a46 100644 --- a/gi/Makefile.am +++ b/gi/Makefile.am @@ -26,14 +26,6 @@ endif pygidir = $(pyexecdir)/gi -pygi_PYTHON = \ - __init__.py \ - types.py \ - module.py \ - importer.py \ - pygtkcompat.py \ - docstring.py - pygi_LTLIBRARIES = _gi.la _gi_la_SOURCES = \ @@ -118,16 +110,8 @@ _gi_cairo_la_LDFLAGS = \ %$(PYTHON_SO): %.la $(LN_S) -f .libs/$@ $@ -# if we build in a separate tree, we need to symlink the *.py files from the -# source tree; Python does not accept the extensions and modules in different -# paths -build_pylinks: - for f in $(pygi_PYTHON); do \ - [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \ - done - -all-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks +all-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) -check-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks +check-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) clean-local: rm -f $(LTLIBRARIES:.la=$(PYTHON_SO)) diff --git a/gi/Makefile.in b/gi/Makefile.in index f8bc6eb..d4f89c7 100644 --- a/gi/Makefile.in +++ b/gi/Makefile.in @@ -56,8 +56,7 @@ host_triplet = @host@ @ENABLE_CAIRO_TRUE@am__append_2 = _gi_cairo.la subdir = gi -DIST_COMMON = $(pygi_PYTHON) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ $(top_srcdir)/m4/jhflags.m4 $(top_srcdir)/m4/libtool.m4 \ @@ -97,7 +96,7 @@ am__uninstall_files_from_dir = { \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } -am__installdirs = "$(DESTDIR)$(pygidir)" "$(DESTDIR)$(pygidir)" +am__installdirs = "$(DESTDIR)$(pygidir)" LTLIBRARIES = $(pygi_LTLIBRARIES) am__DEPENDENCIES_1 = @OS_WIN32_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) @@ -167,8 +166,6 @@ am__can_run_installinfo = \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac -am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile) -py_compile = $(top_srcdir)/py-compile RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ @@ -388,14 +385,6 @@ extension_ldflags = -module -avoid-version -shrext $(PYTHON_SO) \ @OS_WIN32_TRUE@ $(PYTHON_LIBS) pygidir = $(pyexecdir)/gi -pygi_PYTHON = \ - __init__.py \ - types.py \ - module.py \ - importer.py \ - pygtkcompat.py \ - docstring.py - pygi_LTLIBRARIES = _gi.la $(am__append_2) _gi_la_SOURCES = \ pygi-repository.c \ @@ -732,48 +721,6 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs -install-pygiPYTHON: $(pygi_PYTHON) - @$(NORMAL_INSTALL) - @list='$(pygi_PYTHON)'; dlist=; list2=; test -n "$(pygidir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pygidir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pygidir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ - if test -f $$b$$p; then \ - $(am__strip_dir) \ - dlist="$$dlist $$f"; \ - list2="$$list2 $$b$$p"; \ - else :; fi; \ - done; \ - for file in $$list2; do echo $$file; done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pygidir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(pygidir)" || exit $$?; \ - done || exit $$?; \ - if test -n "$$dlist"; then \ - if test -z "$(DESTDIR)"; then \ - $(am__py_compile) --basedir "$(pygidir)" $$dlist; \ - else \ - $(am__py_compile) --destdir "$(DESTDIR)" \ - --basedir "$(pygidir)" $$dlist; \ - fi; \ - else :; fi - -uninstall-pygiPYTHON: - @$(NORMAL_UNINSTALL) - @list='$(pygi_PYTHON)'; test -n "$(pygidir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - dir='$(DESTDIR)$(pygidir)'; \ - filesc=`echo "$$files" | sed 's|$$|c|'`; \ - fileso=`echo "$$files" | sed 's|$$|o|'`; \ - st=0; \ - for files in "$$files" "$$filesc" "$$fileso"; do \ - $(am__uninstall_files_from_dir) || st=$$?; \ - done; \ - exit $$st # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. @@ -971,7 +918,7 @@ check: check-recursive all-am: Makefile $(LTLIBRARIES) all-local installdirs: installdirs-recursive installdirs-am: - for dir in "$(DESTDIR)$(pygidir)" "$(DESTDIR)$(pygidir)"; do \ + for dir in "$(DESTDIR)$(pygidir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive @@ -1027,7 +974,7 @@ info: info-recursive info-am: -install-data-am: install-pygiLTLIBRARIES install-pygiPYTHON +install-data-am: install-pygiLTLIBRARIES install-dvi: install-dvi-recursive @@ -1073,7 +1020,7 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-pygiLTLIBRARIES uninstall-pygiPYTHON +uninstall-am: uninstall-pygiLTLIBRARIES .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \ ctags-recursive install-am install-strip tags-recursive @@ -1088,12 +1035,12 @@ uninstall-am: uninstall-pygiLTLIBRARIES uninstall-pygiPYTHON install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am \ - install-pygiLTLIBRARIES install-pygiPYTHON install-strip \ - installcheck installcheck-am installdirs installdirs-am \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ - uninstall-pygiLTLIBRARIES uninstall-pygiPYTHON + install-pygiLTLIBRARIES install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am \ + uninstall-pygiLTLIBRARIES # This is to ensure we have a symlink to the .so in the @@ -1102,17 +1049,9 @@ uninstall-am: uninstall-pygiLTLIBRARIES uninstall-pygiPYTHON %$(PYTHON_SO): %.la $(LN_S) -f .libs/$@ $@ -# if we build in a separate tree, we need to symlink the *.py files from the -# source tree; Python does not accept the extensions and modules in different -# paths -build_pylinks: - for f in $(pygi_PYTHON); do \ - [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \ - done - -all-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks +all-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) -check-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks +check-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) clean-local: rm -f $(LTLIBRARIES:.la=$(PYTHON_SO)) diff --git a/gi/docstring.py b/gi/docstring.py index 2aa2629..a1b8a51 100644 --- a/gi/docstring.py +++ b/gi/docstring.py @@ -23,7 +23,11 @@ from ._gi import \ VFuncInfo, \ FunctionInfo, \ - Direction + CallableInfo, \ + ObjectInfo, \ + StructInfo, \ + Direction, \ + TypeTag #: Module storage for currently registered doc string generator function. @@ -55,49 +59,78 @@ def generate_doc_string(info): return _generate_doc_string_func(info) -def split_function_info_args(info): - """Split a functions args into a tuple of two lists. - - Note that args marked as Direction.INOUT will be in both lists. - - :Returns: - Tuple of (in_args, out_args) - """ - in_args = [] - out_args = [] - for arg in info.get_arguments(): - direction = arg.get_direction() - if direction in (Direction.IN, Direction.INOUT): - in_args.append(arg) - if direction in (Direction.OUT, Direction.INOUT): - out_args.append(arg) - return (in_args, out_args) - - -def _generate_callable_info_function_signature(info): - """Default doc string generator""" - in_args, out_args = split_function_info_args(info) +_type_tag_to_py_type = {TypeTag.BOOLEAN: bool, + TypeTag.INT8: int, + TypeTag.UINT8: int, + TypeTag.INT16: int, + TypeTag.UINT16: int, + TypeTag.INT32: int, + TypeTag.UINT32: int, + TypeTag.INT64: int, + TypeTag.UINT64: int, + TypeTag.FLOAT: float, + TypeTag.DOUBLE: float, + TypeTag.GLIST: list, + TypeTag.GSLIST: list, + TypeTag.ARRAY: list, + TypeTag.GHASH: dict, + TypeTag.UTF8: str, + TypeTag.FILENAME: str, + TypeTag.UNICHAR: str, + TypeTag.INTERFACE: None, + TypeTag.GTYPE: None, + TypeTag.ERROR: None, + TypeTag.VOID: None, + } + + +def _get_pytype_hint(gi_type): + type_tag = gi_type.get_tag() + py_type = _type_tag_to_py_type.get(type_tag, None) + + if py_type and hasattr(py_type, '__name__'): + return py_type.__name__ + elif type_tag == TypeTag.INTERFACE: + iface = gi_type.get_interface() + + info_name = iface.get_name() + if not info_name: + return gi_type.get_tag_as_string() + + return '%s.%s' % (iface.get_namespace(), info_name) + + return gi_type.get_tag_as_string() + + +def _generate_callable_info_doc(info): in_args_strs = [] if isinstance(info, VFuncInfo): in_args_strs = ['self'] elif isinstance(info, FunctionInfo): if info.is_method(): in_args_strs = ['self'] - elif info.is_constructor(): - in_args_strs = ['cls'] - # Build a lists of indices prior to adding the docs because - # because it is possible the index retrieved comes before in - # argument being used. - ignore_indices = set([arg.get_destroy() for arg in in_args]) - user_data_indices = set([arg.get_closure() for arg in in_args]) - - for i, arg in enumerate(in_args): + args = info.get_arguments() + hint_blacklist = ('void',) + + # Build lists of indices prior to adding the docs because it is possible + # the index retrieved comes before input arguments being used. + ignore_indices = set() + user_data_indices = set() + for arg in args: + ignore_indices.add(arg.get_destroy()) + ignore_indices.add(arg.get_type().get_array_length()) + user_data_indices.add(arg.get_closure()) + + # Build input argument strings + for i, arg in enumerate(args): + if arg.get_direction() == Direction.OUT: + continue # skip exclusively output args if i in ignore_indices: continue argstr = arg.get_name() - hint = arg.get_pytype_hint() - if hint not in ('void',): + hint = _get_pytype_hint(arg.get_type()) + if hint not in hint_blacklist: argstr += ':' + hint if arg.may_be_null() or i in user_data_indices: # allow-none or user_data from a closure @@ -107,12 +140,56 @@ def _generate_callable_info_function_signature(info): in_args_strs.append(argstr) in_args_str = ', '.join(in_args_strs) - if out_args: - out_args_str = ', '.join(arg.get_name() + ':' + arg.get_pytype_hint() - for arg in out_args) - return '%s(%s) -> %s' % (info.get_name(), in_args_str, out_args_str) + # Build return + output argument strings + out_args_strs = [] + return_hint = _get_pytype_hint(info.get_return_type()) + if not info.skip_return and return_hint and return_hint not in hint_blacklist: + if info.may_return_null(): + argstr += ' or None' + out_args_strs.append(return_hint) + + for i, arg in enumerate(args): + if arg.get_direction() == Direction.IN: + continue # skip exclusively input args + if i in ignore_indices: + continue + argstr = arg.get_name() + hint = _get_pytype_hint(arg.get_type()) + if hint not in hint_blacklist: + argstr += ':' + hint + out_args_strs.append(argstr) + + if out_args_strs: + return '%s(%s) -> %s' % (info.__name__, in_args_str, ', '.join(out_args_strs)) else: - return '%s(%s)' % (info.get_name(), in_args_str) + return '%s(%s)' % (info.__name__, in_args_str) + + +def _generate_class_info_doc(info): + doc = '\n:Constructors:\n' # start with \n to avoid auto indent of other lines + + if isinstance(info, StructInfo): + # Don't show default constructor for disguised (0 length) structs + if info.get_size() > 0: + doc += ' ' + info.get_name() + '()\n' + else: + doc += ' ' + info.get_name() + '(**properties)\n' + + for method_info in info.get_methods(): + if method_info.is_constructor(): + doc += ' ' + _generate_callable_info_doc(method_info) + '\n' + + return doc + + +def _generate_doc_dispatch(info): + if isinstance(info, (ObjectInfo, StructInfo)): + return _generate_class_info_doc(info) + + elif isinstance(info, CallableInfo): + return _generate_callable_info_doc(info) + + return '' -set_doc_string_generator(_generate_callable_info_function_signature) +set_doc_string_generator(_generate_doc_dispatch) diff --git a/gi/module.py b/gi/module.py index 71f8ac5..8996926 100644 --- a/gi/module.py +++ b/gi/module.py @@ -60,8 +60,7 @@ from .types import \ StructMeta from ._gobject._gobject import \ - GInterface, \ - GObject + GInterface from ._gobject.constants import \ TYPE_NONE, \ @@ -81,10 +80,16 @@ def get_parent_for_object(object_info): parent_object_info = object_info.get_parent() if not parent_object_info: - # Special case GObject.Object as being derived from the static GObject. - if object_info.get_namespace() == 'GObject' and object_info.get_name() == 'Object': - return GObject - + # If we reach the end of the introspection info class hierarchy, look + # for an existing wrapper on the GType and use it as a base for the + # new introspection wrapper. This allows static C wrappers already + # registered with the GType to be used as the introspection base + # (_gobject.GObject for example) + gtype = object_info.get_g_type() + if gtype and gtype.pytype: + return gtype.pytype + + # Otherwise use builtins.object as the base return object namespace = parent_object_info.get_namespace() @@ -163,6 +168,8 @@ class IntrospectionModule(object): for value_info in info.get_values(): value_name = value_info.get_name_unescaped().translate(ascii_upper_trans) setattr(wrapper, value_name, wrapper(value_info.get_value())) + for method_info in info.get_methods(): + setattr(wrapper, method_info.__name__, method_info) if g_type != TYPE_NONE: g_type.pytype = wrapper diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py index fc38f69..df5654a 100644 --- a/gi/overrides/GLib.py +++ b/gi/overrides/GLib.py @@ -551,11 +551,6 @@ class Source(GLib.Source): if hasattr(self, '__pygi_custom_source'): self.unref() - # Backwards compatible API for optional arguments - def attach(self, context=None): - id = super(Source, self).attach(context) - return id - def set_callback(self, fn, user_data=None): if hasattr(self, '__pygi_custom_source'): # use our custom pyg_source_set_callback() if for a GSource object diff --git a/gi/overrides/GObject.py b/gi/overrides/GObject.py index 2187ce5..147a452 100644 --- a/gi/overrides/GObject.py +++ b/gi/overrides/GObject.py @@ -23,7 +23,6 @@ import sys import warnings -import functools from collections import namedtuple import gi.overrides @@ -515,7 +514,7 @@ def _signalmethod(func): # Function wrapper for signal functions used as instance methods. # This is needed when the signal functions come directly from GI. # (they are not already wrapped) - @functools.wraps(func) + @gi.overrides.wraps(func) def meth(*args, **kwargs): return func(*args, **kwargs) return meth diff --git a/gi/overrides/Gdk.py b/gi/overrides/Gdk.py index d979746..9d0ba7d 100644 --- a/gi/overrides/Gdk.py +++ b/gi/overrides/Gdk.py @@ -44,7 +44,7 @@ class Color(Gdk.Color): return self.equal(other) def __repr__(self): - return '<Gdk.Color(red=%d, green=%d, blue=%d)>' % (self.red, self.green, self.blue) + return 'Gdk.Color(red=%d, green=%d, blue=%d)' % (self.red, self.green, self.blue) red_float = property(fget=lambda self: self.red / float(self.MAX_VALUE), fset=lambda self, v: setattr(self, 'red', int(v * self.MAX_VALUE))) @@ -84,7 +84,7 @@ if Gdk._version == '3.0': return self.equal(other) def __repr__(self): - return '<Gdk.Color(red=%f, green=%f, blue=%f, alpha=%f)>' % (self.red, self.green, self.blue, self.alpha) + return 'Gdk.RGBA(red=%f, green=%f, blue=%f, alpha=%f)' % (self.red, self.green, self.blue, self.alpha) def __iter__(self): """Iterator which allows easy conversion to tuple and list types.""" @@ -121,7 +121,7 @@ if Gdk._version == '2.0': self.height = height def __repr__(self): - return '<Gdk.Rectangle(x=%d, y=%d, width=%d, height=%d)>' % (self.x, self.y, self.height, self.width) + return 'Gdk.Rectangle(x=%d, y=%d, width=%d, height=%d)' % (self.x, self.y, self.height, self.width) Rectangle = override(Rectangle) __all__.append('Rectangle') @@ -332,9 +332,9 @@ def _gdk_atom_str(atom): def _gdk_atom_repr(atom): n = atom.name() if n: - return 'Gdk.Atom<%s>' % n + return 'Gdk.Atom.intern("%s", False)' % n # fall back to atom index - return 'Gdk.Atom<%i>' % hash(atom) + return '<Gdk.Atom(%i)>' % hash(atom) Gdk.Atom.__str__ = _gdk_atom_str diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py index c0a9096..4d16a68 100644 --- a/gi/overrides/Gtk.py +++ b/gi/overrides/Gtk.py @@ -76,9 +76,6 @@ class Widget(Gtk.Widget): translate_coordinates = strip_boolean_result(Gtk.Widget.translate_coordinates) - def render_icon(self, stock_id, size, detail=None): - return super(Widget, self).render_icon(stock_id, size, detail) - def drag_dest_set_target_list(self, target_list): if (target_list is not None) and (not isinstance(target_list, Gtk.TargetList)): target_list = Gtk.TargetList.new(_construct_target_list(target_list)) @@ -713,19 +710,9 @@ __all__.append('TextBuffer') class TextIter(Gtk.TextIter): - forward_search = strip_boolean_result(Gtk.TextIter.forward_search) backward_search = strip_boolean_result(Gtk.TextIter.backward_search) - def begins_tag(self, tag=None): - return super(TextIter, self).begins_tag(tag) - - def ends_tag(self, tag=None): - return super(TextIter, self).ends_tag(tag) - - def toggles_tag(self, tag=None): - return super(TextIter, self).toggles_tag(tag) - TextIter = override(TextIter) __all__.append('TextIter') @@ -857,9 +844,6 @@ class TreeModel(Gtk.TreeModel): return tuple(values) - def filter_new(self, root=None): - return super(TreeModel, self).filter_new(root) - # # Signals supporting python iterables as tree paths # diff --git a/gi/overrides/Pango.py b/gi/overrides/Pango.py index 74602c4..0f7c484 100644 --- a/gi/overrides/Pango.py +++ b/gi/overrides/Pango.py @@ -26,15 +26,6 @@ Pango = get_introspection_module('Pango') __all__ = [] -class Context(Pango.Context): - - def get_metrics(self, desc, language=None): - return super(Context, self).get_metrics(desc, language) - -Context = override(Context) -__all__.append('Context') - - class FontDescription(Pango.FontDescription): def __new__(cls, string=None): diff --git a/gi/overrides/__init__.py b/gi/overrides/__init__.py index 3406622..9e7a0f1 100644 --- a/gi/overrides/__init__.py +++ b/gi/overrides/__init__.py @@ -1,6 +1,5 @@ import types import warnings -import functools from gi import PyGIDeprecationWarning from gi._gi import CallableInfo @@ -15,6 +14,14 @@ __path__ = extend_path(__path__, __name__) registry = None +def wraps(wrapped): + def assign(wrapper): + wrapper.__name__ = wrapped.__name__ + wrapper.__module__ = wrapped.__module__ + return wrapper + return assign + + class _Registry(dict): def __setitem__(self, key, value): '''We do checks here to make sure only submodules of the override @@ -61,12 +68,8 @@ class overridefunc(object): self.module = modules[module_name]._introspection_module def __call__(self, func): - def wrapper(*args, **kwargs): - return func(*args, **kwargs) - wrapper.__name__ = func.__name__ - wrapper.__doc__ = func.__doc__ - setattr(self.module, func.__name__, wrapper) - return wrapper + setattr(self.module, func.__name__, func) + return func registry = _Registry() @@ -82,7 +85,7 @@ def override(type_): def deprecated(fn, replacement): '''Decorator for marking methods and classes as deprecated''' - @functools.wraps(fn) + @wraps(fn) def wrapped(*args, **kwargs): warnings.warn('%s is deprecated; use %s instead' % (fn.__name__, replacement), PyGIDeprecationWarning, stacklevel=2) @@ -185,7 +188,7 @@ def strip_boolean_result(method, exc_type=None, exc_str=None, fail_ret=None): several out arguments. Translate such a method to return the out arguments on success and None on failure. ''' - @functools.wraps(method) + @wraps(method) def wrapped(*args, **kwargs): ret = method(*args, **kwargs) if ret[0]: diff --git a/gi/pygi-boxed.c b/gi/pygi-boxed.c index d352e23..ea798ff 100644 --- a/gi/pygi-boxed.c +++ b/gi/pygi-boxed.c @@ -47,7 +47,8 @@ _boxed_dealloc (PyGIBoxed *self) void * _pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out) { - gsize size; + gpointer boxed = NULL; + gsize size = 0; switch (g_base_info_get_type (info)) { case GI_INFO_TYPE_UNION: @@ -64,10 +65,21 @@ _pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out) return NULL; } + if (size == 0) { + PyErr_Format (PyExc_TypeError, + "boxed cannot be created directly; try using a constructor, see: help(%s.%s)", + g_base_info_get_namespace (info), + g_base_info_get_name (info)); + return NULL; + } + if( size_out != NULL) *size_out = size; - return g_slice_alloc0 (size); + boxed = g_slice_alloc0 (size); + if (boxed == NULL) + PyErr_NoMemory(); + return boxed; } static PyObject * @@ -90,7 +102,6 @@ _boxed_new (PyTypeObject *type, boxed = _pygi_boxed_alloc (info, &size); if (boxed == NULL) { - PyErr_NoMemory(); goto out; } diff --git a/gi/pygi-info.c b/gi/pygi-info.c index 12f756c..af893ec 100644 --- a/gi/pygi-info.c +++ b/gi/pygi-info.c @@ -186,10 +186,9 @@ static PyObject * _base_info_repr (PyGIBaseInfo *self) { - return PYGLIB_PyUnicode_FromFormat ("<%s object (%s) at 0x%p>", + return PYGLIB_PyUnicode_FromFormat ("%s(%s)", Py_TYPE( (PyObject *) self)->tp_name, - _safe_base_info_get_name (self->info), - (void *) self); + _safe_base_info_get_name (self->info)); } static PyObject * @@ -510,7 +509,7 @@ _pygi_object_get_gi_info (PyObject *object, } if (!PyObject_TypeCheck (py_info, type)) { PyErr_Format (PyExc_TypeError, "attribute '__info__' must be %s, not %s", - type->tp_name, Py_TYPE(&py_info)->tp_name); + type->tp_name, Py_TYPE(py_info)->tp_name); goto out; } @@ -730,6 +729,12 @@ _wrap_g_callable_info_may_return_null (PyGIBaseInfo *self) } static PyObject * +_wrap_g_callable_info_skip_return (PyGIBaseInfo *self) +{ + return PyBool_FromLong (g_callable_info_skip_return (self->info)); +} + +static PyObject * _wrap_g_callable_info_get_return_attribute (PyGIBaseInfo *self, PyObject *py_name) { gchar *name; @@ -757,6 +762,7 @@ static PyMethodDef _PyGICallableInfo_methods[] = { { "get_return_type", (PyCFunction) _wrap_g_callable_info_get_return_type, METH_NOARGS }, { "get_caller_owns", (PyCFunction) _wrap_g_callable_info_get_caller_owns, METH_NOARGS }, { "may_return_null", (PyCFunction) _wrap_g_callable_info_may_return_null, METH_NOARGS }, + { "skip_return", (PyCFunction) _wrap_g_callable_info_skip_return, METH_NOARGS }, { "get_return_attribute", (PyCFunction) _wrap_g_callable_info_get_return_attribute, METH_O }, { NULL, NULL, 0 } }; @@ -908,54 +914,6 @@ _wrap_g_arg_info_get_type (PyGIBaseInfo *self) return _get_child_info (self, g_arg_info_get_type); } -/* _g_arg_get_pytype_hint - * - * Returns new value reference to a string hinting at the python type - * which can be used for the given gi argument info. - */ -static PyObject * -_g_arg_get_pytype_hint (PyGIBaseInfo *self) -{ - GIArgInfo *arg_info = (GIArgInfo*)self->info; - GITypeInfo type_info; - GITypeTag type_tag; - PyObject *py_type; - - g_arg_info_load_type(arg_info, &type_info); - type_tag = g_type_info_get_tag(&type_info); - - /* First attempt getting a python type object. */ - py_type = _pygi_get_py_type_hint(type_tag); - if (py_type != Py_None && PyObject_HasAttrString(py_type, "__name__")) { - PyObject *name = PyObject_GetAttrString(py_type, "__name__"); - Py_DecRef(py_type); - return name; - } else { - Py_DecRef(py_type); - if (type_tag == GI_TYPE_TAG_INTERFACE) { - const char *info_name; - PyObject *py_string; - GIBaseInfo *iface = g_type_info_get_interface(&type_info); - gchar *name; - - info_name = _safe_base_info_get_name (iface); - if (info_name == NULL) { - g_base_info_unref (iface); - return PYGLIB_PyUnicode_FromString(g_type_tag_to_string(type_tag)); - } - - name = g_strdup_printf("%s.%s", - g_base_info_get_namespace(iface), - info_name); - g_base_info_unref(iface); - py_string = PYGLIB_PyUnicode_FromString(name); - g_free(name); - return py_string; - } - return PYGLIB_PyUnicode_FromString(g_type_tag_to_string(type_tag)); - } -} - static PyMethodDef _PyGIArgInfo_methods[] = { { "get_direction", (PyCFunction) _wrap_g_arg_info_get_direction, METH_NOARGS }, { "is_caller_allocates", (PyCFunction) _wrap_g_arg_info_is_caller_allocates, METH_NOARGS }, @@ -967,7 +925,6 @@ static PyMethodDef _PyGIArgInfo_methods[] = { { "get_closure", (PyCFunction) _wrap_g_arg_info_get_closure, METH_NOARGS }, { "get_destroy", (PyCFunction) _wrap_g_arg_info_get_destroy, METH_NOARGS }, { "get_type", (PyCFunction) _wrap_g_arg_info_get_type, METH_NOARGS }, - { "get_pytype_hint", (PyCFunction) _g_arg_get_pytype_hint, METH_NOARGS }, { NULL, NULL, 0 } }; diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c index ed2e582..41dcf54 100644 --- a/gi/pygi-marshal-from-py.c +++ b/gi/pygi-marshal-from-py.c @@ -1362,8 +1362,19 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state, /* NULL out user_data if it was not supplied and the default arg placeholder * was used instead. */ - if (py_user_data == _PyGIDefaultArgPlaceholder) + if (py_user_data == _PyGIDefaultArgPlaceholder) { py_user_data = NULL; + } else if (callable_cache->user_data_varargs_index < 0) { + /* For non-variable length user data, place the user data in a + * single item tuple which is concatenated to the callbacks arguments. + * This allows callback input arg marshaling to always expect a + * tuple for user data. Note the + */ + py_user_data = Py_BuildValue("(O)", py_user_data, NULL); + } else { + /* increment the ref borrowed from PyTuple_GetItem above */ + Py_INCREF (py_user_data); + } } } @@ -1384,6 +1395,9 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state, closure = _pygi_make_native_closure (callable_info, callback_cache->scope, py_arg, py_user_data); arg->v_pointer = closure->closure; + /* always decref the user data as _pygi_make_native_closure adds its own ref */ + Py_XDECREF (py_user_data); + /* The PyGICClosure instance is used as user data passed into the C function. * The return trip to python will marshal this back and pull the python user data out. */ diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c index 29ea38e..296c47c 100644 --- a/gi/pygi-struct.c +++ b/gi/pygi-struct.c @@ -27,12 +27,39 @@ #include <girepository.h> #include <pyglib-python-compat.h> + +static GIBaseInfo * +_struct_get_info (PyObject *self) +{ + PyObject *py_info; + GIBaseInfo *info = NULL; + + py_info = PyObject_GetAttrString (self, "__info__"); + if (py_info == NULL) { + return NULL; + } + if (!PyObject_TypeCheck (py_info, &PyGIStructInfo_Type) && + !PyObject_TypeCheck (py_info, &PyGIUnionInfo_Type)) { + PyErr_Format (PyExc_TypeError, "attribute '__info__' must be %s or %s, not %s", + PyGIStructInfo_Type.tp_name, + PyGIUnionInfo_Type.tp_name, + Py_TYPE(py_info)->tp_name); + goto out; + } + + info = ( (PyGIBaseInfo *) py_info)->info; + g_base_info_ref (info); + +out: + Py_DECREF (py_info); + + return info; +} + static void _struct_dealloc (PyGIStruct *self) { - GIBaseInfo *info = _pygi_object_get_gi_info ( - (PyObject *) self, - &PyGIStructInfo_Type); + GIBaseInfo *info = _struct_get_info ( (PyObject *) self ); if (info != NULL && g_struct_info_is_foreign ( (GIStructInfo *) info)) { pygi_struct_foreign_release (info, ( (PyGPointer *) self)->pointer); @@ -40,7 +67,9 @@ _struct_dealloc (PyGIStruct *self) g_free ( ( (PyGPointer *) self)->pointer); } - g_base_info_unref (info); + if (info != NULL) { + g_base_info_unref (info); + } Py_TYPE( (PyGPointer *) self )->tp_free ( (PyObject *) self); } @@ -61,7 +90,7 @@ _struct_new (PyTypeObject *type, return NULL; } - info = _pygi_object_get_gi_info ( (PyObject *) type, &PyGIStructInfo_Type); + info = _struct_get_info ( (PyObject *) type ); if (info == NULL) { if (PyErr_ExceptionMatches (PyExc_AttributeError)) { PyErr_Format (PyExc_TypeError, "missing introspection information"); @@ -72,7 +101,7 @@ _struct_new (PyTypeObject *type, size = g_struct_info_get_size ( (GIStructInfo *) info); if (size == 0) { PyErr_Format (PyExc_TypeError, - "cannot allocate disguised struct %s.%s; consider adding a constructor to the library or to the overrides", + "struct cannot be created directly; try using a constructor, see: help(%s.%s)", g_base_info_get_namespace (info), g_base_info_get_name (info)); goto out; diff --git a/gi/pygi-type.c b/gi/pygi-type.c index dfaadb0..95f3c2c 100644 --- a/gi/pygi-type.c +++ b/gi/pygi-type.c @@ -99,61 +99,3 @@ _pygi_type_get_from_g_type (GType g_type) return py_type; } -/* _pygi_get_py_type_hint - * - * This gives a hint to what python type might be used as - * a particular gi type. - */ -PyObject * -_pygi_get_py_type_hint(GITypeTag type_tag) -{ - PyObject *type = Py_None; - - switch (type_tag) { - case GI_TYPE_TAG_BOOLEAN: - type = (PyObject *) &PyBool_Type; - break; - - case GI_TYPE_TAG_INT8: - case GI_TYPE_TAG_UINT8: - case GI_TYPE_TAG_INT16: - case GI_TYPE_TAG_UINT16: - case GI_TYPE_TAG_INT32: - case GI_TYPE_TAG_UINT32: - case GI_TYPE_TAG_INT64: - case GI_TYPE_TAG_UINT64: - type = (PyObject *) &PYGLIB_PyLong_Type; - break; - - case GI_TYPE_TAG_FLOAT: - case GI_TYPE_TAG_DOUBLE: - type = (PyObject *) &PyFloat_Type; - break; - - case GI_TYPE_TAG_GLIST: - case GI_TYPE_TAG_GSLIST: - case GI_TYPE_TAG_ARRAY: - type = (PyObject *) &PyList_Type; - break; - - case GI_TYPE_TAG_GHASH: - type = (PyObject *) &PyDict_Type; - break; - - case GI_TYPE_TAG_UTF8: - case GI_TYPE_TAG_FILENAME: - case GI_TYPE_TAG_UNICHAR: - type = (PyObject *) &PYGLIB_PyUnicode_Type; - break; - - case GI_TYPE_TAG_INTERFACE: - case GI_TYPE_TAG_GTYPE: - case GI_TYPE_TAG_ERROR: - case GI_TYPE_TAG_VOID: - break; - } - - Py_INCREF(type); - return type; -} - diff --git a/gi/pygi-type.h b/gi/pygi-type.h index 01b5994..1d225f0 100644 --- a/gi/pygi-type.h +++ b/gi/pygi-type.h @@ -39,8 +39,6 @@ PyObject *_pygi_type_import_by_gi_info (GIBaseInfo *info); PyObject *_pygi_type_get_from_g_type (GType g_type); -PyObject *_pygi_get_py_type_hint (GITypeTag type_tag); - G_END_DECLS #endif /* __PYGI_TYPE_H__ */ diff --git a/gi/types.py b/gi/types.py index 7c0f617..41efc05 100644 --- a/gi/types.py +++ b/gi/types.py @@ -28,6 +28,7 @@ import warnings from . import _gobject from ._gobject._gobject import GInterface from ._gobject.constants import TYPE_INVALID +from .docstring import generate_doc_string from ._gi import \ InterfaceInfo, \ @@ -196,6 +197,10 @@ class GObjectMeta(_gobject.GObjectMeta, MetaClassHelper): def mro(cls): return mro(cls) + @property + def __doc__(cls): + return generate_doc_string(cls.__info__) + def mro(C): """Compute the class precedence list (mro) according to C3, with GObject @@ -276,3 +281,7 @@ class StructMeta(type, MetaClassHelper): not method_info.get_arguments(): cls.__new__ = staticmethod(method_info) break + + @property + def __doc__(cls): + return generate_doc_string(cls.__info__) |