Imported Upstream version 3.36.0 upstream/3.36.0
authorDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 25 Nov 2020 05:49:11 +0000 (14:49 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 25 Nov 2020 05:49:11 +0000 (14:49 +0900)
39 files changed:
.gitlab-ci.yml
.gitlab-ci/Dockerfile
.gitlab-ci/Dockerfile.gtk4 [deleted file]
.gitlab-ci/Dockerfile.old
.gitlab-ci/coverage-docker.sh
.gitlab-ci/fixup-covpy-paths.py [new file with mode: 0644]
.gitlab-ci/fixup-lcov-paths.py [moved from .gitlab-ci/fixup-cov-paths.py with 100% similarity]
.gitlab-ci/run-docker-gtk4.sh [deleted file]
.gitlab-ci/run-docker-old.sh
.gitlab-ci/run-docker-runtime.sh
.gitlab-ci/run-docker.sh
.gitlab-ci/test-docker-gtk4.sh [deleted file]
.gitlab-ci/test-docker-old.sh
.gitlab-ci/test-docker.sh
.gitlab-ci/test-flatpak-gtk4.sh [new file with mode: 0755]
.gitlab-ci/test-flatpak.sh
.gitlab-ci/test-msys2.sh
NEWS
docs/getting_started.rst
docs/guide/api/basic_types.rst
docs/index.rst
gi/gimodule.c
gi/gimodule.h
gi/overrides/Gtk.py
gi/pygi-info.c
gi/pygi-type.c
gi/pygi-value.c
gi/pygobject-object.c
gi/pygobject-object.h
meson.build
setup.cfg
setup.py
subprojects/pycairo.wrap
tests/__init__.py
tests/regressextra.c
tests/test_gtk_template.py
tests/test_overrides_gtk.py
tests/test_signal.py
tests/testhelpermodule.c

index be27ed2..f93d384 100644 (file)
@@ -1,4 +1,4 @@
-image: registry.gitlab.gnome.org/gnome/pygobject/main:v11
+image: registry.gitlab.gnome.org/gnome/pygobject/main:v13
 
 stages:
   - build_and_test
@@ -34,7 +34,7 @@ coverage:
     paths:
       - coverage/
   variables:
-    PYENV_VERSION: "3.6.8"
+    PYENV_VERSION: "3.6.10"
   script:
     - bash -x ./.gitlab-ci/coverage-docker.sh
 
@@ -51,20 +51,6 @@ pages:
   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"
@@ -81,62 +67,67 @@ python3-mingw64:
 
 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
index eaaa484..75d66d8 100644 (file)
@@ -39,12 +39,12 @@ ENV PYTHON_CONFIGURE_OPTS="--enable-shared"
 
 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}"
diff --git a/.gitlab-ci/Dockerfile.gtk4 b/.gitlab-ci/Dockerfile.gtk4
deleted file mode 100644 (file)
index a1e6034..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-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
index fa135de..7f53e40 100644 (file)
@@ -17,8 +17,8 @@ RUN apt-get update && apt-get install -y \
     libgtk-3-0 \
     libtool \
     locales \
