summaryrefslogtreecommitdiff
path: root/gi
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:40:19 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:40:22 +0900
commit9e05f0b92b0d6cde13d729955af7b911f79ba833 (patch)
treee9bf82708776e0eb586bb1e26742ad4e1c7c5f85 /gi
parentd7ab1229ba0f909c4a3ba445441a4c9f89d7b38d (diff)
downloadpygobject2-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.am20
-rw-r--r--gi/Makefile.in87
-rw-r--r--gi/docstring.py157
-rw-r--r--gi/module.py19
-rw-r--r--gi/overrides/GLib.py5
-rw-r--r--gi/overrides/GObject.py3
-rw-r--r--gi/overrides/Gdk.py10
-rw-r--r--gi/overrides/Gtk.py16
-rw-r--r--gi/overrides/Pango.py9
-rw-r--r--gi/overrides/__init__.py21
-rw-r--r--gi/pygi-boxed.c17
-rw-r--r--gi/pygi-info.c63
-rw-r--r--gi/pygi-marshal-from-py.c16
-rw-r--r--gi/pygi-struct.c41
-rw-r--r--gi/pygi-type.c58
-rw-r--r--gi/pygi-type.h2
-rw-r--r--gi/types.py9
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__)