-image: registry.gitlab.gnome.org/gnome/pygobject/main:v11
+image: registry.gitlab.gnome.org/gnome/pygobject/main:v13
stages:
- build_and_test
paths:
- coverage/
variables:
- PYENV_VERSION: "3.6.8"
+ PYENV_VERSION: "3.6.10"
script:
- bash -x ./.gitlab-ci/coverage-docker.sh
only:
- master
-python2-mingw32:
- variables:
- PYTHON: "python2"
- MSYSTEM: "MINGW32"
- CHERE_INVOKING: "yes"
- <<: *mingw-defaults
-
-python2-mingw64:
- variables:
- PYTHON: "python2"
- MSYSTEM: "MINGW64"
- CHERE_INVOKING: "yes"
- <<: *mingw-defaults
-
python3-mingw32:
variables:
PYTHON: "python3"
python2.7:
variables:
- PYENV_VERSION: "2.7.16-debug"
+ PYENV_VERSION: "2.7.17-debug"
<<: *defaults
python3.5:
variables:
- PYENV_VERSION: "3.5.7"
+ PYENV_VERSION: "3.5.9"
<<: *defaults
python3.6:
variables:
- PYENV_VERSION: "3.6.8"
+ PYENV_VERSION: "3.6.10"
<<: *defaults
python3.7:
variables:
- PYENV_VERSION: "3.7.3-debug"
+ PYENV_VERSION: "3.7.6-debug"
<<: *defaults
python3.8:
variables:
- PYENV_VERSION: "3.8-dev-debug"
+ PYENV_VERSION: "3.8.1-debug"
<<: *defaults
pypy2.7:
allow_failure: true
variables:
- PYENV_VERSION: "pypy2.7-7.1.0"
+ PYENV_VERSION: "pypy2.7-7.3.0"
<<: *defaults
pypy3.6:
allow_failure: true
variables:
- PYENV_VERSION: "pypy3.6-7.1.0"
+ PYENV_VERSION: "pypy3.6-7.3.0"
<<: *defaults
-xenial-i386-py2:
+xenial-i386-py3:
stage: build_and_test
- image: registry.gitlab.gnome.org/gnome/pygobject/old:v2
+ image: registry.gitlab.gnome.org/gnome/pygobject/old:v3
artifacts:
paths:
- coverage/
script:
- bash -x ./.gitlab-ci/test-docker-old.sh
-gtk4:
+gnome-master:
+ allow_failure: true
stage: build_and_test
- image: registry.gitlab.gnome.org/gnome/pygobject/gtk4:v4
- artifacts:
- paths:
- - coverage/
+ image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
+ tags:
+ - flatpak
script:
- - bash -x ./.gitlab-ci/test-docker-gtk4.sh
+ - xvfb-run -a flatpak run --filesystem=host --share=network --socket=x11 --command=bash org.gnome.Sdk//master -x .gitlab-ci/test-flatpak.sh
-gnome-master:
+gnome-master-gtk4:
allow_failure: true
stage: build_and_test
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
+ tags:
+ - flatpak
script:
- - xvfb-run -a flatpak run --filesystem=host --share=network --socket=x11 --command=bash org.gnome.Sdk//master -x .gitlab-ci/test-flatpak.sh
+ - xvfb-run -a flatpak run --filesystem=host --share=network --socket=x11 --command=bash org.gnome.Sdk//master -x .gitlab-ci/test-flatpak-gtk4.sh
+ artifacts:
+ paths:
+ - coverage/
\ No newline at end of file
RUN curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
-RUN pyenv install pypy2.7-7.1.0
-RUN pyenv install pypy3.6-7.1.0
-RUN pyenv install --debug 2.7.16
-RUN pyenv install 3.5.7
-RUN pyenv install 3.6.8
-RUN pyenv install --debug 3.7.3
-RUN pyenv install --debug 3.8-dev
+RUN pyenv install pypy2.7-7.3.0
+RUN pyenv install pypy3.6-7.3.0
+RUN pyenv install --debug 2.7.17
+RUN pyenv install 3.5.9
+RUN pyenv install 3.6.10
+RUN pyenv install --debug 3.7.6
+RUN pyenv install --debug 3.8.1
ENV PATH="/usr/lib/ccache:${PATH}"
+++ /dev/null
-FROM registry.gitlab.gnome.org/gnome/pygobject/main:v11
-
-USER root
-
-RUN python3 -m pip install meson==0.49.2
-
-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.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.3-debug
libgtk-3-0 \
libtool \
locales \
- python-dev \
- python-virtualenv \
+ python3-dev \
+ python3-venv \
xauth \
xvfb \
&& rm -rf /var/lib/apt/lists/*
python -m pip install coverage
# Make the Windows paths match our current layout
-python ./.gitlab-ci/fixup-cov-paths.py coverage/.coverage* coverage/*.lcov
+python ./.gitlab-ci/fixup-lcov-paths.py coverage/*.lcov
+python ./.gitlab-ci/fixup-covpy-paths.py coverage/.coverage*
# Remove external headers (except gi tests)
for path in coverage/*.lcov; do
done
python -m coverage combine coverage
-python -m coverage html --ignore-errors -d coverage/report-python
+python -m coverage html --show-contexts --ignore-errors -d coverage/report-python
genhtml --ignore-errors=source --rc lcov_branch_coverage=1 \
coverage/*.lcov -o coverage/report-c
--- /dev/null
+import sys
+import sqlite3
+
+
+def main(argv):
+ paths = argv[1:]
+
+ for path in paths:
+ # https://github.com/nedbat/coveragepy/issues/903
+ conn = sqlite3.connect(path)
+ conn.execute("UPDATE file set path = REPLACE(path, '\\', '/')")
+ conn.commit()
+ conn.close()
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
+++ /dev/null
-#!/bin/bash
-
-set -e
-
-TAG="registry.gitlab.gnome.org/gnome/pygobject/gtk4:v4"
-
-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
set -e
-TAG="registry.gitlab.gnome.org/gnome/pygobject/old:v2"
+TAG="registry.gitlab.gnome.org/gnome/pygobject/old:v3"
sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \
--file "Dockerfile.old" .
sudo docker run --privileged --rm --security-opt label=disable \
--volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \
--tty --interactive "${TAG}" xvfb-run -a flatpak run --filesystem=host \
- --share=network --socket=x11 --command=bash org.gnome.Sdk//master
+ --share=network --socket=x11 --devel --command=bash org.gnome.Sdk//master
set -e
-TAG="registry.gitlab.gnome.org/gnome/pygobject/main:v11"
+TAG="registry.gitlab.gnome.org/gnome/pygobject/main:v13"
sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \
--file "Dockerfile" .
-sudo docker run -e PYENV_VERSION='3.7.3-debug' --rm --security-opt label=disable \
+sudo docker run -e PYENV_VERSION='3.8.1-debug' --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
-export CCACHE_BASEDIR="$(pwd)"
-export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
-COV_DIR="$(pwd)/coverage"
-export COVERAGE_FILE="${COV_DIR}/.coverage.${CI_JOB_NAME}"
-mkdir -p "${COV_DIR}"
-mkdir -p "${CCACHE_DIR}"
-
-# test
-python -m pip install git+https://github.com/pygobject/pycairo.git
-python -m pip install pytest pytest-faulthandler coverage
-g-ir-inspect Gtk --version=4.0 --print-typelibs
-export TEST_GTK_VERSION=4.0
-python setup.py build_tests
-xvfb-run -a python -m coverage run tests/runtests.py
set -e
-python --version
-virtualenv --python=python _venv
+python3 --version
+python3 -m venv _venv
source _venv/bin/activate
# ccache setup
export CCACHE_BASEDIR="$(pwd)"
export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
COV_DIR="$(pwd)/coverage"
-export COVERAGE_FILE="${COV_DIR}/.coverage.${CI_JOB_NAME}"
+COV_KEY="${CI_JOB_NAME}"
+export COVERAGE_FILE="${COV_DIR}/.coverage.${COV_KEY}"
mkdir -p "${COV_DIR}"
mkdir -p "${CCACHE_DIR}"
# test
-python -m pip install git+https://github.com/pygobject/pycairo.git
-python -m pip install pytest pytest-faulthandler coverage
+python -m pip install --upgrade pip
+python -m pip install pycairo pytest pytest-faulthandler coverage
python setup.py build_tests
-xvfb-run -a python -m coverage run tests/runtests.py
+xvfb-run -a python -m coverage run --context "${COV_KEY}" tests/runtests.py
export MALLOC_CHECK_=3
export MALLOC_PERTURB_=$((${RANDOM} % 255 + 1))
export G_SLICE="debug-blocks"
-export COVERAGE_FILE="${COV_DIR}/.coverage.${CI_JOB_NAME}"
+COV_KEY="${CI_JOB_NAME}"
+export COVERAGE_FILE="${COV_DIR}/.coverage.${COV_KEY}"
export CCACHE_BASEDIR="$(pwd)"
export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
mkdir -p "${CCACHE_DIR}"
mkdir -p "${COV_DIR}"
-python -m pip install git+https://github.com/pygobject/pycairo.git
-python -m pip install flake8 pytest pytest-faulthandler coverage
+python -m pip install pycairo flake8 pytest pytest-faulthandler coverage
export CFLAGS="-coverage -ftest-coverage -fprofile-arcs -Werror"
# BUILD & TEST AGAIN USING SETUP.PY
python setup.py build_tests
-xvfb-run -a python -m coverage run tests/runtests.py
+xvfb-run -a python -m coverage run --context "${COV_KEY}" tests/runtests.py
# COLLECT GCOV COVERAGE
lcov --rc lcov_branch_coverage=1 --directory . --capture --output-file \
--- /dev/null
+#!/bin/bash
+
+set -e
+
+COV_DIR="$(pwd)/coverage"
+COV_KEY="gtk4"
+export COVERAGE_FILE="${COV_DIR}/.coverage.${COV_KEY}"
+mkdir -p "${COV_DIR}"
+
+export TEST_GTK_VERSION=4.0
+python3 -m pip install --user pytest pytest-faulthandler coverage
+python3 setup.py build_tests
+python3 -m coverage run --context "${COV_KEY}" tests/runtests.py
+chmod -R 777 "${COV_DIR}"
\ No newline at end of file
# for some reason pip3 fails the first time now..
# https://gitlab.com/freedesktop-sdk/freedesktop-sdk/issues/776
python3 -m pip install --user pytest pytest-faulthandler
-python3 setup.py test -s
+python3 setup.py test -s
\ No newline at end of file
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
export PYTHONDEVMODE=1
$PYTHON setup.py build_tests
-MSYSTEM= $PYTHON -m coverage run tests/runtests.py
+MSYSTEM= $PYTHON -m coverage run --context "${COV_KEY}" tests/runtests.py
# FIXME: lcov doesn't support gcc9
#~ curl -O -J -L "https://github.com/linux-test-project/lcov/archive/master.tar.gz"
+3.36.0 - 2020-03-08
+-------------------
+
+This will be the last release supporting Python 2.
+
+* pygobject-object: Avoid checking whether NULL is floating :mr:`135` (:user:`Alexandru Băluț <aleb>`)
+* Avoid various new glib deprecation warnings
+* Port to g_object_new_with_properties()
+* Drop Python 2 support on Windows
+* gtk overrides: Drop Menu, MenuItem for Gtk 4 (:user:`Marinus Schraal <mschraal>`)
+* Docs:
+
+ * Update openSUSE instructions (:user:`sharkwouter`)
+ * Add Gaphor to Who is Using PyGObject (:user:`Dan Yeaw <danyeaw>`)
+ * Remove reference to a fixed bug (:user:`Christian Stadelmann <genodeftest>`)
+
+
3.34.0 - 2019-09-09
-------------------
Installing the system provided PyGObject:
#) Open a terminal
- #) Execute ``sudo zypper install python3-gobject gtk3``
+ #) Execute ``sudo zypper install python3-gobject python3-gobject-Gdk typelib-1_0-Gtk-3_0 libgtk-3-0``
#) Change the directory to where your ``hello.py`` script can be found
#) Run ``python3 hello.py``
* Unix + Python 2: :obj:`str`
* Unix + Python 3: :obj:`str`
-On Python 3 there is currently no support for :obj:`bytes`, see `bug 746564
-<https://bugzilla.gnome.org/show_bug.cgi?id=746564>`__ for more details.
-
Other Types
-----------
* `Anaconda <https://fedoraproject.org/wiki/Anaconda>`__ - an installation program used by Fedora, RHEL and others
* `D-Feet <https://wiki.gnome.org/action/show/Apps/DFeet>`__ - an easy to use D-Bus debugger
+* `Gaphor <https://gaphor.org/>`__ - a simple modeling tool
+* `Girens <https://gitlab.gnome.org/tijder/girens>`__ - a Plex client for playing movies, TV shows and music from your Plex library
* `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
return pspec;
}
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
/**
* pyg_parse_constructor_args: helper function for PyGObject constructors
* @obj_type: GType of the GObject, for parameter introspection
return TRUE;
}
+G_GNUC_END_IGNORE_DEPRECATIONS
+
/* Only for backwards compatibility */
static int
pygobject_enable_threads(void)
return (PyObject *) g_private_get(&pygobject_construction_wrapper);
}
+/**
+ * Like g_object_new_with_properties() but also works with older glib versions.
+ */
+GObject *
+pygobject_object_new_with_properties(GType object_type,
+ guint n_properties,
+ const char *names[],
+ const GValue values[])
+{
+ GObject *obj;
+
+#if GLIB_CHECK_VERSION(2, 54, 0)
+ obj = g_object_new_with_properties(object_type, n_properties, names, values);
+#else
+ {
+ GParameter *parameters;
+ uint i;
+
+ parameters = g_new(GParameter, n_properties);
+ for (i = 0; i < n_properties; i++) {
+ parameters[i].name = names[i];
+ parameters[i].value = values[i];
+ }
+ obj = g_object_newv(object_type, n_properties, parameters);
+ g_free(parameters);
+ }
+#endif
+
+ return obj;
+}
+
int
-pygobject_constructv(PyGObject *self,
- guint n_parameters,
- GParameter *parameters)
+pygobject_constructv (PyGObject *self,
+ guint n_properties,
+ const char *names[],
+ const GValue values[])
{
GObject *obj;
g_assert (self->obj == NULL);
pygobject_init_wrapper_set((PyObject *) self);
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- obj = g_object_newv(pyg_type_from_object((PyObject *) self),
- n_parameters, parameters);
-G_GNUC_END_IGNORE_DEPRECATIONS
+
+ obj = pygobject_object_new_with_properties(pyg_type_from_object((PyObject *) self),
+ n_properties,
+ names,
+ values);
+
if (g_object_is_floating (obj))
self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING;
pygobject_sink (obj);
#include "pygobject-internal.h"
int pygobject_constructv (PyGObject *self,
- guint n_parameters,
- GParameter *parameters);
+ guint n_properties,
+ const char *names[],
+ const GValue values[]);
+
+GObject *
+pygobject_object_new_with_properties(GType object_type,
+ guint n_properties,
+ const char *names[],
+ const GValue values[]);
#endif /*_PYGOBJECT_GIMODULE_H_*/
translate_coordinates = strip_boolean_result(Gtk.Widget.translate_coordinates)
- def freeze_child_notify(self):
- super(Widget, self).freeze_child_notify()
- return _FreezeNotifyManager(self)
+ if Gtk._version != "4.0":
+ def freeze_child_notify(self):
+ super(Widget, self).freeze_child_notify()
+ return _FreezeNotifyManager(self)
if Gtk._version != "4.0":
def drag_dest_set_target_list(self, target_list):
# alias for Python 2.x object protocol
__nonzero__ = __bool__
- def child_get_property(self, child, property_name, value=None):
- if value is None:
- prop = self.find_child_property(property_name)
- if prop is None:
- raise ValueError('Class "%s" does not contain child property "%s"' %
- (self, property_name))
- value = GObject.Value(prop.value_type)
+ if Gtk._version in ("2.0", "3.0"):
- Gtk.Container.child_get_property(self, child, property_name, value)
- return value.get_value()
+ def child_get_property(self, child, property_name, value=None):
+ if value is None:
+ prop = self.find_child_property(property_name)
+ if prop is None:
+ raise ValueError('Class "%s" does not contain child property "%s"' %
+ (self, property_name))
+ value = GObject.Value(prop.value_type)
+
+ Gtk.Container.child_get_property(self, child, property_name, value)
+ return value.get_value()
- 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]
__all__.append('SizeGroup')
-class MenuItem(Gtk.MenuItem):
- __init__ = deprecated_init(Gtk.MenuItem.__init__,
- arg_names=('label',),
- category=PyGTKDeprecationWarning)
-
+if Gtk._version in ("2.0", "3.0"):
+ class MenuItem(Gtk.MenuItem):
+ __init__ = deprecated_init(Gtk.MenuItem.__init__,
+ arg_names=('label',),
+ category=PyGTKDeprecationWarning)
-MenuItem = override(MenuItem)
-__all__.append('MenuItem')
+ MenuItem = override(MenuItem)
+ __all__.append('MenuItem')
def _get_utf8_length(string):
TreeModelFilter = override(TreeModelFilter)
__all__.append('TreeModelFilter')
-if Gtk._version != '2.0':
+if Gtk._version == '3.0':
class Menu(Gtk.Menu):
def popup(self, parent_menu_shell, parent_menu_item, func, data, button, activate_time):
self.popup_for_device(None, parent_menu_shell, parent_menu_item, func, data, button, activate_time)
size = g_struct_info_get_size ( (GIStructInfo *) info);
g_assert (size > 0);
- g_memmove ((char*) pointer + offset, value.v_pointer, size);
+ memmove ((char*) pointer + offset, value.v_pointer, size);
g_base_info_unref (info);
GParamSpec **props;
guint n_props = 0, i;
gboolean has_prop = FALSE;
- G_CONST_RETURN gchar *blurb=NULL;
+ const gchar *blurb=NULL;
class = g_type_class_ref(gtype);
props = g_object_class_list_properties(class, &n_props);
#include "pygparamspec.h"
+/* glib 2.62 has started to print warnings for these which can't be disabled selectively, so just copy them here */
+#define PYGI_TYPE_VALUE_ARRAY (g_value_array_get_type())
+#define PYGI_IS_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), PYGI_TYPE_VALUE_ARRAY))
+#define PYGI_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), g_param_spec_types[18], GParamSpecValueArray))
+
GIArgument
_pygi_argument_from_g_value(const GValue *value,
GITypeInfo *type_info)
gboolean holds_value_array;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- holds_value_array = G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY);
+ holds_value_array = G_VALUE_HOLDS(value, PYGI_TYPE_VALUE_ARRAY);
G_GNUC_END_IGNORE_DEPRECATIONS
if (obj == Py_None)
gboolean holds_value_array;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- holds_value_array = G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY);
+ holds_value_array = G_VALUE_HOLDS(value, PYGI_TYPE_VALUE_ARRAY);
G_GNUC_END_IGNORE_DEPRECATIONS
if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT)) {
}
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
int
pyg_param_gvalue_from_pyobject(GValue* value,
PyObject* py_obj,
g_value_set_uint(value, u);
return 0;
}
- else if (G_IS_PARAM_SPEC_VALUE_ARRAY(pspec))
+ else if (PYGI_IS_PARAM_SPEC_VALUE_ARRAY(pspec))
return pyg_value_array_from_pyobject(value, py_obj,
- G_PARAM_SPEC_VALUE_ARRAY(pspec));
+ PYGI_PARAM_SPEC_VALUE_ARRAY(pspec));
else {
return pyg_value_from_pyobject(value, py_obj);
}
}
+G_GNUC_END_IGNORE_DEPRECATIONS
+
PyObject*
pyg_param_gvalue_as_pyobject(const GValue* gvalue,
gboolean copy_boxed,
PyObject_GC_Del(op);
}
-gboolean
+static gboolean
pygobject_prepare_construct_properties(GObjectClass *class, PyObject *kwargs,
- guint *n_params, GParameter **params)
+ guint *n_properties, const char **names[], const GValue **values)
{
- *n_params = 0;
- *params = NULL;
+ *n_properties = 0;
+ *names = NULL;
+ *values = NULL;
if (kwargs) {
Py_ssize_t pos = 0;
PyObject *key;
PyObject *value;
+ Py_ssize_t len;
- *params = g_new0(GParameter, PyDict_Size(kwargs));
+ len = PyDict_Size(kwargs);
+ *names = g_new(const char*, len);
+ *values = g_new0(GValue, len);
while (PyDict_Next(kwargs, &pos, &key, &value)) {
GParamSpec *pspec;
- GParameter *param = &(*params)[*n_params];
+ GValue *gvalue = &(*values)[*n_properties];
+
const gchar *key_str = PYGLIB_PyUnicode_AsString(key);
pspec = g_object_class_find_property(class, key_str);
G_OBJECT_CLASS_NAME(class), key_str);
return FALSE;
}
- g_value_init(¶m->value, G_PARAM_SPEC_VALUE_TYPE(pspec));
- if (pyg_param_gvalue_from_pyobject(¶m->value, value, pspec) < 0) {
+ g_value_init(gvalue, G_PARAM_SPEC_VALUE_TYPE(pspec));
+ if (pyg_param_gvalue_from_pyobject(gvalue, value, pspec) < 0) {
PyErr_Format(PyExc_TypeError,
"could not convert value for property `%s' from %s to %s",
key_str, Py_TYPE(value)->tp_name,
g_type_name(G_PARAM_SPEC_VALUE_TYPE(pspec)));
return FALSE;
}
- param->name = g_strdup(key_str);
- ++(*n_params);
+ (*names)[*n_properties] = g_strdup(key_str);
+ ++(*n_properties);
}
}
return TRUE;
pygobject_init(PyGObject *self, PyObject *args, PyObject *kwargs)
{
GType object_type;
- guint n_params = 0, i;
- GParameter *params = NULL;
+ guint n_properties = 0, i;
+ const GValue *values = NULL;
+ const char **names = NULL;
GObjectClass *class;
/* Only do GObject creation and property setting if the GObject hasn't
return -1;
}
- if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, ¶ms))
+ if (!pygobject_prepare_construct_properties (class, kwargs, &n_properties, &names, &values))
goto cleanup;
- if (pygobject_constructv(self, n_params, params))
- PyErr_SetString(PyExc_RuntimeError, "could not create object");
+ if (pygobject_constructv(self, n_properties, names, values))
+ PyErr_SetString(PyExc_RuntimeError, "could not create object");
cleanup:
- for (i = 0; i < n_params; i++) {
- g_free((gchar *) params[i].name);
- g_value_unset(¶ms[i].value);
+ for (i = 0; i < n_properties; i++) {
+ g_free(names[i]);
+ g_value_unset(&values[i]);
}
- g_free(params);
+ g_free(names);
+ g_free(values);
+
g_type_class_unref(class);
return (self->obj) ? 0 : -1;
if (G_VALUE_HOLDS_OBJECT (&ret)) {
GObject *obj = g_value_get_object (&ret);
- was_floating = g_object_is_floating (obj);
+ if (obj != NULL && G_IS_OBJECT(obj)) {
+ was_floating = g_object_is_floating (obj);
+ }
}
py_ret = pyg_value_as_pyobject(&ret, TRUE);
if (!was_floating)
GType type;
GObject *obj = NULL;
GObjectClass *class;
- guint n_params = 0, i;
- GParameter *params = NULL;
+ guint n_properties = 0, i;
+ const GValue *values = NULL;
+ const char **names = NULL;
if (!PyArg_ParseTuple (args, "O:gobject.new", &pytype)) {
return NULL;
return NULL;
}
- if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, ¶ms))
+ if (!pygobject_prepare_construct_properties (class, kwargs, &n_properties, &names, &values))
goto cleanup;
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- obj = g_object_newv(type, n_params, params);
-G_GNUC_END_IGNORE_DEPRECATIONS
+ obj = pygobject_object_new_with_properties(type, n_properties, names, values);
if (!obj)
PyErr_SetString (PyExc_RuntimeError, "could not create object");
cleanup:
- for (i = 0; i < n_params; i++) {
- g_free((gchar *) params[i].name);
- g_value_unset(¶ms[i].value);
+ for (i = 0; i < n_properties; i++) {
+ g_free(names[i]);
+ g_value_unset(&values[i]);
}
- g_free(params);
+ g_free(names);
+ g_free(values);
+
g_type_class_unref(class);
if (obj) {
g_object_get_qdata(obj, pygobject_instance_data_key));
}
-gboolean pygobject_prepare_construct_properties (GObjectClass *class,
- PyObject *kwargs,
- guint *n_params,
- GParameter **params);
void pygobject_register_class (PyObject *dict,
const gchar *type_name,
GType gtype, PyTypeObject *type,
project('pygobject', 'c',
- version : '3.34.0',
+ version : '3.36.0',
meson_version : '>= 0.46.0',
default_options : [ 'warning_level=1',
'buildtype=debugoptimized'])
pymod = import('python')
python = pymod.find_installation(get_option('python'))
+if python.language_version().version_compare('< 3.0') and host_machine.system() == 'windows'
+ error('Python 2 on Windows no longer supported since 3.35. Use Python 3 instead.')
+endif
+
python_dep = python.dependency()
glib_version_req = '>= 2.48.0'
[coverage:run]
branch=True
+relative_files=True
include=
gi/*
tests/*
from distutils.spawn import find_executable
-PYGOBJECT_VERSION = "3.34.0"
+PYGOBJECT_VERSION = "3.36.0"
GLIB_VERSION_REQUIRED = "2.48.0"
GI_VERSION_REQUIRED = "1.46.0"
PYCAIRO_VERSION_REQUIRED = "1.11.1"
add_ext_compiler_flags(gi_cairo_ext, compiler)
def run(self):
+ if os.name == "nt" and sys.version_info[0] == 2:
+ raise SystemExit("Python 2 on Windows no longer supported since 3.35. Use Python 3 instead.")
+
self._write_config_h()
self._setup_extensions()
du_build_ext.run(self)
[wrap-git]
directory=pycairo
url=https://github.com/pygobject/pycairo.git
-revision=master
+revision=pycairo-1.18
os.environ['GSETTINGS_SCHEMA_DIR'] = tests_builddir
os.environ['G_FILENAME_ENCODING'] = 'UTF-8'
+ # Avoid accessibility dbus warnings
+ os.environ['NO_AT_BRIDGE'] = '1'
+
# Force the default theme so broken themes don't affect the tests
os.environ['GTK_THEME'] = 'Adwaita'
{
SIGNAL_0,
ACTION_SIGNAL,
+ ACTION2_SIGNAL,
LAST_SIGNAL
};
return ret;
}
+static RegressTestAction *
+regress_test_action_do_action2 (RegressTestAction *self)
+{
+ return NULL;
+}
+
static void
regress_test_action_init (RegressTestAction *self)
{
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_CALLBACK (regress_test_action_do_action), NULL, NULL,
NULL, regress_test_action_get_type (), 0);
+
+ /**
+ * RegressTestAction::action2:
+ *
+ * Another action signal.
+ *
+ * Returns: (transfer full): another #RegressTestAction
+ */
+ regress_test_action_signals[ACTION2_SIGNAL] =
+ g_signal_new_class_handler ("action2",
+ G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (regress_test_action_do_action2), NULL, NULL,
+ NULL, regress_test_action_get_type (), 0);
}
assert w.goodbye_button.props.label == "Goodbye World"
assert w.callback_hello == []
- w._hello_button.clicked()
+ w._hello_button.emit("clicked")
assert w.callback_hello == [(w,)]
assert w.callback_hello_after == [(w,)]
assert w.callback_goodbye == []
- w.goodbye_button.clicked()
+ w.goodbye_button.emit("clicked")
assert w.callback_goodbye == [(w.goodbye_button,)]
assert w.callback_goodbye_after == [(w.goodbye_button,)]
def test_duplicate_handler():
-
type_name = new_gtype_name()
xml = """\
<template class="{0}" parent="GtkBox">
<child>
<object class="GtkButton" id="hello_button">
- <signal name="clicked" handler="hello_button_clicked">
+ <signal name="clicked" handler="hello_button_clicked" />
</object>
</child>
</template>
def test_handler_swapped_not_supported():
-
type_name = new_gtype_name()
xml = """\
def test_handler_class_staticmethod():
-
type_name = new_gtype_name()
xml = """\
signal_args_static.append(args)
foo = Foo()
- foo.hello_button.clicked()
+ foo.hello_button.emit("clicked")
assert signal_args_class == [(Foo, foo.hello_button)]
assert signal_args_static == [(foo.hello_button,)]
+@pytest.mark.skipif(Gtk._version == "4.0", reason="errors out first with gtk4")
def test_check_decorated_class():
-
NonWidget = type("Foo", (object,), {})
with pytest.raises(TypeError, match=".*on Widgets.*"):
Gtk.Template.from_string("")(NonWidget)
toplevel = widget
else:
if Gtk._version == "4.0":
- toplevel = widget.get_parent_surface()
+ toplevel = widget.get_parent()
else:
toplevel = widget.get_parent_window()
@unittest.skipUnless(Gtk, 'Gtk not available')
+@unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
def test_freeze_child_notif():
events = []
c = Gtk.Button()
c.connect("child-notify", on_notify)
c.freeze_child_notify()
- if GTK4:
- b.pack_start(c)
- else:
- b.pack_start(c, True, True, 0)
+ 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()
else:
win.size_allocate(rect)
self.assertTrue(win._alloc_called)
- self.assertIsInstance(win._alloc_value, Gdk.Rectangle)
+ if GTK4:
+ self.assertIsInstance(win._alloc_value, int)
+ else:
+ self.assertIsInstance(win._alloc_value, Gdk.Rectangle)
self.assertTrue(win._alloc_error is None, win._alloc_error)
@unittest.expectedFailure # https://bugzilla.gnome.org/show_bug.cgi?id=735693
result = box.child_get_property(child, 'padding')
self.assertEqual(result, 42)
+ @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
def test_child_get_property_error(self):
box = Gtk.Box()
child = Gtk.Button()
if Gtk_version == "4.0":
- box.pack_start(child)
+ box.add(child)
else:
box.pack_start(child, expand=False, fill=True, padding=42)
with self.assertRaises(ValueError):
obj = Regress.TestAction()
other_obj = obj.emit('action')
self.assertEqual(other_obj.__grefcount__, 1)
+ other_obj2 = obj.emit('action2')
+ self.assertIsNone(other_obj2)
class TestIntrospectedSignalsIssue158(unittest.TestCase):
Py_RETURN_NONE;
}
+#define PYGI_TYPE_VALUE_ARRAY (g_value_array_get_type())
+
static PyObject *
_wrap_test_value_array(PyObject *self, PyObject *args)
{
return NULL;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- g_value_init(value, G_TYPE_VALUE_ARRAY);
+ g_value_init(value, PYGI_TYPE_VALUE_ARRAY);
G_GNUC_END_IGNORE_DEPRECATIONS
if (pyg_value_from_pyobject(value, obj)) {
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (pyg_boxed_check(obj, G_TYPE_VALUE) &&
- G_VALUE_HOLDS(pyg_boxed_get(obj, GValue), G_TYPE_VALUE_ARRAY)) {
+ G_VALUE_HOLDS(pyg_boxed_get(obj, GValue), PYGI_TYPE_VALUE_ARRAY)) {
arr = g_value_get_boxed(pyg_boxed_get(obj, GValue));
- } else if (pyg_boxed_check(obj, G_TYPE_VALUE_ARRAY)) {
+ } else if (pyg_boxed_check(obj, PYGI_TYPE_VALUE_ARRAY)) {
arr = pyg_boxed_get(obj, GValueArray);
} else {
PyErr_SetString(PyExc_TypeError, "First argument is not GValueArray");
return py_list;
}
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static PyObject *
_wrap_test_parse_constructor_args (PyObject *self, PyObject *args)
return PYGLIB_PyLong_FromLong (nparams);
}
+G_GNUC_END_IGNORE_DEPRECATIONS
+
static PyObject *
_wrap_test_to_unichar_conv (PyObject * self, PyObject *args)
{