-    python-dev \
-    python-virtualenv \
+    python3-dev \
+    python3-venv \
     xauth \
     xvfb \
     && rm -rf /var/lib/apt/lists/*
index 2a51d03..e594f1c 100755 (executable)
@@ -5,7 +5,8 @@ set -e
 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
@@ -14,7 +15,7 @@ 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
 
diff --git a/.gitlab-ci/fixup-covpy-paths.py b/.gitlab-ci/fixup-covpy-paths.py
new file mode 100644 (file)
index 0000000..3efdc5a
--- /dev/null
@@ -0,0 +1,17 @@
+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))
diff --git a/.gitlab-ci/run-docker-gtk4.sh b/.gitlab-ci/run-docker-gtk4.sh
deleted file mode 100755 (executable)
index e2de085..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/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
index 4dd1752..6f6a1d6 100755 (executable)
@@ -2,7 +2,7 @@
 
 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" .
index 0205ec6..d70cba3 100755 (executable)
@@ -8,4 +8,4 @@ sudo docker pull "${TAG}"
 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
index c1d362b..148e5f4 100755 (executable)
@@ -2,10 +2,10 @@
 
 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
diff --git a/.gitlab-ci/test-docker-gtk4.sh b/.gitlab-ci/test-docker-gtk4.sh
deleted file mode 100755 (executable)
index 0dd1219..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/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
index 91312c7..c06f7ee 100755 (executable)
@@ -2,20 +2,21 @@
 
 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
index 7205f8b..dcf4636 100755 (executable)
@@ -11,7 +11,8 @@ COV_DIR="${SOURCE_DIR}/coverage"
 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"
 
@@ -21,8 +22,7 @@ export PYTHONDEVMODE=1
 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"
 
@@ -47,7 +47,7 @@ fi;
 
 # 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 \
diff --git a/.gitlab-ci/test-flatpak-gtk4.sh b/.gitlab-ci/test-flatpak-gtk4.sh
new file mode 100755 (executable)
index 0000000..320a107
--- /dev/null
@@ -0,0 +1,14 @@
+#!/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
index 0dd01c4..b76eefa 100755 (executable)
@@ -6,4 +6,4 @@ python3 -m pip install --user pytest pytest-faulthandler
 # 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
index 9f3d875..133e2e6 100755 (executable)
@@ -31,9 +31,6 @@ pacman --noconfirm -S --needed \
     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
@@ -52,7 +49,7 @@ export COVERAGE_FILE="${COV_DIR}/.coverage.${COV_KEY}"
 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"
diff --git a/NEWS b/NEWS
index 0895e12..552738b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,20 @@
+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
 -------------------
 
index c171b78..a2f53dd 100644 (file)
@@ -127,7 +127,7 @@ Installing from PyPI with pip:
 
 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``
 
index b41fee9..6248f94 100644 (file)
@@ -40,9 +40,6 @@ Platform String Types
 * 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
 -----------
index e000590..7646390 100644 (file)
@@ -69,6 +69,8 @@ Who Is Using PyGObject?
 
 * `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
index c9b29f5..cf3c5ea 100644 (file)
@@ -460,6 +460,8 @@ pyg_param_spec_from_object (PyObject *tuple)
     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
@@ -514,6 +516,8 @@ pyg_parse_constructor_args(GType        obj_type,
     return TRUE;
 }
 
+G_GNUC_END_IGNORE_DEPRECATIONS
+
 /* Only for backwards compatibility */
 static int
 pygobject_enable_threads(void)
@@ -1001,19 +1005,53 @@ pygobject_init_wrapper_get(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);
index 7917ef6..b9274bc 100644 (file)
@@ -4,7 +4,14 @@
 #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_*/
index b5c2dd0..834f5eb 100644 (file)
@@ -137,9 +137,10 @@ class Widget(Gtk.Widget):
 
     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):
@@ -186,18 +187,19 @@ class Container(Gtk.Container, Widget):
     # 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]
@@ -450,14 +452,14 @@ SizeGroup = override(SizeGroup)
 __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):
@@ -1605,7 +1607,7 @@ class TreeModelFilter(Gtk.TreeModelFilter):
 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)
index 94564ed..0c4824f 100644 (file)
@@ -2080,7 +2080,7 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self,
                 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);
 
index 3ca0fc8..952d307 100644 (file)
@@ -1162,7 +1162,7 @@ add_property_docs(GType gtype, GString *string)
     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);
index 8376231..0c54c3e 100644 (file)
 #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)
@@ -502,7 +507,7 @@ pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj)
         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)
@@ -718,7 +723,7 @@ value_to_py_structured_type (const GValue *value, GType fundamental, gboolean co
         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)) {
@@ -826,6 +831,7 @@ pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed)
 }
 
 
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 int
 pyg_param_gvalue_from_pyobject(GValue* value,
                                PyObject* py_obj,
@@ -841,14 +847,16 @@ pyg_param_gvalue_from_pyobject(GValue* value,
         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,
index bf96995..76b18cc 100644 (file)
@@ -1256,22 +1256,27 @@ pygobject_free(PyObject *op)
     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);
@@ -1281,16 +1286,16 @@ pygobject_prepare_construct_properties(GObjectClass *class, PyObject *kwargs,
                              G_OBJECT_CLASS_NAME(class), key_str);
                 return FALSE;
             }
-            g_value_init(&param->value, G_PARAM_SPEC_VALUE_TYPE(pspec));
-            if (pyg_param_gvalue_from_pyobject(&param->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;
@@ -1302,8 +1307,9 @@ static int
 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
@@ -1337,18 +1343,20 @@ pygobject_init(PyGObject *self, PyObject *args, PyObject *kwargs)
        return -1;
     }
 
-    if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, &params))
+    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(&params[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;
@@ -1939,7 +1947,9 @@ pygobject_emit(PyGObject *self, PyObject *args)
 
       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)
@@ -2495,8 +2505,9 @@ pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs)
     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;
@@ -2517,22 +2528,22 @@ pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs)
        return NULL;
     }
 
