-image: registry.gitlab.gnome.org/gnome/pygobject/main:v9
+image: registry.gitlab.gnome.org/gnome/pygobject/main:v10
stages:
- build_and_test
paths:
- coverage/
variables:
- PYENV_VERSION: "3.6.7"
+ PYENV_VERSION: "3.6.8"
script:
- bash -x ./.gitlab-ci/coverage-docker.sh
python3.6:
variables:
- PYENV_VERSION: "3.6.7"
+ PYENV_VERSION: "3.6.8"
<<: *defaults
python3.7:
variables:
- PYENV_VERSION: "3.7.1-debug"
+ PYENV_VERSION: "3.7.2-debug"
<<: *defaults
-pypy2:
+pypy2.7:
allow_failure: true
variables:
- PYENV_VERSION: "pypy2.7-6.0.0"
+ PYENV_VERSION: "pypy2.7-7.0.0"
<<: *defaults
-pypy3:
+pypy3.5:
allow_failure: true
variables:
- PYENV_VERSION: "pypy3.5-6.0.0"
+ PYENV_VERSION: "pypy3.5-7.0.0"
+ <<: *defaults
+
+pypy3.6:
+ allow_failure: true
+ variables:
+ PYENV_VERSION: "pypy3.6-7.0.0"
<<: *defaults
xenial-i386-py2:
gtk4:
stage: build_and_test
- image: registry.gitlab.gnome.org/gnome/pygobject/gtk4:v2
+ image: registry.gitlab.gnome.org/gnome/pygobject/gtk4:v3
artifacts:
paths:
- coverage/
RUN curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
+RUN pyenv install pypy2.7-7.0.0
+RUN pyenv install pypy3.5-7.0.0
+RUN pyenv install pypy3.6-7.0.0
RUN pyenv install --debug 2.7.15
RUN pyenv install 3.5.6
-RUN pyenv install 3.6.7
-RUN pyenv install --debug 3.7.1
-RUN pyenv install pypy2.7-6.0.0
-RUN pyenv install pypy3.5-6.0.0
+RUN pyenv install 3.6.8
+RUN pyenv install --debug 3.7.2
ENV PATH="/usr/lib/ccache:${PATH}"
-FROM registry.gitlab.gnome.org/gnome/pygobject/main:v9
+FROM registry.gitlab.gnome.org/gnome/pygobject/main:v10
USER root
-RUN python3 -m pip install meson
+RUN python3 -m pip install meson==0.49.2
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y \
&& rm -Rf gtk
USER user
-ENV PYENV_VERSION 3.7.1-debug
+ENV PYENV_VERSION 3.7.2-debug
set -e
-TAG="registry.gitlab.gnome.org/gnome/pygobject/gtk4:v2"
+TAG="registry.gitlab.gnome.org/gnome/pygobject/gtk4:v3"
sudo docker build --tag "${TAG}" --file "Dockerfile.gtk4" .
sudo docker run --rm --security-opt label=disable \
set -e
-TAG="registry.gitlab.gnome.org/gnome/pygobject/main:v9"
+TAG="registry.gitlab.gnome.org/gnome/pygobject/main:v10"
sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \
--file "Dockerfile" .
-sudo docker run -e PYENV_VERSION='3.7.1-debug' --rm --security-opt label=disable \
+sudo docker run -e PYENV_VERSION='3.7.2-debug' --rm --security-opt label=disable \
--volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \
--tty --interactive "${TAG}" bash
/usr/bin/python3 -m pip install --user meson
export PATH="${HOME}/.local/bin:${PATH}"
export PKG_CONFIG_PATH="$(python -c 'import sys; sys.stdout.write(sys.prefix)')/lib/pkgconfig"
-# pycairo install under PyPy doesn't install a .pc file
-if [[ "${PYIMPL}" == "PyPy" ]]; then
- meson _build -Dpython="$(which python)" -Dpycairo=false
-else
- meson _build -Dpython="$(which python)"
-fi
+
+meson _build -Dpython="$(which python)"
ninja -C _build
-xvfb-run -a meson test --timeout-multiplier 4 -C _build -v
+xvfb-run -a meson test --suite pygobject --timeout-multiplier 4 -C _build -v
rm -Rf _build
# CODE QUALITY
+3.31.4 - 2019-03-07
+-------------------
+
+* docs: document GObject.Object.weak_ref() :issue:`245`
+* cairo: Add cairo pattern foreign struct support :mr:`111` (:user:`Renato Florentino Garcia <renato_garcia>`)
+* cairo: Add cairo_matrix_t converter to GValue :mr:`112` (:user:`Renato Florentino Garcia <renato_garcia>`)
+
+
3.31.3 - 2019-02-02
-------------------
|
**PyGObject** is a Python package which provides bindings for `GObject
-<https://developer.gnome.org/gobject/stable/>`__ based libraries such as `GTK+
+<https://developer.gnome.org/gobject/stable/>`__ based libraries such as `GTK
<https://www.gtk.org/>`__, `GStreamer <https://gstreamer.freedesktop.org/>`__,
-`WebKitGTK+ <https://webkitgtk.org/>`__, `GLib
+`WebKitGTK <https://webkitgtk.org/>`__, `GLib
<https://developer.gnome.org/glib/stable/>`__, `GIO
<https://developer.gnome.org/gio/stable/>`__ and many more.
images/%.svg: images/%.dia
dia $< --export=$@ --filter=dia-svg
-_build: Makefile *.rst devguide/*.rst guide/*.rst conf.py images/*.png $(DIA_SVGS) ../README.rst ../NEWS
+_build: Makefile *.rst devguide/*.rst guide/*/*.rst guide/*.rst conf.py images/*.png $(DIA_SVGS) ../README.rst ../NEWS
sphinx-build -b html . _build
linkcheck:
Further Resources
=================
-`Python GTK+ 3 Tutorial <https://python-gtk-3-tutorial.readthedocs.io>`__
- Many examples showing how to build an application using PyGObject and GTK+.
+`Python GTK 3 Tutorial <https://python-gtk-3-tutorial.readthedocs.io>`__
+ Many examples showing how to build an application using PyGObject and GTK.
`Python GI API Reference <https://lazka.github.io/pgi-docs>`__
Auto generated API documentation for many libraries accessible through
Getting Started
===============
-To get things started we will try to run a very simple `GTK+
+To get things started we will try to run a very simple `GTK
<https://www.gtk.org/>`_ based GUI application using the :doc:`PyGObject <index>` provided
Python bindings. First create a small Python script called ``hello.py`` with
the following content and save it somewhere:
window.connect("destroy", Gtk.main_quit)
Gtk.main()
-Before we can run the example application we need to install PyGObject, GTK+
+Before we can run the example application we need to install PyGObject, GTK
and their dependencies. Follow the instructions for your platform below.
======================================================= ==================================================== ==========================================================
|windows-logo| :ref:`Windows <windows-getting-started>` |macosx-logo| :ref:`macOS <macosx-getting-started>` |opensuse-logo| :ref:`openSUSE <opensuse-getting-started>`
======================================================= ==================================================== ==========================================================
+After running the example application have a look at the "`Python GTK 3
+Tutorial <https://python-gtk-3-tutorial.readthedocs.io>`__" for more examples
+on how to create GTK apps and the "`PyGObject API Reference
+<https://lazka.github.io/pgi-docs>`__" for API documentation for all supported
+libraries.
.. _windows-getting-started:
#) Run ``C:\msys64\mingw32.exe`` - a terminal window should pop up
#) Execute ``pacman -Suy``
#) Execute ``pacman -S mingw-w64-i686-gtk3 mingw-w64-i686-python3-gobject``
-#) To test that GTK+3 is working you can run ``gtk3-demo``
+#) To test that GTK 3 is working you can run ``gtk3-demo``
#) Copy the ``hello.py`` script you created to ``C:\msys64\home\<username>``
#) In the mingw32 terminal execute ``python3 hello.py`` - a window should appear.
signals
properties
+ weakrefs
Examples
--- /dev/null
+Weak References
+===============
+
+While Python has a builtin ``weakref`` module it only allows one to create
+weak references to Python objects, but with PyGObject the Python object
+"wrapping" a GObject and the GObject itself might not have the same lifetime.
+The wrapper can get garbage collected and a new wrapper created again at a
+later point.
+
+If you want to get notified when the underlying GObject gets finalized use
+``GObject.Object.weak_ref``:
+
+
+.. method:: GObject.Object.weak_ref(callback, *user_data)
+
+ Registers a callback to be called when the underlying GObject gets
+ finalized. The callback will receive the give `user_data`.
+
+ To unregister the callback call the ``unref()`` method of the returned
+ GObjectWeakRef object.
+
+ :param callback: A callback which will be called when the object
+ is finalized
+ :type callback: :func:`callable`
+ :param user_data: User data that will be passed to the callback
+ :returns: GObjectWeakRef
jhbuild shell
GOBJECT_DEBUG=instance-count GTK_DEBUG=interactive ./quodlibet.py
-* In the GTK+ Inspector switch to the "Statistics" tab
+* In the GTK Inspector switch to the "Statistics" tab
* Sort by "Cumulative" and do the action which you suspect does leak or where
you want to make sure it doesn't repeatedly. Like for example opening
and closing a window or switching between media files to present.
Static Bindings Library Differences
-----------------------------------
-**pygtk** supported GTK+ 2.0 and Python 2 only. PyGObject supports GTK+ >=3.0
-and Python 2/3. If you port away from pygtk you also have to move to GTK+ 3.0
+**pygtk** supported GTK 2.0 and Python 2 only. PyGObject supports GTK >=3.0
+and Python 2/3. If you port away from pygtk you also have to move to GTK 3.0
at the same time. **pygtkcompat** described below can help you with that
transition.
-**pygst** supports GStreamer 0.10 and Python 2 only. Like with GTK+ you have
+**pygst** supports GStreamer 0.10 and Python 2 only. Like with GTK you have
to move to PyGObject and GStreamer 1.0 at the same time.
**pygobject 2** supports glib 2.0 and Python 2. The new bindings also support
4) Continue to the next module...
-Porting Tips for GTK+
----------------------
+Porting Tips for GTK
+--------------------
-While PyGObject theoretically supports GTK+ 2.0 it is not really usable. It
-will be easier to port to GTK+ 3.0 right away.
+While PyGObject theoretically supports GTK 2.0 it is not really usable. It
+will be easier to port to GTK 3.0 right away.
-For some general advice regarding the migration from GTK+ 2.0 to 3.0 see the
+For some general advice regarding the migration from GTK 2.0 to 3.0 see the
`offical migration guide
<https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html>`__. If you
need to know how a C symbol is exposed in Python have a look at the `symbol
Testing and Continuous Integration
==================================
-To get automated tests of GTK+ code running on a headless server use Xvfb
+To get automated tests of GTK code running on a headless server use Xvfb
(virtual framebuffer X server). It provides the ``xvfb-run -a`` command which
creates a temporary X server without the need for any real display hardware.
Continuous Integration using Travis CI / CircleCI
-------------------------------------------------
-Travis CI uses a rather old Ubuntu and thus the supported GTK+ is at 3.10 and
-PyGObject is at 3.12. If that's enough for you then have a look at our Travis
+Travis CI uses a rather old Ubuntu and thus the supported GTK is at 3.18 and
+PyGObject is at 3.20. If that's enough for you then have a look at our Travis
CI example project:
|github-logo| https://github.com/pygobject/pygobject-travis-ci-examples
.. image:: https://travis-ci.org/pygobject/pygobject-travis-ci-examples.svg?branch=master
:target: https://travis-ci.org/pygobject/pygobject-travis-ci-examples
-To get newer PyGObject, GTK+, etc. working on `Travis CI
+To get newer PyGObject, GTK, etc. working on `Travis CI
<https://travis-ci.org>`__ or `CircleCI <https://circleci.com>`__ you can use
Docker with an image of your choosing. Have a look at our Docker example
project which runs tests on various Debian, Ubuntu and Fedora versions:
The following examples show
-* how Python threads, running in parallel to GTK+, can interact with the UI
+* how Python threads, running in parallel to GTK, can interact with the UI
* how to use and control asynchronous I/O operations in glib
The example shows a simple window containing a progress bar. After everything
is set up it constructs a Python thread, passes it a function to execute,
-starts the thread and the GTK+ main loop. After the main loop is started it is
+starts the thread and the GTK main loop. After the main loop is started it is
possible to see the window and interact with it.
In the background ``example_target()`` gets executed and calls
:func:`time.sleep` represents the blocking operation. :func:`GLib.idle_add`
takes the ``update_progess()`` function and arguments that will get passed to
the function and asks the main loop to schedule its execution in the main
-thread. This is needed because GTK+ isn't thread safe; only one thread, the
-main thread, is allowed to call GTK+ code at all times.
+thread. This is needed because GTK isn't thread safe; only one thread, the
+main thread, is allowed to call GTK code at all times.
Threads: FAQ
------------
-* I'm porting code from pygtk (GTK+ 2) to PyGObject (GTK+ 3). Has anything
+* I'm porting code from pygtk (GTK 2) to PyGObject (GTK 3). Has anything
changed regarding threads?
Short answer: No.
* Remove any :func:`Gdk.threads_init()`, :func:`Gdk.threads_enter` and
:func:`Gdk.threads_leave` calls. In case they get executed in a thread,
- move the GTK+ code into its own function and schedule it using
+ move the GTK code into its own function and schedule it using
:func:`GLib.idle_add`. Be aware that the newly created function will be
executed some time later, so other stuff can happen in between.
In GStreamer, for example, some signals can be called from a different
thread, see the respective signal documentation for when this is the case.
In case you connect to such a signal you have to make sure to not call any
- GTK+ code or use :func:`GLib.idle_add` accordingly.
+ GTK code or use :func:`GLib.idle_add` accordingly.
-* What if I need to call GTK+ code in signal handlers emitted from a thread?
+* What if I need to call GTK code in signal handlers emitted from a thread?
In case you have a signal that is emitted from another thread and you need
- to call GTK+ code during and not after signal handling, you can push the
+ to call GTK code during and not after signal handling, you can push the
operation with an :class:`threading.Event` object to the main loop and wait
in the signal handler until the operation gets scheduled and the result is
available. Be aware that if the signal is emitted from the main loop this
-pygobject.svg and pygobject-small.svg are based on the GTK+ logo, created by
+pygobject.svg and pygobject-small.svg are based on the GTK logo, created by
Andreas Nilsson, licensed under CC BY-SA 3.0. For more info see
https://commons.wikimedia.org/wiki/File:GTK%2B_logo.svg
:end-before: ----
If you want to write a Python application for `GNOME
-<https://www.gnome.org/>`__ or a Python GUI application using GTK+, then
+<https://www.gnome.org/>`__ or a Python GUI application using GTK, then
PyGObject is the way to go. For more information on specific libraries check
-out the "`Python GTK+ 3 Tutorial
+out the "`Python GTK 3 Tutorial
<https://python-gtk-3-tutorial.readthedocs.io>`__" and the "`Python GI API
Reference <https://lazka.github.io/pgi-docs>`__".
Test Suite dependencies:
* The runtime dependencies
- * GTK+ 3 (optional)
+ * GTK 3 (optional)
* pango (optional)
* pycairo (optional)
def on_activate(self, app):
self.window = Gtk.ApplicationWindow.new(self)
- self.window.set_title('PyGObject GTK+ Code Demos')
+ self.window.set_title('PyGObject GTK Code Demos')
self.window.set_default_size(600, 400)
self.setup_default_icon()
transparent = pixbuf.add_alpha(True, 0xff, 0xff, 0xff)
about = Gtk.AboutDialog(parent=window,
- program_name='GTK+ Code Demos',
+ program_name='GTK Code Demos',
version='0.1',
copyright='(C) 2010 The PyGI Team',
license=license,
authors=authors,
documenters=documentors,
logo=transparent,
- title='About GTK+ Code Demos')
+ title='About GTK Code Demos')
about.connect('response', widget_destroy)
about.show()
about_cb),
("Logo", "demo-gtk-logo", # name, stock id
None, None, # label, accelerator
- "GTK+", # tooltip
+ "GTK", # tooltip
activate_action),
)
import math
-UTF8_TEXT = u"I ♥ GTK+"
+UTF8_TEXT = u"I ♥ GTK"
HEART = u"♥"
BYTES_TEXT = UTF8_TEXT.encode("utf-8")
BYTES_HEART = HEART.encode("utf-8")
pass
if GDK2 or GDK3:
- # Gdk.Color was deprecated since 3.14 and dropped in Gtk+-4.0
+ # Gdk.Color was deprecated since 3.14 and dropped in Gtk-4.0
class Color(Gdk.Color):
MAX_VALUE = 65535
__all__.append('Color')
if GDK3:
- # Introduced since Gtk+-3.0
+ # Introduced since Gtk-3.0
class RGBA(Gdk.RGBA):
def __init__(self, red=1.0, green=1.0, blue=1.0, alpha=1.0):
Gdk.RGBA.__init__(self)
Rectangle = override(Rectangle)
__all__.append('Rectangle')
elif GDK3:
- # Newer GTK+/gobject-introspection (3.17.x) include GdkRectangle in the
+ # Newer GTK/gobject-introspection (3.17.x) include GdkRectangle in the
# typelib. See https://bugzilla.gnome.org/show_bug.cgi?id=748832 and
# https://bugzilla.gnome.org/show_bug.cgi?id=748833
if not hasattr(Gdk, 'Rectangle'):
Cursor = override(Cursor)
__all__.append('Cursor')
- # Gdk.Color was deprecated since 3.14 and dropped in Gtk+-4.0
+ # Gdk.Color was deprecated since 3.14 and dropped in Gtk-4.0
color_parse = strip_boolean_result(Gdk.color_parse)
__all__.append('color_parse')
* cairo_pattern_t marshaling
*/
+static PyObject *
+cairo_pattern_to_arg (PyObject *value,
+ GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ GIArgument *arg)
+{
+ cairo_pattern_t *pattern;
+
+ if (!PyObject_TypeCheck (value, &PycairoPattern_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Pattern");
+ return NULL;
+ }
+
+ pattern = ((PycairoPattern*) value)->pattern;
+ if (!pattern) {
+ PyErr_SetString (PyExc_ValueError, "Pattern instance wrapping a NULL pattern");
+ return NULL;
+ }
+
+ if (transfer != GI_TRANSFER_NOTHING)
+ pattern = cairo_pattern_reference (pattern);
+
+ arg->v_pointer = pattern;
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+cairo_pattern_from_arg (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ gpointer data)
+{
+ cairo_pattern_t *pattern = (cairo_pattern_t*) data;
+
+ if (transfer == GI_TRANSFER_NOTHING)
+ pattern = cairo_pattern_reference (pattern);
+
+ return PycairoPattern_FromPattern (pattern, NULL);
+}
+
+static PyObject *
+cairo_pattern_release (GIBaseInfo *base_info,
+ gpointer struct_)
+{
+ cairo_pattern_destroy ( (cairo_pattern_t*) struct_);
+ Py_RETURN_NONE;
+}
+
static int
cairo_pattern_to_gvalue (GValue *value, PyObject *obj)
{
Py_RETURN_NONE;
}
+static int
+cairo_matrix_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_matrix_t *matrix;
+
+ if (!PyObject_TypeCheck (obj, &PycairoMatrix_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Matrix");
+ return -1;
+ }
+
+ matrix = &(( (PycairoMatrix*) obj)->matrix);
+ if (!matrix) {
+ return -1;
+ }
+
+ g_value_set_boxed (value, matrix);
+ return 0;
+}
+
+static PyObject *
+cairo_matrix_from_gvalue (const GValue *value)
+{
+ cairo_matrix_t *matrix = g_value_get_boxed(value);
+ if (!matrix) {
+ Py_RETURN_NONE;
+ }
+
+ return PycairoMatrix_FromMatrix (matrix);
+}
+
static PyMethodDef _gi_cairo_functions[] = { {0,} };
PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo")
{
cairo_font_options_from_arg,
cairo_font_options_release);
+ pygi_register_foreign_struct ("cairo",
+ "Pattern",
+ cairo_pattern_to_arg,
+ cairo_pattern_from_arg,
+ cairo_pattern_release);
+
pygi_register_foreign_struct ("cairo",
"Region",
cairo_region_to_arg,
cairo_region_from_arg,
cairo_region_release);
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_MATRIX,
+ cairo_matrix_from_gvalue,
+ cairo_matrix_to_gvalue);
+
pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_CONTEXT,
cairo_context_from_gvalue,
cairo_context_to_gvalue);
PyObject *object;
/* HACK:
- * The following hack is to work around GTK+ sending signals which
+ * The following hack is to work around GTK sending signals which
* contain floating widgets in them. This assumes control of how
* references are added by the PyGObject wrapper and avoids the sink
* behavior by explicitly passing GI_TRANSFER_EVERYTHING as the transfer
project('pygobject', 'c',
- version : '3.31.3',
+ version : '3.31.4',
meson_version : '>= 0.46.0',
default_options : [ 'warning_level=1',
'buildtype=debugoptimized'])
<name xml:lang="en">PyGObject</name>
<shortdesc xml:lang="en">Python bindings for GObject Introspection</shortdesc>
<description>
-GObject is a object system used by GTK+, GStreamer and other libraries.
+GObject is a object system used by GTK, GStreamer and other libraries.
PyGObject provides a convenient wrapper for use in Python programs when accessing GObject libraries.
_patch(Gdk, "PixbufLoader", GdkPixbuf.PixbufLoader.new_with_type)
_patch(Gdk, "pixbuf_new_from_data", GdkPixbuf.Pixbuf.new_from_data)
_patch(Gdk, "pixbuf_new_from_file", GdkPixbuf.Pixbuf.new_from_file)
- try:
- _patch(Gdk, "pixbuf_new_from_file_at_scale", GdkPixbuf.Pixbuf.new_from_file_at_scale)
- except AttributeError:
- pass
+ _patch(Gdk, "pixbuf_new_from_file_at_scale", GdkPixbuf.Pixbuf.new_from_file_at_scale)
_patch(Gdk, "pixbuf_new_from_file_at_size", GdkPixbuf.Pixbuf.new_from_file_at_size)
_patch(Gdk, "pixbuf_new_from_inline", GdkPixbuf.Pixbuf.new_from_inline)
_patch(Gdk, "pixbuf_new_from_stream", GdkPixbuf.Pixbuf.new_from_stream)
_patch(Gdk, "pixbuf_get_formats", get_formats)
- orig_get_frame_extents = Gdk.Window.get_frame_extents
-
- def get_frame_extents(window):
- try:
- try:
- rect = Gdk.Rectangle(0, 0, 0, 0)
- except TypeError:
- rect = Gdk.Rectangle()
- orig_get_frame_extents(window, rect)
- except TypeError:
- rect = orig_get_frame_extents(window)
- return rect
- _patch(Gdk.Window, "get_frame_extents", get_frame_extents)
-
orig_get_origin = Gdk.Window.get_origin
def get_origin(self):
_patch(Gtk, "image_new_from_file", Gtk.Image.new_from_file)
_patch(Gtk, "settings_get_default", Gtk.Settings.get_default)
_patch(Gtk, "window_set_default_icon", Gtk.Window.set_default_icon)
- try:
- _patch(Gtk, "clipboard_get", Gtk.Clipboard.get)
- except AttributeError:
- pass
+ _patch(Gtk, "clipboard_get", Gtk.Clipboard.get)
# AccelGroup
_patch(Gtk.AccelGroup, "connect_group", Gtk.AccelGroup.connect)
from distutils.spawn import find_executable
-PYGOBJECT_VERSION = "3.31.3"
+PYGOBJECT_VERSION = "3.31.4"
GLIB_VERSION_REQUIRED = "2.48.0"
GI_VERSION_REQUIRED = "1.46.0"
PYCAIRO_VERSION_REQUIRED = "1.11.1"
return path;
}
+/**
+ * regress_test_cairo_pattern_full_in:
+ * @pattern: (transfer full):
+ */
+void
+regress_test_cairo_pattern_full_in (cairo_pattern_t *pattern)
+{
+ cairo_pattern_destroy (pattern);
+}
+
+/**
+ * regress_test_cairo_pattern_none_in:
+ * @pattern: (transfer none):
+ */
+void
+regress_test_cairo_pattern_none_in (cairo_pattern_t *pattern)
+{
+ cairo_t *cr = regress_test_cairo_context_full_return ();
+ cairo_set_source (cr, pattern);
+ g_assert (cairo_status (cr) == CAIRO_STATUS_SUCCESS);
+ cairo_destroy (cr);
+}
+
+/**
+ * regress_test_cairo_pattern_none_return:
+ *
+ * Returns: (transfer none):
+ */
+cairo_pattern_t*
+regress_test_cairo_pattern_none_return (void)
+{
+ static cairo_pattern_t *pattern;
+
+ if (pattern == NULL) {
+ pattern = cairo_pattern_create_rgb(0.1, 0.2, 0.3);
+ }
+
+ return pattern;
+}
+
+/**
+ * regress_test_cairo_pattern_full_return:
+ *
+ * Returns: (transfer full):
+ */
+cairo_pattern_t *
+regress_test_cairo_pattern_full_return (void)
+{
+ cairo_pattern_t *pattern = cairo_pattern_create_rgb(0.5, 0.6, 0.7);
+ return pattern;
+}
+
/**
* regress_test_cairo_region_full_in:
* @region: (transfer full):
_GI_TEST_EXTERN
cairo_path_t * regress_test_cairo_path_full_in_full_return (cairo_path_t *path);
_GI_TEST_EXTERN
+void regress_test_cairo_pattern_full_in (cairo_pattern_t *pattern);
+_GI_TEST_EXTERN
+void regress_test_cairo_pattern_none_in (cairo_pattern_t *pattern);
+_GI_TEST_EXTERN
+cairo_pattern_t* regress_test_cairo_pattern_none_return (void);
+_GI_TEST_EXTERN
+cairo_pattern_t * regress_test_cairo_pattern_full_return (void);
+_GI_TEST_EXTERN
cairo_font_options_t *regress_test_cairo_font_options_full_return (void);
_GI_TEST_EXTERN
cairo_font_options_t *regress_test_cairo_font_options_none_return (void);
def test_gvalue_converters(self):
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
context = cairo.Context(surface)
+ matrix = cairo.Matrix()
objects = {
'CairoContext': context,
'CairoSurface': surface,
'CairoFontFace': context.get_font_face(),
'CairoScaledFont': context.get_scaled_font(),
'CairoPattern': context.get_source(),
+ 'CairoMatrix': matrix,
}
for type_name, cairo_obj in objects.items():
gtype = GObject.type_from_name(type_name)
options = cairo.FontOptions()
Regress.test_cairo_font_options_none_in(options)
+ def test_cairo_pattern_full_in(self):
+ pattern = cairo.SolidPattern(1, 1, 1, 1)
+ Regress.test_cairo_pattern_full_in(pattern)
+
+ with pytest.raises(TypeError):
+ Regress.test_cairo_pattern_full_in(object())
+
+ def test_cairo_pattern_none_in(self):
+ pattern = cairo.SolidPattern(1, 1, 1, 1)
+ Regress.test_cairo_pattern_none_in(pattern)
+
+ def test_cairo_pattern_full_return(self):
+ pattern = Regress.test_cairo_pattern_full_return()
+ self.assertTrue(isinstance(pattern, cairo.Pattern))
+ self.assertTrue(isinstance(pattern, cairo.SolidPattern))
+
+ def test_cairo_pattern_none_return(self):
+ pattern = Regress.test_cairo_pattern_none_return()
+ self.assertTrue(isinstance(pattern, cairo.Pattern))
+ self.assertTrue(isinstance(pattern, cairo.SolidPattern))
+
def test_cairo_region_full_in(self):
region = cairo.Region()
Regress.test_cairo_region_full_in(region)
import gc
import unittest
import warnings
+import weakref
+import platform
import pytest
from .helper import capture_glib_deprecation_warnings
+@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="crashes")
+def test_gobject_weak_ref():
+
+ called = []
+
+ def callback(*args):
+ called.extend(args)
+
+ # object gets finalized
+ obj = GObject.Object()
+ obj.weak_ref(callback, 1)
+ del obj
+ gc.collect()
+ gc.collect()
+ assert called == [1]
+ del called[:]
+
+ # wrapper gets finalized first
+ obj = GObject.Object()
+ pyref = weakref.ref(obj, lambda x: callback(-2))
+ value = GObject.Value(GObject.Object, obj)
+ ref = obj.weak_ref(callback, 2)
+ del obj
+ gc.collect()
+ assert called == [-2]
+ del pyref
+ value.unset()
+ gc.collect()
+ assert called == [-2, 2]
+ del called[:]
+
+ # weakref gets unregistered first
+ obj = GObject.Object()
+ ref = obj.weak_ref(callback, 3)
+ ref.unref()
+ del obj
+ gc.collect()
+ assert not called
+
+ # weakref gets GCed
+ obj = GObject.Object()
+ obj.weak_ref(callback, 4)
+ gc.collect()
+ del obj
+ assert called == [4]
+
+
class TestGObjectAPI(unittest.TestCase):
def test_call_method_uninitialized_instance(self):
self.assertTrue(isinstance(button, Gtk.Widget))
if Gtk_version != "4.0":
- # Using stock items causes hard warning in devel versions of GTK+.
+ # Using stock items causes hard warning in devel versions of GTK.
with capture_glib_warnings(allow_warnings=True):
button = Gtk.Button.new_from_stock(Gtk.STOCK_CLOSE)
def test_toolbutton(self):
# PyGTK compat
- # Using stock items causes hard warning in devel versions of GTK+.
+ # Using stock items causes hard warning in devel versions of GTK.
with capture_glib_warnings(allow_warnings=True):
button = Gtk.ToolButton()
self.assertEqual(button.props.stock_id, None)
import unittest
import base64
+import pytest
+import gi
import pygtkcompat
from pygtkcompat.pygtkcompat import _disable_all as disable_all
def tearDown(self):
disable_all()
+ def test_window_get_frame_extents(self):
+ import gtk
+ import gtk.gdk
+ w = gtk.Window()
+ w.realize()
+ rect = w.window.get_frame_extents()
+ assert isinstance(rect, gtk.gdk.Rectangle)
+
+ def test_window_get_geometry(self):
+ import gtk
+ w = gtk.Window()
+ w.realize()
+ with capture_gi_deprecation_warnings():
+ geo = w.window.get_geometry()
+ assert isinstance(geo, tuple)
+ assert len(geo) == 5
+
+ def test_action_set_tool_item_type(self):
+ import gtk
+ with pytest.warns(gi.PyGIDeprecationWarning):
+ gtk.Action().set_tool_item_type(gtk.Action)
+
+ def test_treeviewcolumn_pack(self):
+ import gtk
+ col = gtk.TreeViewColumn()
+ col.pack_end(gtk.CellRendererText())
+ col.pack_start(gtk.CellRendererText())
+
+ def test_cell_layout_pack(self):
+ import gtk
+ layout = gtk.EntryCompletion()
+ layout.pack_end(gtk.CellRendererText())
+ layout.pack_start(gtk.CellRendererText())
+
+ def test_cell_layout_cell_data_func(self):
+ import gtk
+
+ def func(*args):
+ pass
+
+ layout = gtk.EntryCompletion()
+ render = gtk.CellRendererText()
+ layout.set_cell_data_func(render, func)
+
+ def test_combo_row_separator_func(self):
+ import gtk
+
+ def func(*args):
+ pass
+
+ combo = gtk.ComboBox()
+ combo.set_row_separator_func(func)
+
+ def test_container_install_child_property(self):
+ import gtk
+
+ box = gtk.Box()
+ with pytest.warns(gi.PyGIDeprecationWarning):
+ box.install_child_property(0, None)
+
+ def test_combo_box_new_text(self):
+ import gtk
+
+ combo = gtk.combo_box_new_text()
+ assert isinstance(combo, gtk.ComboBox)
+ combo.append_text("foo")
+
+ def test_scale(self):
+ import gtk
+
+ adjustment = gtk.Adjustment()
+ assert gtk.HScale()
+ assert gtk.HScale(adjustment).get_adjustment() == adjustment
+ adjustment = gtk.Adjustment()
+ assert gtk.VScale()
+ assert gtk.VScale(adjustment).get_adjustment() == adjustment
+
+ def test_stock_add(self):
+ import gtk
+
+ gtk.stock_add([])
+
+ def test_text_view_scroll_to_mark(self):
+ import gtk
+
+ view = gtk.TextView()
+ buf = view.get_buffer()
+ mark = gtk.TextMark(name="foo")
+ buf.add_mark(mark, buf.get_end_iter())
+ view.scroll_to_mark(mark, 0.0)
+
+ def test_window_set_geometry_hints(self):
+ import gtk
+
+ w = gtk.Window()
+ w.set_geometry_hints(None, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ w.set_geometry_hints(None, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1)
+ with pytest.raises(TypeError):
+ w.set_geometry_hints(None, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+
def test_buttons(self):
import gtk.gdk
self.assertEqual(gtk.gdk._2BUTTON_PRESS, 5)