script:
- bash -x ./.gitlab-ci/test-docker-old.sh
-gnome-runtime:
+gtk4:
stage: build_and_test
- image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.30
+ image: registry.gitlab.gnome.org/gnome/pygobject/gtk4:v1
script:
- - xvfb-run -a flatpak run --filesystem=host --share=network --socket=x11 --command=bash org.gnome.Sdk//3.30 -x .gitlab-ci/test-flatpak.sh
+ - bash -x ./.gitlab-ci/test-docker-gtk4.sh
+
+gnome-master:
+ allow_failure: true
+ stage: build_and_test
+ image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
+ script:
+ - xvfb-run -a flatpak run --filesystem=host --share=network --socket=x11 --command=bash org.gnome.Sdk//master -x .gitlab-ci/test-flatpak.sh
--- /dev/null
+FROM registry.gitlab.gnome.org/gnome/pygobject/main:v8
+
+USER root
+
+RUN python3 -m pip install meson
+
+ENV DEBIAN_FRONTEND noninteractive
+RUN apt-get update && apt-get install -y \
+ libfribidi-dev \
+ libgraphene-1.0-dev \
+ libgstreamer-plugins-bad1.0-dev \
+ libgtk-3-dev \
+ libwayland-dev \
+ libxml2-dev \
+ wayland-protocols \
+ && rm -rf /var/lib/apt/lists/*
+
+RUN git clone https://gitlab.freedesktop.org/wayland/wayland.git \
+ && cd wayland \
+ && git checkout 1.16.0 \
+ && ./autogen.sh --disable-documentation \
+ && make -j8 && make install \
+ && cd .. \
+ && rm -Rf wayland
+
+RUN git clone https://gitlab.gnome.org/GNOME/gtk.git \
+ && cd gtk \
+ && git checkout 833442e1e29e5 \
+ && meson -Dprefix=/usr -Dbuild-tests=false -Ddemos=false -Dbuild-examples=false -Dprint-backends=none _build \
+ && ninja -C _build \
+ && ninja -C _build install \
+ && cd .. \
+ && rm -Rf gtk
+
+USER user
+ENV PYENV_VERSION 3.7.0-debug
--- /dev/null
+#!/bin/bash
+
+set -e
+
+TAG="registry.gitlab.gnome.org/gnome/pygobject/gtk4:v1"
+
+sudo docker build --tag "${TAG}" --file "Dockerfile.gtk4" .
+sudo docker run --rm --security-opt label=disable \
+ --volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \
+ --tty --interactive "${TAG}" bash
--- /dev/null
+#!/bin/bash
+
+set -e
+
+# ccache setup
+mkdir -p _ccache
+export CCACHE_BASEDIR="$(pwd)"
+export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
+
+# test
+python -m pip install git+https://github.com/pygobject/pycairo.git
+python -m pip install pytest pytest-faulthandler
+g-ir-inspect Gtk --version=4.0 --print-typelibs
+export TEST_GTK_VERSION=4.0
+xvfb-run -a python setup.py test
meson _build -Dpython="$(which python)"
fi
ninja -C _build
-xvfb-run -a meson test --timeout-multiplier 4 -C _build -v
+xvfb-run -a meson test -C _build -v
rm -Rf _build
# CODE QUALITY
git \
perl
+# https://github.com/Alexpux/MINGW-packages/issues/4333
+pacman --noconfirm -S --needed mingw-w64-$MSYS2_ARCH-$PYTHON-pathlib2
+
# ccache setup
export PATH="$MSYSTEM/lib/ccache/bin:$PATH"
mkdir -p _ccache
$PYTHON setup.py build_tests
MSYSTEM= $PYTHON -m coverage run tests/runtests.py
-# FIXME: lcov doesn't support gcc9
-#~ curl -O -J -L "https://github.com/linux-test-project/lcov/archive/master.tar.gz"
-#~ tar -xvzf lcov-master.tar.gz
+curl -O -J -L "https://github.com/linux-test-project/lcov/archive/master.tar.gz"
+tar -xvzf lcov-master.tar.gz
-#~ ./lcov-master/bin/lcov \
- #~ --rc lcov_branch_coverage=1 --no-external \
- #~ --directory . --capture --output-file \
- #~ "${COV_DIR}/${COV_KEY}.lcov"
+./lcov-master/bin/lcov \
+ --rc lcov_branch_coverage=1 --no-external \
+ --directory . --capture --output-file \
+ "${COV_DIR}/${COV_KEY}.lcov"
include setup.cfg
+include pyproject.toml
include COPYING
include *.in
include NEWS
-3.30.5 - 2019-06-16
--------------------
-
-* tests/gimarshallingtestsextra.c/h: relicense to LGPLv2.1+ :issue:`320`
-* Fix a crash when marshalling a GError to Python fails :mr:`115`
-* Fix leak of transfer-full/container C arrays :mr:`117` (:user:`Tomasz Miąsko <tmiasko>`)
-* Python 3.8b1 compatibility fixes
-
-
-3.30.4 - 2018-11-30
--------------------
-
-* gtk overrides: Fix rows getting inserted on the wrong level with
- TreeStore.insert_before/inster_after if parent=None.
- :issue:`281` (3.30 regression, thanks to :user:`Cian Wilson <cianwilson>`
- for the report)
-
-
-3.30.3 - 2018-11-27
--------------------
-
-* GValue: fall back to the custom C marshaller to support fundamental types.
- This makes GValue work with GstFraction. :issue:`280`
-* GValue: Work around wrong annotations for GVariant
-* Fix GObject attribute access during instance init which can lead to errors
- with __getattr__ implementations of subclasses. This lead to criticals when
- instantiating Gio.DBusProxy. :issue:`267`
+3.31.1 - 2018-11-17
+-------------------
+
+* Changes included in 3.30.2
+* overrides: add Pango.Layout.set_text() override. :issue:`259` :mr:`89`
+* docs: link updates :mr:`93` (:user:`tijder`)
+* overrides: Use functools.wraps instead of custom version.
+ :issue:`271` :mr:`95` (:user:`Kai Willadsen <kaiw>`)
+* tests: Make tests run with current gtk4 master
+* Add (again) a pyproject.toml for specifying the pycairo build dep
+ (requires pip >=18.0)
+* setup.py: Make it possible to build without cairo support through the
+ PYGOBJECT_WITHOUT_PYCAIRO env var. :issue:`250`
3.30.2 - 2018-11-11
Platform: POSIX, Windows
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)
+Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
Classifier: Operating System :: POSIX
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: C
.. code:: console
- sudo zypper install -y python3-venv python3-wheel gobject-introspection \
+ sudo zypper install -y python3-venv python3-wheel gobject-introspection-devel \
python3-cairo-devel openssl zlib git
sudo zypper install --type pattern devel_basis
* `GNOME Music <https://wiki.gnome.org/Apps/Music>`__ - a music player for GNOME
* `GNOME Tweak Tool <https://wiki.gnome.org/action/show/Apps/GnomeTweakTool>`__ - a tool to customize advanced GNOME 3 options
* `Gramps <https://gramps-project.org/>`__ - a genealogy program
-* `Lollypop <https://gnumdk.github.io/lollypop-web/>`__ - a modern music player
+* `Lollypop <https://wiki.gnome.org/Apps/Lollypop>`__ - a modern music player
* `Meld <http://meldmerge.org/>`__ - a visual diff and merge tool
* `MyPaint <http://mypaint.org/>`__ - a nimble, distraction-free, and easy tool for digital painters
* `Orca <https://wiki.gnome.org/Projects/Orca>`__ - a flexible and extensible screen reader
except OSError:
return None
mode = filestat.st_mode
- if column == 0:
+ if column is 0:
if stat.S_ISDIR(mode):
return folderpb
else:
return filepb
- elif column == 1:
+ elif column is 1:
return rowref
- elif column == 2:
+ elif column is 2:
return filestat.st_size
- elif column == 3:
+ elif column is 3:
return oct(stat.S_IMODE(mode))
return time.ctime(filestat.st_mtime)
except OSError:
return None
mode = filestat.st_mode
- if column == 0:
+ if column is 0:
if stat.S_ISDIR(mode):
return folderpb
else:
return filepb
- elif column == 1:
+ elif column is 1:
return os.path.basename(relpath)
- elif column == 2:
+ elif column is 2:
return filestat.st_size
- elif column == 3:
+ elif column is 3:
return oct(stat.S_IMODE(mode))
return time.ctime(filestat.st_mtime)
}
/* XXX: used for Gtk.Template */
- if (PyObject_HasAttrString ((PyObject*) Py_TYPE (wrapper), "__dontuse_ginstance_init__")) {
+ if (PyObject_HasAttrString (wrapper, "__dontuse_ginstance_init__")) {
result = PyObject_CallMethod (wrapper, "__dontuse_ginstance_init__", NULL);
if (result == NULL)
PyErr_Print ();
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
+import functools
import warnings
from collections import namedtuple
-import gi.overrides
import gi.module
from gi.overrides import override, deprecated_attr
from gi.repository import GLib
elif gtype == TYPE_PYOBJECT:
self.set_boxed(py_value)
else:
- # Fall back to _gvalue_set which handles some more cases
- # like fundamentals for which a converter is registered
- _gi._gvalue_set(self, py_value)
+ raise TypeError("Unknown value type %s" % gtype)
def get_value(self):
gtype = self.g_type
elif gtype == TYPE_GTYPE:
return self.get_gtype()
elif gtype == TYPE_VARIANT:
- # get_variant was missing annotations
- # https://gitlab.gnome.org/GNOME/glib/merge_requests/492
- return self.dup_variant()
+ return self.get_variant()
elif gtype == TYPE_PYOBJECT:
- return self.get_boxed()
- elif gtype == _gi.TYPE_INVALID:
- return None
+ pass
else:
- return _gi._gvalue_get(self)
+ return None
def __repr__(self):
return '<Value (%s) %s>' % (self.g_type.name, self.get_value())
# 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)
- @gi.overrides.wraps(func)
+ @functools.wraps(func)
def meth(*args, **kwargs):
return func(*args, **kwargs)
return meth
Drawable = override(Drawable)
__all__.append('Drawable')
-else:
+elif Gdk._version == '3.0':
class Window(Gdk.Window):
def __new__(cls, parent, attributes, attributes_mask):
# Gdk.Window had to be made abstract,
Gdk.EventType._2BUTTON_PRESS = getattr(Gdk.EventType, "2BUTTON_PRESS")
Gdk.EventType._3BUTTON_PRESS = getattr(Gdk.EventType, "3BUTTON_PRESS")
-
-class Event(Gdk.Event):
- _UNION_MEMBERS = {
- Gdk.EventType.DELETE: 'any',
- Gdk.EventType.DESTROY: 'any',
- Gdk.EventType.EXPOSE: 'expose',
- Gdk.EventType.MOTION_NOTIFY: 'motion',
- Gdk.EventType.BUTTON_PRESS: 'button',
- Gdk.EventType.BUTTON_RELEASE: 'button',
- Gdk.EventType.KEY_PRESS: 'key',
- Gdk.EventType.KEY_RELEASE: 'key',
- Gdk.EventType.ENTER_NOTIFY: 'crossing',
- Gdk.EventType.LEAVE_NOTIFY: 'crossing',
- Gdk.EventType.FOCUS_CHANGE: 'focus_change',
- Gdk.EventType.CONFIGURE: 'configure',
- Gdk.EventType.MAP: 'any',
- Gdk.EventType.UNMAP: 'any',
- Gdk.EventType.PROXIMITY_IN: 'proximity',
- Gdk.EventType.PROXIMITY_OUT: 'proximity',
- Gdk.EventType.DRAG_ENTER: 'dnd',
- Gdk.EventType.DRAG_LEAVE: 'dnd',
- Gdk.EventType.DRAG_MOTION: 'dnd',
- Gdk.EventType.DROP_START: 'dnd',
- }
-
- if Gdk._version in ("2.0", "3.0"):
- _UNION_MEMBERS.update({
+ class Event(Gdk.Event):
+ _UNION_MEMBERS = {
+ Gdk.EventType.DELETE: 'any',
+ Gdk.EventType.DESTROY: 'any',
+ Gdk.EventType.MOTION_NOTIFY: 'motion',
+ Gdk.EventType.BUTTON_PRESS: 'button',
+ Gdk.EventType.BUTTON_RELEASE: 'button',
+ Gdk.EventType.KEY_PRESS: 'key',
+ Gdk.EventType.KEY_RELEASE: 'key',
+ Gdk.EventType.ENTER_NOTIFY: 'crossing',
+ Gdk.EventType.LEAVE_NOTIFY: 'crossing',
+ Gdk.EventType.FOCUS_CHANGE: 'focus_change',
+ Gdk.EventType.CONFIGURE: 'configure',
+ Gdk.EventType.PROXIMITY_IN: 'proximity',
+ Gdk.EventType.PROXIMITY_OUT: 'proximity',
+ Gdk.EventType.DRAG_ENTER: 'dnd',
+ Gdk.EventType.DRAG_LEAVE: 'dnd',
+ Gdk.EventType.DRAG_MOTION: 'dnd',
+ Gdk.EventType.DROP_START: 'dnd',
Gdk.EventType._2BUTTON_PRESS: 'button',
Gdk.EventType._3BUTTON_PRESS: 'button',
Gdk.EventType.PROPERTY_NOTIFY: 'property',
Gdk.EventType.DROP_FINISHED: 'dnd',
Gdk.EventType.CLIENT_EVENT: 'client',
Gdk.EventType.VISIBILITY_NOTIFY: 'visibility',
- })
-
- if Gdk._version == '2.0':
- _UNION_MEMBERS[Gdk.EventType.NO_EXPOSE] = 'no_expose'
-
- if hasattr(Gdk.EventType, 'TOUCH_BEGIN'):
- _UNION_MEMBERS.update(
- {
- Gdk.EventType.TOUCH_BEGIN: 'touch',
- Gdk.EventType.TOUCH_UPDATE: 'touch',
- Gdk.EventType.TOUCH_END: 'touch',
- Gdk.EventType.TOUCH_CANCEL: 'touch',
- })
-
- def __getattr__(self, name):
- real_event = getattr(self, '_UNION_MEMBERS').get(self.type)
- if real_event:
- return getattr(getattr(self, real_event), name)
- else:
- raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
-
- def __setattr__(self, name, value):
- real_event = getattr(self, '_UNION_MEMBERS').get(self.type)
- if real_event:
- setattr(getattr(self, real_event), name, value)
- else:
- Gdk.Event.__setattr__(self, name, value)
-
- def __repr__(self):
- base_repr = Gdk.Event.__repr__(self).strip("><")
- return "<%s type=%r>" % (base_repr, self.type)
-
-
-Event = override(Event)
-__all__.append('Event')
-
-# manually bind GdkEvent members to GdkEvent
-
-modname = globals()['__name__']
-module = sys.modules[modname]
-
-# right now we can't get the type_info from the
-# field info so manually list the class names
-event_member_classes = ['EventAny',
- 'EventExpose',
- 'EventMotion',
- 'EventButton',
- 'EventScroll',
- 'EventKey',
- 'EventCrossing',
- 'EventFocus',
- 'EventConfigure',
- 'EventProximity',
- 'EventDND',
- 'EventSetting',
- 'EventGrabBroken']
-
-if Gdk._version in ("2.0", "3.0"):
- event_member_classes.extend([
- 'EventVisibility',
- 'EventProperty',
- 'EventSelection',
- 'EventOwnerChange',
- 'EventWindowState',
- 'EventVisibility',
- ])
-
-if Gdk._version == '2.0':
- event_member_classes.append('EventNoExpose')
-
-if hasattr(Gdk, 'EventTouch'):
- event_member_classes.append('EventTouch')
-
-
-# whitelist all methods that have a success return we want to mask
-gsuccess_mask_funcs = ['get_state',
- 'get_axis',
- 'get_coords',
- 'get_root_coords']
-
-
-for event_class in event_member_classes:
- override_class = type(event_class, (getattr(Gdk, event_class),), {})
- # add the event methods
- for method_info in Gdk.Event.__info__.get_methods():
- name = method_info.get_name()
- event_method = getattr(Gdk.Event, name)
- # python2 we need to use the __func__ attr to avoid internal
- # instance checks
- event_method = getattr(event_method, '__func__', event_method)
-
- # use the _gsuccess_mask decorator if this method is whitelisted
- if name in gsuccess_mask_funcs:
- event_method = strip_boolean_result(event_method)
- setattr(override_class, name, event_method)
-
- setattr(module, event_class, override_class)
- __all__.append(event_class)
-
-# end GdkEvent overrides
-
-
-class DragContext(Gdk.DragContext):
- def finish(self, success, del_, time):
- Gtk = get_introspection_module('Gtk')
- Gtk.drag_finish(self, success, del_, time)
+ Gdk.EventType.EXPOSE: 'expose',
+ Gdk.EventType.MAP: 'any',
+ Gdk.EventType.UNMAP: 'any',
+ }
+
+ if Gdk._version == '2.0':
+ _UNION_MEMBERS[Gdk.EventType.NO_EXPOSE] = 'no_expose'
+
+ if hasattr(Gdk.EventType, 'TOUCH_BEGIN'):
+ _UNION_MEMBERS.update(
+ {
+ Gdk.EventType.TOUCH_BEGIN: 'touch',
+ Gdk.EventType.TOUCH_UPDATE: 'touch',
+ Gdk.EventType.TOUCH_END: 'touch',
+ Gdk.EventType.TOUCH_CANCEL: 'touch',
+ })
+
+ def __getattr__(self, name):
+ real_event = getattr(self, '_UNION_MEMBERS').get(self.type)
+ if real_event:
+ return getattr(getattr(self, real_event), name)
+ else:
+ raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
+
+ def __setattr__(self, name, value):
+ real_event = getattr(self, '_UNION_MEMBERS').get(self.type)
+ if real_event:
+ setattr(getattr(self, real_event), name, value)
+ else:
+ Gdk.Event.__setattr__(self, name, value)
+ def __repr__(self):
+ base_repr = Gdk.Event.__repr__(self).strip("><")
+ return "<%s type=%r>" % (base_repr, self.type)
+
+ Event = override(Event)
+ __all__.append('Event')
+
+ # manually bind GdkEvent members to GdkEvent
+
+ modname = globals()['__name__']
+ module = sys.modules[modname]
+
+ # right now we can't get the type_info from the
+ # field info so manually list the class names
+ event_member_classes = ['EventAny',
+ 'EventExpose',
+ 'EventMotion',
+ 'EventButton',
+ 'EventScroll',
+ 'EventKey',
+ 'EventCrossing',
+ 'EventFocus',
+ 'EventConfigure',
+ 'EventProximity',
+ 'EventDND',
+ 'EventSetting',
+ 'EventGrabBroken',
+ 'EventVisibility',
+ 'EventProperty',
+ 'EventSelection',
+ 'EventOwnerChange',
+ 'EventWindowState',
+ 'EventVisibility']
-DragContext = override(DragContext)
-__all__.append('DragContext')
+ if Gdk._version == '2.0':
+ event_member_classes.append('EventNoExpose')
+
+ if hasattr(Gdk, 'EventTouch'):
+ event_member_classes.append('EventTouch')
+
+ # whitelist all methods that have a success return we want to mask
+ gsuccess_mask_funcs = ['get_state',
+ 'get_axis',
+ 'get_coords',
+ 'get_root_coords']
+
+ for event_class in event_member_classes:
+ override_class = type(event_class, (getattr(Gdk, event_class),), {})
+ # add the event methods
+ for method_info in Gdk.Event.__info__.get_methods():
+ name = method_info.get_name()
+ event_method = getattr(Gdk.Event, name)
+ # python2 we need to use the __func__ attr to avoid internal
+ # instance checks
+ event_method = getattr(event_method, '__func__', event_method)
+
+ # use the _gsuccess_mask decorator if this method is whitelisted
+ if name in gsuccess_mask_funcs:
+ event_method = strip_boolean_result(event_method)
+ setattr(override_class, name, event_method)
+
+ setattr(module, event_class, override_class)
+ __all__.append(event_class)
+
+ # end GdkEvent overrides
+
+ class DragContext(Gdk.DragContext):
+ def finish(self, success, del_, time):
+ Gtk = get_introspection_module('Gtk')
+ Gtk.drag_finish(self, success, del_, time)
+
+ DragContext = override(DragContext)
+ __all__.append('DragContext')
class Cursor(Gdk.Cursor):
super(Widget, self).freeze_child_notify()
return _FreezeNotifyManager(self)
- 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))
- super(Widget, self).drag_dest_set_target_list(target_list)
-
- def drag_source_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))
- super(Widget, self).drag_source_set_target_list(target_list)
+ if Gtk._version != "4.0":
+ 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))
+ super(Widget, self).drag_dest_set_target_list(target_list)
+
+ if Gtk._version != "4.0":
+ def drag_source_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))
+ super(Widget, self).drag_source_set_target_list(target_list)
def style_get_property(self, property_name, value=None):
if value is None:
# alias for Python 2.x object protocol
__nonzero__ = __bool__
- get_focus_chain = strip_boolean_result(Gtk.Container.get_focus_chain)
-
def child_get_property(self, child, property_name, value=None):
if value is None:
prop = self.find_child_property(property_name)
Gtk.Container.child_get_property(self, child, property_name, value)
return value.get_value()
- def child_get(self, child, *prop_names):
- """Returns a list of child property values for the given names."""
- return [self.child_get_property(child, name) for name in prop_names]
+ if Gtk._version in ("2.0", "3.0"):
+ def child_get(self, child, *prop_names):
+ """Returns a list of child property values for the given names."""
+ return [self.child_get_property(child, name) for name in prop_names]
+
+ def child_set(self, child, **kwargs):
+ """Set a child properties on the given child to key/value pairs."""
+ for name, value in kwargs.items():
+ name = name.replace('_', '-')
+ self.child_set_property(child, name, value)
- def child_set(self, child, **kwargs):
- """Set a child properties on the given child to key/value pairs."""
- for name, value in kwargs.items():
- name = name.replace('_', '-')
- self.child_set_property(child, name, value)
+ get_focus_chain = strip_boolean_result(Gtk.Container.get_focus_chain)
Container = override(Container)
if sibling is None:
position = -1
else:
- if parent is None:
- parent = self.iter_parent(sibling)
position = self.get_path(sibling).get_indices()[-1]
return self._do_insert(parent, position, row)
if sibling is None:
position = 0
else:
- if parent is None:
- parent = self.iter_parent(sibling)
position = self.get_path(sibling).get_indices()[-1] + 1
return self._do_insert(parent, position, row)
def set_markup(self, text, length=-1):
super(Layout, self).set_markup(text, length)
+ def set_text(self, text, length=-1):
+ super(Layout, self).set_text(text, length)
+
Layout = override(Layout)
__all__.append('Layout')
+import functools
import types
import warnings
import importlib
_deprecated_attrs = {}
-def wraps(wrapped):
- def assign(wrapper):
- wrapper.__name__ = wrapped.__name__
- wrapper.__module__ = wrapped.__module__
- return wrapper
- return assign
-
-
class OverridesProxyModule(types.ModuleType):
"""Wraps a introspection module and contains all overrides"""
def deprecated(fn, replacement):
"""Decorator for marking methods and classes as deprecated"""
- @wraps(fn)
+ @functools.wraps(fn)
def wrapped(*args, **kwargs):
warnings.warn('%s is deprecated; use %s instead' % (fn.__name__, replacement),
PyGIDeprecationWarning, stacklevel=2)
several out arguments. Translate such a method to return the out arguments
on success and None on failure.
"""
- @wraps(method)
+ @functools.wraps(method)
def wrapped(*args, **kwargs):
ret = method(*args, **kwargs)
if ret[0]:
return;
free_array = TRUE;
- free_array_full = arg_cache->transfer != GI_TRANSFER_NOTHING;
+ free_array_full = FALSE;
} else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
ptr_array_ = (GPtrArray *) data;
} else {
*
* Checks to see if @error has been set. If @error has been set, then a
* GLib.GError Python exception object is returned (but not raised).
- * If not error is set returns Py_None.
*
- * Returns: a GLib.GError Python exception object, or Py_None,
- * or NULL and sets an error if creating the exception object fails.
+ * Returns: a GLib.GError Python exception object, or NULL.
*/
PyObject *
pygi_error_marshal_to_py (GError **error)
g_return_val_if_fail(error != NULL, NULL);
if (*error == NULL)
- Py_RETURN_NONE;
+ return NULL;
state = PyGILState_Ensure();
state = PyGILState_Ensure();
exc_instance = pygi_error_marshal_to_py (error);
- if (exc_instance != NULL) {
- PyErr_SetObject(PyGError, exc_instance);
- Py_DECREF(exc_instance);
- } else {
- PyErr_Print ();
- PyErr_SetString (PyExc_RuntimeError, "Converting the GError failed");
- }
+ PyErr_SetObject(PyGError, exc_instance);
+ Py_DECREF(exc_instance);
g_clear_error(error);
PyGILState_Release(state);
g_error_free (error);
}
- return py_obj;
+ if (py_obj != NULL) {
+ return py_obj;
+ } else {
+ Py_RETURN_NONE;
+ }
}
static gboolean
{
GError *gerror = (GError *) g_value_get_boxed (value);
PyObject *pyerr = pygi_error_marshal_to_py (&gerror);
- return pyerr;
+ if (pyerr == NULL) {
+ Py_RETURN_NONE;
+ } else {
+ return pyerr;
+ }
}
static int
offsetof(PyTypeObject, tp_iter),
offsetof(PyTypeObject, tp_repr),
offsetof(PyTypeObject, tp_str),
-#if PY_VERSION_HEX < 0x03000000
- offsetof(PyTypeObject, tp_print),
-#endif
- };
+ offsetof(PyTypeObject, tp_print) };
gsize i;
/* Happens when registering gobject.GObject itself, at least. */
project('pygobject', 'c',
- version : '3.30.5',
+ version : '3.31.1',
meson_version : '>= 0.46.0',
default_options : [ 'warning_level=1',
'buildtype=debugoptimized'])
'-Wall',
'-Warray-bounds',
'-Wcast-align',
+ '-Wdeclaration-after-statement',
'-Wduplicated-branches',
'-Wextra',
'-Wformat=2',
'-Wsign-compare',
'-Wstrict-aliasing',
'-Wstrict-prototypes',
- '-Wswitch-default',
'-Wundef',
'-Wunused-but-set-variable',
'-Wwrite-strings',
]
- if python.language_version().split('.')[0] == '2'
- main_c_args += [
- '-Wdeclaration-after-statement',
- ]
- endif
-
main_c_args += [
'-Wno-incompatible-pointer-types-discards-qualifiers',
'-Wno-missing-field-initializers',
'-fvisibility=hidden',
]
+ if not ['3.3', '3.4'].contains(python.language_version())
+ main_c_args += [
+ '-Wswitch-default',
+ ]
+ endif
+
main_c_args = cc.get_supported_arguments(main_c_args)
endif
--- /dev/null
+[build-system]
+requires = ["setuptools", "wheel", "pycairo"]
from distutils.spawn import find_executable
-PYGOBJECT_VERSION = "3.30.5"
+PYGOBJECT_VERISON = "3.31.1"
GLIB_VERSION_REQUIRED = "2.38.0"
GI_VERSION_REQUIRED = "1.46.0"
PYCAIRO_VERSION_REQUIRED = "1.11.1"
LIBFFI_VERSION_REQUIRED = "3.0"
+WITH_CAIRO = not bool(os.environ.get("PYGOBJECT_WITHOUT_PYCAIRO"))
+"""Set PYGOBJECT_WITHOUT_PYCAIRO if you don't want to build with
+cairo/pycairo support. Note that this option might get removed in the future.
+"""
+
def is_dev_version():
- version = tuple(map(int, PYGOBJECT_VERSION.split(".")))
+ version = tuple(map(int, PYGOBJECT_VERISON.split(".")))
return version[1] % 2 != 0
def get_versions():
- version = PYGOBJECT_VERSION.split(".")
+ version = PYGOBJECT_VERISON.split(".")
assert len(version) == 3
versions = {
def run(self):
# Don't use PEP 440 pre-release versions for GNOME releases
- self.distribution.metadata.version = PYGOBJECT_VERSION
+ self.distribution.metadata.version = PYGOBJECT_VERISON
dist_dir = tempfile.mkdtemp()
try:
self.build_temp = None
self.build_base = None
self.force = False
- self.extra_defines = []
def finalize_options(self):
self.set_undefined_options(
# MSVC: We need to define _GI_EXTERN explcitly so that
# symbols get exported properly
if compiler.compiler_type == "msvc":
- self.extra_defines = [('_GI_EXTERN',
- '__declspec(dllexport)extern')]
+ extra_defines = [('_GI_EXTERN',
+ '__declspec(dllexport)extern')]
+ else:
+ extra_defines = []
objects = compiler.compile(
ext.sources,
output_dir=self.build_temp,
include_dirs=ext.include_dirs,
- macros=self.extra_defines)
+ macros=ext.define_macros + extra_defines)
if os.name == "nt":
if compiler.compiler_type == "msvc":
"--output=%s" % typelib_path,
])
+ regress_macros = []
+ if not WITH_CAIRO:
+ regress_macros.append(("_GI_DISABLE_CAIRO", "1"))
+
ext = Extension(
name='libregress',
sources=[
os.path.join(gi_tests_dir, "regress.h"),
os.path.join(tests_dir, "regressextra.h"),
],
+ define_macros=regress_macros,
)
add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
- add_ext_pkg_config_dep(ext, compiler.compiler_type, "cairo")
- add_ext_pkg_config_dep(ext, compiler.compiler_type, "cairo-gobject")
+ if WITH_CAIRO:
+ add_ext_pkg_config_dep(ext, compiler.compiler_type, "cairo")
+ add_ext_pkg_config_dep(
+ ext, compiler.compiler_type, "cairo-gobject")
ext_paths = build_ext(ext)
# We want to always use POSIX-style paths for g-ir-compiler
typelib_path = posixpath.join(tests_dir, "Regress-1.0.typelib")
regress_g_ir_scanner_cmd = g_ir_scanner_cmd + [
"--no-libtool",
- "--include=cairo-1.0",
"--include=Gio-2.0",
"--namespace=Regress",
"--nsversion=1.0",
"--pkg=gio-2.0"]
if self._newer_group(ext_paths, gir_path):
- # MSVC: We don't normally have the pkg-config files for
- # cairo and cairo-gobject, so use --extra-library
- # instead of --pkg to pass those to the linker, so that
- # g-ir-scanner won't fail due to linker errors
- if compiler.compiler_type == "msvc":
- regress_g_ir_scanner_cmd += [
- "--extra-library=cairo",
- "--extra-library=cairo-gobject"]
+ if WITH_CAIRO:
+ regress_g_ir_scanner_cmd += ["--include=cairo-1.0"]
+ # MSVC: We don't normally have the pkg-config files for
+ # cairo and cairo-gobject, so use --extra-library
+ # instead of --pkg to pass those to the linker, so that
+ # g-ir-scanner won't fail due to linker errors
+ if compiler.compiler_type == "msvc":
+ regress_g_ir_scanner_cmd += [
+ "--extra-library=cairo",
+ "--extra-library=cairo-gobject"]
+ else:
+ regress_g_ir_scanner_cmd += [
+ "--pkg=cairo",
+ "--pkg=cairo-gobject"]
else:
- regress_g_ir_scanner_cmd += [
- "--pkg=cairo",
- "--pkg=cairo-gobject"]
+ regress_g_ir_scanner_cmd += ["-D_GI_DISABLE_CAIRO"]
regress_g_ir_scanner_cmd += ["--output=%s" % gir_path]
)
add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
- add_ext_pkg_config_dep(ext, compiler.compiler_type, "cairo")
add_ext_compiler_flags(ext, compiler)
dist = Distribution({"ext_modules": [ext]})
"-Wall",
"-Warray-bounds",
"-Wcast-align",
+ "-Wdeclaration-after-statement",
"-Wduplicated-branches",
"-Wextra",
"-Wformat=2",
"-Wsign-compare",
"-Wstrict-aliasing",
"-Wstrict-prototypes",
- "-Wswitch-default",
"-Wundef",
"-Wunused-but-set-variable",
"-Wwrite-strings",
]
- if sys.version_info[0] == 2:
+ if sys.version_info[:2] != (3, 4):
args += [
- "-Wdeclaration-after-statement",
+ "-Wswitch-default",
]
args += [
add_dependency(gi_ext, "libffi")
add_ext_compiler_flags(gi_ext, compiler)
- gi_cairo_ext = ext["gi._gi_cairo"]
- add_dependency(gi_cairo_ext, "glib-2.0")
- add_dependency(gi_cairo_ext, "gio-2.0")
- add_dependency(gi_cairo_ext, "gobject-introspection-1.0")
- add_dependency(gi_cairo_ext, "libffi")
- add_dependency(gi_cairo_ext, "cairo")
- add_dependency(gi_cairo_ext, "cairo-gobject")
- add_pycairo(gi_cairo_ext)
- add_ext_compiler_flags(gi_cairo_ext, compiler)
+ if WITH_CAIRO:
+ gi_cairo_ext = ext["gi._gi_cairo"]
+ add_dependency(gi_cairo_ext, "glib-2.0")
+ add_dependency(gi_cairo_ext, "gio-2.0")
+ add_dependency(gi_cairo_ext, "gobject-introspection-1.0")
+ add_dependency(gi_cairo_ext, "libffi")
+ add_dependency(gi_cairo_ext, "cairo")
+ add_dependency(gi_cairo_ext, "cairo-gobject")
+ add_pycairo(gi_cairo_ext)
+ add_ext_compiler_flags(gi_cairo_ext, compiler)
def run(self):
self._write_config_h()
"includedir": "${prefix}/include",
"datarootdir": "${prefix}/share",
"datadir": "${datarootdir}",
- "VERSION": PYGOBJECT_VERSION,
+ "VERSION": PYGOBJECT_VERISON,
}
for key, value in config.items():
content = content.replace("@%s@" % key, value)
with io.open(readme, encoding="utf-8") as h:
long_description = h.read()
+ ext_modules = []
+ install_requires = []
+
gi_ext = Extension(
name='gi._gi',
sources=sorted(sources),
depends=list_headers(script_dir) + list_headers(gi_dir),
define_macros=[("PY_SSIZE_T_CLEAN", None)],
)
-
- gi_cairo_ext = Extension(
- name='gi._gi_cairo',
- sources=cairo_sources,
- include_dirs=[script_dir, gi_dir],
- depends=list_headers(script_dir) + list_headers(gi_dir),
- define_macros=[("PY_SSIZE_T_CLEAN", None)],
- )
+ ext_modules.append(gi_ext)
+
+ if WITH_CAIRO:
+ gi_cairo_ext = Extension(
+ name='gi._gi_cairo',
+ sources=cairo_sources,
+ include_dirs=[script_dir, gi_dir],
+ depends=list_headers(script_dir) + list_headers(gi_dir),
+ define_macros=[("PY_SSIZE_T_CLEAN", None)],
+ )
+ ext_modules.append(gi_cairo_ext)
+ install_requires.append(
+ "pycairo>=%s" % get_version_requirement(
+ get_pycairo_pkg_config_name()))
version = pkginfo["Version"]
if is_dev_version():
"gi.repository",
"gi.overrides",
],
- ext_modules=[
- gi_ext,
- gi_cairo_ext,
- ],
+ ext_modules=ext_modules,
cmdclass={
"build_ext": build_ext,
"distcheck": distcheck,
"install": install,
"install_pkgconfig": install_pkgconfig,
},
- install_requires=[
- "pycairo>=%s" % get_version_requirement(
- get_pycairo_pkg_config_name()),
- ],
+ install_requires=install_requires,
data_files=[
('include/pygobject-3.0', ['gi/pygobject.h']),
],
# always on for the tests.
warnings.simplefilter('default', gi.PyGIDeprecationWarning)
+ # Otherwise we crash on the first gtk use when e.g. DISPLAY isn't set
+ try:
+ from gi.repository import Gtk
+ except ImportError:
+ pass
+ else:
+ if Gtk._version == "4.0":
+ res = Gtk.init_check()
+ else:
+ res = Gtk.init_check([])[0]
+ if not res:
+ raise RuntimeError("Gtk available, but Gtk.init_check() failed")
+
init_test_environ()
*
* Copyright (C) 2016 Thibault Saunier <tsaunier@gnome.org>
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gimarshallingtestsextra.h"
*
* Copyright (C) 2016 Thibault Saunier <tsaunier@gnome.org>
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EXTRA_TESTS
@unittest.skipUnless(Gdk, 'Gdk not available')
+@unittest.skipIf(Gdk._version == "4.0", 'Gdk4 doesn\'t have GdkAtom')
class TestGdkAtom(unittest.TestCase):
def test_create(self):
atom = Gdk.Atom.intern('my_string', False)
@unittest.skipUnless(has_cairo, 'built without cairo support')
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestPango(unittest.TestCase):
+
def test_cairo_font_options(self):
- screen = Gtk.Window().get_screen()
- font_opts = screen.get_font_options()
+ window = Gtk.Window()
+ if Gtk._version == "4.0":
+ window.set_font_options(cairo.FontOptions())
+ font_opts = window.get_font_options()
+ else:
+ screen = window.get_screen()
+ font_opts = screen.get_font_options()
+ assert font_opts is not None
self.assertTrue(isinstance(font_opts.get_subpixel_order(), int))
self.assertTrue(isinstance(data['error'], Exception))
self.assertTrue('InvalidArgs' in str(data['error']), str(data['error']))
-
- def test_instantiate_custom_proxy(self):
- class SomeProxy(Gio.DBusProxy):
- def __init__(self):
- Gio.DBusProxy.__init__(self)
-
- SomeProxy()
with pytest.raises(TypeError, match=".*on Widgets.*"):
Gtk.Template.from_string("")(object())
+
+@pytest.mark.skipif(Gtk._version == "4.0", reason="errors out first with gtk4")
+def test_subclass_fail():
@Gtk.Template.from_string("")
class Base(Gtk.Widget):
__gtype_name__ = new_gtype_name()
self.assertEqual(tuple(Gdk.RGBA(0.1, 0.2, 0.3, 0.4)),
(0.1, 0.2, 0.3, 0.4))
+ @unittest.skipIf(Gdk_version == "4.0", "not in gdk4")
def test_event(self):
event = Gdk.Event.new(Gdk.EventType.CONFIGURE)
self.assertEqual(event.type, Gdk.EventType.CONFIGURE)
event.type = Gdk.EventType.SCROLL
self.assertRaises(AttributeError, lambda: getattr(event, 'foo_bar'))
+ @unittest.skipIf(Gdk_version == "4.0", "not in gdk4")
def test_event_touch(self):
event = Gdk.Event.new(Gdk.EventType.TOUCH_BEGIN)
self.assertEqual(event.type, Gdk.EventType.TOUCH_BEGIN)
self.assertTrue(event.emulating_pointer)
self.assertTrue(event.touch.emulating_pointer)
+ @unittest.skipIf(Gdk_version == "4.0", "not in gdk4")
def test_event_setattr(self):
event = Gdk.Event.new(Gdk.EventType.DRAG_MOTION)
event.x_root, event.y_root = 0, 5
self.assertFalse(hasattr(event, "foo_bar"))
event.foo_bar = 42
+ @unittest.skipIf(Gdk_version == "4.0", "not in gdk4")
def test_event_repr(self):
event = Gdk.Event.new(Gdk.EventType.CONFIGURE)
self.assertTrue("CONFIGURE" in repr(event))
import contextlib
import unittest
+import time
import sys
import gc
import warnings
-import timeit
from .helper import ignore_gi_deprecation_warnings, capture_glib_warnings
Gtk.get_micro_version())
+GTK4 = (Gtk._version == "4.0")
+
+
@contextlib.contextmanager
def realized(widget):
"""Makes sure the widget is realized.
if isinstance(widget, Gtk.Window):
toplevel = widget
else:
- toplevel = widget.get_parent_window()
+ if Gtk._version == "4.0":
+ toplevel = widget.get_parent_surface()
+ else:
+ toplevel = widget.get_parent_window()
if toplevel is None:
window = Gtk.Window()
c = Gtk.Button()
c.connect("child-notify", on_notify)
c.freeze_child_notify()
- b.pack_start(c, True, True, 0)
- b.child_set_property(c, "expand", False)
- b.child_set_property(c, "expand", True)
+ if GTK4:
+ b.pack_start(c)
+ else:
+ b.pack_start(c, True, True, 0)
+ b.child_set_property(c, "pack-type", Gtk.PackType.END)
+ b.child_set_property(c, "pack-type", Gtk.PackType.START)
c.thaw_child_notify()
- assert events.count("expand") == 1
+ assert events.count("pack-type") == 1
del events[:]
with c.freeze_child_notify():
- b.child_set_property(c, "expand", True)
- b.child_set_property(c, "expand", False)
+ b.child_set_property(c, "pack-type", Gtk.PackType.END)
+ b.child_set_property(c, "pack-type", Gtk.PackType.START)
- assert events.count("expand") == 1
+ assert events.count("pack-type") == 1
@unittest.skipUnless(Gtk, 'Gtk not available')
Gtk.Button.__init__(self)
self._height = height
+ def do_measure(self, orientation, for_size):
+ if orientation == Gtk.Orientation.VERTICAL:
+ return (self._height, self._height, -1, -1)
+ else:
+ return (0, 0, -1, -1)
+
def do_get_preferred_height(self):
return (self._height, self._height)
w = Gtk.Window()
b = MyButton(height)
w.add(b)
- b.show_all()
+ if not GTK4:
+ b.show_all()
del b
gc.collect()
gc.collect()
- assert w.get_preferred_size().minimum_size.height == height
+ if GTK4:
+ # XXX: Why?
+ assert w.get_preferred_size().minimum_size.height == height + 10
+ else:
+ assert w.get_preferred_size().minimum_size.height == height
@unittest.skipUnless(Gtk, 'Gtk not available')
def test_dialog_classes(self):
self.assertEqual(Gtk.Dialog, gi.overrides.Gtk.Dialog)
self.assertEqual(Gtk.FileChooserDialog, gi.overrides.Gtk.FileChooserDialog)
- self.assertEqual(Gtk.RecentChooserDialog, gi.overrides.Gtk.RecentChooserDialog)
- if Gtk_version != "4.0":
+ if not GTK4:
+ self.assertEqual(Gtk.RecentChooserDialog, gi.overrides.Gtk.RecentChooserDialog)
self.assertEqual(Gtk.ColorSelectionDialog, gi.overrides.Gtk.ColorSelectionDialog)
self.assertEqual(Gtk.FontSelectionDialog, gi.overrides.Gtk.FontSelectionDialog)
self.assertTrue(isinstance(dialog, Gtk.Window))
self.assertEqual('font selection dialog test', dialog.get_title())
+ @unittest.skipIf(GTK4, "not in gtk4")
def test_recent_chooser_dialog(self):
test_manager = Gtk.RecentManager()
dialog = Gtk.RecentChooserDialog(title='recent chooser dialog test',
widget.drag_dest_set_track_motion(True)
widget.drag_dest_get_target_list()
widget.drag_dest_set_target_list(None)
- widget.drag_dest_set_target_list(Gtk.TargetList.new([Gtk.TargetEntry.new('test', 0, 0)]))
+ if GTK4:
+ widget.drag_dest_set_target_list(Gdk.ContentFormats.new([]))
+ else:
+ widget.drag_dest_set_target_list(Gtk.TargetList.new([Gtk.TargetEntry.new('test', 0, 0)]))
widget.drag_dest_unset()
widget.drag_highlight()
widget.drag_source_add_text_targets()
widget.drag_source_add_uri_targets()
widget.drag_source_set_icon_name("_About")
- widget.drag_source_set_icon_pixbuf(GdkPixbuf.Pixbuf())
- if Gtk_version != "4.0":
+ if not GTK4:
+ widget.drag_source_set_icon_pixbuf(GdkPixbuf.Pixbuf())
widget.drag_source_set_icon_stock(Gtk.STOCK_ABOUT)
widget.drag_source_get_target_list()
widget.drag_source_set_target_list(None)
- widget.drag_source_set_target_list(Gtk.TargetList.new([Gtk.TargetEntry.new('test', 0, 0)]))
+ if GTK4:
+ widget.drag_source_set_target_list(Gdk.ContentFormats.new([]))
+ else:
+ widget.drag_source_set_target_list(Gtk.TargetList.new([Gtk.TargetEntry.new('test', 0, 0)]))
widget.drag_source_unset()
# these methods cannot be called because they require a valid drag on
# a real GdkWindow. So we only check that they exist and are callable.
- if Gtk_version != "4.0":
+ if not GTK4:
self.assertTrue(hasattr(widget, 'drag_dest_set_proxy'))
self.assertTrue(hasattr(widget, 'drag_get_data'))
@unittest.skipIf(sys.platform == "darwin", "crashes")
- def test_drag_target_list(self):
+ @unittest.skipIf(GTK4, "uses lots of gtk3 only api")
+ def test_drag_target_list_gtk3(self):
mixed_target_list = [Gtk.TargetEntry.new('test0', 0, 0),
('test1', 1, 1),
Gtk.TargetEntry.new('test2', 2, 2),
self._alloc_value = None
self._alloc_error = None
- def do_size_allocate(self, alloc):
+ def do_size_allocate(self, *args):
self._alloc_called = True
- self._alloc_value = alloc
+ self._alloc_value = args[0]
try:
- Gtk.ScrolledWindow.do_size_allocate(self, alloc)
+ Gtk.ScrolledWindow.do_size_allocate(self, *args)
except Exception as e:
self._alloc_error = e
with realized(win):
win.show()
win.get_preferred_size()
- win.size_allocate(rect)
+ if GTK4:
+ win.size_allocate(rect, 0)
+ else:
+ win.size_allocate(rect)
self.assertTrue(win._alloc_called)
self.assertIsInstance(win._alloc_value, Gdk.Rectangle)
self.assertTrue(win._alloc_error is None, win._alloc_error)
([0], [-1]), ([0, 0], [0]), ([0, 1], [None]), ([0, 2], [None]),
([0, 3], [4321]), ([0, 4], [1234])]
- def test_tree_store_insert_before_none(self):
- store = Gtk.TreeStore(object)
- root = store.append(None)
- sub = store.append(root)
-
- iter_ = store.insert_before(None, None, [1])
- assert store.get_path(iter_).get_indices() == [1]
-
- iter_ = store.insert_before(root, None, [1])
- assert store.get_path(iter_).get_indices() == [0, 1]
-
- iter_ = store.insert_before(sub, None, [1])
- assert store.get_path(iter_).get_indices() == [0, 0, 0]
-
- iter_ = store.insert_before(None, root, [1])
- assert store.get_path(iter_).get_indices() == [0]
-
- iter_ = store.insert_before(None, sub, [1])
- assert store.get_path(iter_).get_indices() == [1, 0]
-
def test_tree_store_insert_after(self):
store = Gtk.TreeStore(object)
signals = []
([0], [-1]), ([0, 0], [1234]), ([0, 1], [4321]),
([0, 2], [None]), ([0, 3], [None]), ([0, 4], [0])]
- def test_tree_store_insert_after_none(self):
- store = Gtk.TreeStore(object)
- root = store.append(None)
- sub = store.append(root)
-
- iter_ = store.insert_after(None, None, [1])
- assert store.get_path(iter_).get_indices() == [0]
-
- iter_ = store.insert_after(root, None, [1])
- assert store.get_path(iter_).get_indices() == [1, 0]
-
- iter_ = store.insert_after(sub, None, [1])
- assert store.get_path(iter_).get_indices() == [1, 1, 0]
-
- iter_ = store.insert_after(None, root, [1])
- assert store.get_path(iter_).get_indices() == [2]
-
- iter_ = store.insert_after(None, sub, [1])
- assert store.get_path(iter_).get_indices() == [1, 2]
-
def test_tree_path(self):
p1 = Gtk.TreePath()
p2 = Gtk.TreePath.new_first()
model = Gtk.ListStore(int, str)
iterations = 2000
- start = timeit.default_timer()
+ start = time.clock()
i = iterations
while i > 0:
model.append([1, 'hello'])
i -= 1
- end = timeit.default_timer()
+ end = time.clock()
sys.stderr.write('[%.0f µs/append] ' % ((end - start) * 1000000 / iterations))
def test_filter_new_default(self):
box = Gtk.Box()
child = Gtk.Button()
if Gtk_version == "4.0":
- box.pack_start(child, expand=False, fill=True)
+ box.pack_start(child)
else:
box.pack_start(child, expand=False, fill=True, padding=42)
with self.assertRaises(ValueError):
self.assertEqual(expand, False)
self.assertEqual(fill, False)
self.assertEqual(padding, 21)
-
- @unittest.skipIf(Gtk_version != "4.0", "only in gtk4")
- def test_child_get_and_set_gtk4(self):
- # padding got removed in gtk4
- box = Gtk.Box()
- child = Gtk.Button()
- box.pack_start(child, expand=True, fill=True)
-
- expand, fill = box.child_get(child, 'expand', 'fill')
- self.assertEqual(expand, True)
- self.assertEqual(fill, True)
-
- box.child_set(child, expand=False, fill=False, pack_type=1)
- expand, fill, pack_type = box.child_get(child, 'expand', 'fill', 'pack-type')
- self.assertEqual(expand, False)
- self.assertEqual(fill, False)
layout.set_markup("Foobar")
self.assertEqual(layout.get_text(), "Foobar")
+ def test_layout_set_markup(self):
+ context = Pango.Context()
+ layout = Pango.Layout(context)
+ layout.set_markup("abc")
+ assert layout.get_text() == "abc"
+ layout.set_markup("abc", -1)
+ assert layout.get_text() == "abc"
+ layout.set_markup("abc", 2)
+ assert layout.get_text() == "ab"
+
+ def test_layout_set_test(self):
+ context = Pango.Context()
+ layout = Pango.Layout(context)
+ layout.set_text("abc")
+ assert layout.get_text() == "abc"
+ layout.set_text("abc", -1)
+ assert layout.get_text() == "abc"
+ layout.set_text("abc", 2)
+ assert layout.get_text() == "ab"
+
def test_break_keyword_escape(self):
# https://bugzilla.gnome.org/show_bug.cgi?id=697363
self.assertTrue(hasattr(Pango, 'break_'))
from __future__ import absolute_import
import unittest
-try:
- from collections import abc
-except ImportError:
- import collections as abc
+import collections
import gi._gi as GIRepository
from gi.module import repository as repo
def test_object_info(self):
info = repo.find_by_name('GIMarshallingTests', 'Object')
self.assertEqual(info.get_parent(), repo.find_by_name('GObject', 'Object'))
- self.assertTrue(isinstance(info.get_methods(), abc.Iterable))
- self.assertTrue(isinstance(info.get_fields(), abc.Iterable))
- self.assertTrue(isinstance(info.get_interfaces(), abc.Iterable))
- self.assertTrue(isinstance(info.get_constants(), abc.Iterable))
- self.assertTrue(isinstance(info.get_vfuncs(), abc.Iterable))
- self.assertTrue(isinstance(info.get_properties(), abc.Iterable))
+ self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_interfaces(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_constants(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_vfuncs(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_properties(), collections.Iterable))
self.assertFalse(info.get_abstract())
self.assertEqual(info.get_class_struct(), repo.find_by_name('GIMarshallingTests', 'ObjectClass'))
self.assertEqual(info.get_type_name(), 'GIMarshallingTestsObject')
def test_interface_info(self):
info = repo.find_by_name('GIMarshallingTests', 'Interface')
- self.assertTrue(isinstance(info.get_methods(), abc.Iterable))
- self.assertTrue(isinstance(info.get_vfuncs(), abc.Iterable))
- self.assertTrue(isinstance(info.get_constants(), abc.Iterable))
- self.assertTrue(isinstance(info.get_prerequisites(), abc.Iterable))
- self.assertTrue(isinstance(info.get_properties(), abc.Iterable))
- self.assertTrue(isinstance(info.get_signals(), abc.Iterable))
+ self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_vfuncs(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_constants(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_prerequisites(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_properties(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_signals(), collections.Iterable))
method = info.find_method('test_int8_in')
vfunc = info.find_vfunc('test_int8_in')
def test_struct_info(self):
info = repo.find_by_name('GIMarshallingTests', 'InterfaceIface')
self.assertTrue(isinstance(info, GIRepository.StructInfo))
- self.assertTrue(isinstance(info.get_fields(), abc.Iterable))
- self.assertTrue(isinstance(info.get_methods(), abc.Iterable))
+ self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
self.assertTrue(isinstance(info.get_size(), int))
self.assertTrue(isinstance(info.get_alignment(), int))
self.assertTrue(info.is_gtype_struct())
def test_enum_info(self):
info = repo.find_by_name('GIMarshallingTests', 'Enum')
self.assertTrue(isinstance(info, GIRepository.EnumInfo))
- self.assertTrue(isinstance(info.get_values(), abc.Iterable))
- self.assertTrue(isinstance(info.get_methods(), abc.Iterable))
+ self.assertTrue(isinstance(info.get_values(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
self.assertFalse(info.is_flags())
self.assertTrue(info.get_storage_type() > 0) # might be platform dependent
def test_union_info(self):
info = repo.find_by_name('GIMarshallingTests', 'Union')
self.assertTrue(isinstance(info, GIRepository.UnionInfo))
- self.assertTrue(isinstance(info.get_fields(), abc.Iterable))
- self.assertTrue(isinstance(info.get_methods(), abc.Iterable))
+ self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
+ self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
self.assertTrue(isinstance(info.get_size(), int))
def test_type_info(self):
def test_callable_info(self):
func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
self.assertTrue(hasattr(func_info, 'invoke'))
- self.assertTrue(isinstance(func_info.get_arguments(), abc.Iterable))
+ self.assertTrue(isinstance(func_info.get_arguments(), collections.Iterable))
self.assertEqual(func_info.get_caller_owns(), GIRepository.Transfer.NOTHING)
self.assertFalse(func_info.may_return_null())
self.assertEqual(func_info.get_return_type().get_tag(), GIRepository.TypeTag.VOID)