-    if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, &params))
+    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(&params[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) {
index 6658244..580939a 100644 (file)
@@ -33,10 +33,6 @@ pyg_object_peek_inst_data(GObject *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,
index 75a9e03..006fee4 100644 (file)
@@ -1,5 +1,5 @@
 project('pygobject', 'c',
-  version : '3.34.0',
+  version : '3.36.0',
   meson_version : '>= 0.46.0',
   default_options : [ 'warning_level=1',
                       'buildtype=debugoptimized'])
@@ -15,6 +15,10 @@ platform_version = '@0@.0'.format(pygobject_version_major)
 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'
index 33186d6..c165fa2 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -4,6 +4,7 @@ exclude=subprojects
 
 [coverage:run]
 branch=True
+relative_files=True
 include=
     gi/*
     tests/*
index a2739ae..19b8cfa 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -41,7 +41,7 @@ from distutils import dir_util, log
 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"
@@ -1111,6 +1111,9 @@ class build_ext(du_build_ext):
             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)
index 87eac57..ba1c656 100644 (file)
@@ -1,4 +1,4 @@
 [wrap-git]
 directory=pycairo
 url=https://github.com/pygobject/pycairo.git
-revision=master
+revision=pycairo-1.18
index 3723b07..c5f02c3 100644 (file)
@@ -89,6 +89,9 @@ def init_test_environ():
     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'
 
index 7e53373..e0ad393 100644 (file)
@@ -343,6 +343,7 @@ enum
 {
     SIGNAL_0,
     ACTION_SIGNAL,
+    ACTION2_SIGNAL,
     LAST_SIGNAL
 };
 
@@ -356,6 +357,12 @@ regress_test_action_do_action (RegressTestAction *self)
     return ret;
 }
 
+static RegressTestAction *
+regress_test_action_do_action2 (RegressTestAction *self)
+{
+    return NULL;
+}
+
 static void
 regress_test_action_init (RegressTestAction *self)
 {
@@ -375,4 +382,17 @@ static void regress_test_action_class_init (RegressTestActionClass *klass)
         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);
 }
index ee197d0..3a1c1f0 100644 (file)
@@ -190,18 +190,17 @@ def test_main_example():
     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 = """\
@@ -209,7 +208,7 @@ def test_duplicate_handler():
   <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>
@@ -300,7 +299,6 @@ def test_missing_handler_callback():
 
 
 def test_handler_swapped_not_supported():
-
     type_name = new_gtype_name()
 
     xml = """\
@@ -332,7 +330,6 @@ def test_handler_swapped_not_supported():
 
 
 def test_handler_class_staticmethod():
-
     type_name = new_gtype_name()
 
     xml = """\
@@ -368,13 +365,13 @@ def test_handler_class_staticmethod():
             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)
index d791e24..9c32e8b 100644 (file)
@@ -56,7 +56,7 @@ def realized(widget):
         toplevel = widget
     else:
         if Gtk._version == "4.0":
-            toplevel = widget.get_parent_surface()
+            toplevel = widget.get_parent()
         else:
             toplevel = widget.get_parent_window()
 
@@ -79,6 +79,7 @@ def realized(widget):
 
 
 @unittest.skipUnless(Gtk, 'Gtk not available')
+@unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
 def test_freeze_child_notif():
 
     events = []
@@ -90,10 +91,7 @@ def test_freeze_child_notif():
     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()
@@ -895,7 +893,10 @@ class TestSignals(unittest.TestCase):
             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
@@ -2699,11 +2700,12 @@ class TestContainer(unittest.TestCase):
         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):
index edc970f..68592c5 100644 (file)
@@ -1247,6 +1247,8 @@ class TestIntrospectedSignals(unittest.TestCase):
         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):
index e26a004..82b0399 100644 (file)
@@ -513,6 +513,8 @@ _wrap_test_state_ensure_release(PyObject *self, PyObject *args)
     Py_RETURN_NONE;
 }
 
+#define PYGI_TYPE_VALUE_ARRAY (g_value_array_get_type())
+
 static PyObject *
 _wrap_test_value_array(PyObject *self, PyObject *args)
 {
@@ -523,7 +525,7 @@ _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)) {
@@ -550,9 +552,9 @@ _wrap_value_array_get_nth_type(PyObject *self, PyObject *args)
   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");
@@ -655,6 +657,7 @@ _wrap_test_floating_and_sunk_get_instance_list (PyObject *self)
     return py_list;
 }
 
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 
 static PyObject *
 _wrap_test_parse_constructor_args (PyObject *self, PyObject *args)
@@ -676,6 +679,8 @@ _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)
 {