├── .clang-format ├── .coveragerc ├── .flake8 ├── .gitignore ├── .gitlab-ci.yml ├── .gitlab-ci ├── Dockerfile ├── README.rst ├── build-sdists.sh ├── coverage-docker.sh ├── fixup-lcov-paths.py ├── lcovrc ├── run-docker-runtime.sh ├── run-docker.sh ├── set_env.sh ├── test-docker.sh ├── test-flatpak.sh └── test-msys2.sh ├── .pre-commit-config.yaml ├── COPYING ├── METADATA.in ├── NEWS ├── README.rst ├── docs ├── Makefile ├── bugs_repo.rst ├── changelog.rst ├── conf.py ├── contact.rst ├── devguide │ ├── dev_environ.rst │ ├── index.rst │ ├── maintguide.rst │ ├── override_guidelines.rst │ ├── overview.rst │ ├── packagingguide.rst │ └── style_guide.rst ├── extra.css ├── getting_started.rst ├── guide │ ├── api │ │ ├── api.rst │ │ ├── basic_types.rst │ │ ├── error_handling.rst │ │ ├── flags_enums.rst │ │ ├── gobject.rst │ │ ├── index.rst │ │ ├── properties.rst │ │ ├── signals.rst │ │ └── weakrefs.rst │ ├── asynchronous.rst │ ├── cairo_integration.rst │ ├── code │ │ └── cairo-demo.py │ ├── debug_profile.rst │ ├── deploy.rst │ ├── download_asyncio.py │ ├── download_callback.py │ ├── faq.rst │ ├── flatpaking.rst │ ├── gtk_template.rst │ ├── images │ │ └── cairo_integration.png │ ├── imports.rst │ ├── index.rst │ ├── porting.rst │ ├── sysdeps.rst │ ├── testing.rst │ └── threading.rst ├── icons.rst ├── images │ ├── LICENSE │ ├── favicon.ico │ ├── logo.svg │ ├── overview-dark.svg │ ├── overview.dia │ ├── overview.svg │ ├── pygobject-dark.svg │ ├── pygobject-small.svg │ ├── pygobject.svg │ ├── start_linux.png │ ├── start_macos.png │ └── start_windows.png ├── index.rst └── tutorials │ ├── _static │ └── custom.css │ ├── gobject.rst │ ├── gobject │ ├── basics.rst │ ├── examples │ │ └── listmodel.py │ ├── interfaces.rst │ └── subclassing.rst │ ├── gtk3.rst │ ├── gtk4.rst │ ├── gtk4 │ ├── application.rst │ ├── basics.rst │ ├── clipboard.rst │ ├── controls.rst │ ├── controls │ │ ├── buttons.rst │ │ ├── check-radio-buttons.rst │ │ ├── dropdown.rst │ │ ├── entries.rst │ │ ├── examples │ │ │ ├── button.py │ │ │ ├── check_radio_buttons.py │ │ │ ├── dropdown.py │ │ │ ├── entries.py │ │ │ ├── linkbutton.py │ │ │ ├── spinbutton.py │ │ │ ├── switch.py │ │ │ └── togglebutton.py │ │ ├── images │ │ │ ├── button.png │ │ │ ├── check_radio_buttons.png │ │ │ ├── dropdown.png │ │ │ ├── entries.png │ │ │ ├── linkbutton.png │ │ │ ├── spinbutton.png │ │ │ ├── switch.png │ │ │ └── togglebutton.png │ │ ├── scale.rst │ │ ├── spinbutton.rst │ │ └── switch.rst │ ├── display-widgets.rst │ ├── display-widgets │ │ ├── examples │ │ │ ├── label.py │ │ │ ├── picture.py │ │ │ ├── progressbar.py │ │ │ ├── spinner.py │ │ │ └── spinner_ext.py │ │ ├── image.rst │ │ ├── images │ │ │ ├── label.png │ │ │ ├── picture.png │ │ │ ├── progressbar.png │ │ │ ├── spinner.png │ │ │ └── spinner_ext.png │ │ ├── label.rst │ │ ├── picture.rst │ │ ├── progressbar.rst │ │ └── spinner.rst │ ├── drag-and-drop.rst │ ├── examples │ │ ├── application.py │ │ ├── clipboard.py │ │ ├── drag_and_drop.py │ │ ├── extended_example.py │ │ ├── layout_box.py │ │ ├── layout_center.py │ │ ├── layout_flowbox.py │ │ ├── layout_grid.py │ │ ├── layout_headerbar.py │ │ ├── layout_listbox.py │ │ ├── layout_notebook.py │ │ ├── layout_stack.py │ │ ├── popover.py │ │ ├── popover_menu.py │ │ ├── simple_example.py │ │ └── textview.py │ ├── images │ │ ├── application.png │ │ ├── basic_example.png │ │ ├── clipboard.png │ │ ├── drag_and_drop.png │ │ ├── extended_example.png │ │ ├── layout_box.png │ │ ├── layout_center.png │ │ ├── layout_flowbox.png │ │ ├── layout_grid.png │ │ ├── layout_headerbar.png │ │ ├── layout_listbox.png │ │ ├── layout_notebook.png │ │ ├── layout_stack.png │ │ ├── popover.png │ │ ├── popover_menu.png │ │ └── textview.png │ ├── introduction.rst │ ├── layout-widgets.rst │ ├── popovers.rst │ └── textview.rst │ ├── index.rst │ ├── libadwaita.rst │ └── libadwaita │ └── application.rst ├── gi ├── __init__.py ├── _constants.py ├── _enum.py ├── _error.py ├── _gtktemplate.py ├── _option.py ├── _ossighelper.py ├── _propertyhelper.py ├── _signalhelper.py ├── _signature.py ├── docstring.py ├── events.py ├── gimodule.c ├── gimodule.h ├── importer.py ├── meson.build ├── module.py ├── overrides │ ├── GIMarshallingTests.py │ ├── GLib.py │ ├── GObject.py │ ├── Gdk.py │ ├── GdkPixbuf.py │ ├── Gio.py │ ├── Gtk.py │ ├── Pango.py │ ├── __init__.py │ └── meson.build ├── pygboxed.c ├── pygboxed.h ├── pygenum.c ├── pygenum.h ├── pygflags.c ├── pygflags.h ├── pygi-argument.c ├── pygi-argument.h ├── pygi-array.c ├── pygi-array.h ├── pygi-async.c ├── pygi-async.h ├── pygi-basictype.c ├── pygi-basictype.h ├── pygi-boxed.c ├── pygi-boxed.h ├── pygi-cache.c ├── pygi-cache.h ├── pygi-ccallback.c ├── pygi-ccallback.h ├── pygi-closure.c ├── pygi-closure.h ├── pygi-enum-marshal.c ├── pygi-enum-marshal.h ├── pygi-error.c ├── pygi-error.h ├── pygi-foreign-api.h ├── pygi-foreign-cairo.c ├── pygi-foreign.c ├── pygi-foreign.h ├── pygi-fundamental.c ├── pygi-fundamental.h ├── pygi-hashtable.c ├── pygi-hashtable.h ├── pygi-info.c ├── pygi-info.h ├── pygi-invoke-state-struct.h ├── pygi-invoke.c ├── pygi-invoke.h ├── pygi-list.c ├── pygi-list.h ├── pygi-marshal-cleanup.c ├── pygi-marshal-cleanup.h ├── pygi-object.c ├── pygi-object.h ├── pygi-property.c ├── pygi-property.h ├── pygi-repository.c ├── pygi-repository.h ├── pygi-resulttuple.c ├── pygi-resulttuple.h ├── pygi-signal-closure.c ├── pygi-signal-closure.h ├── pygi-source.c ├── pygi-source.h ├── pygi-struct-marshal.c ├── pygi-struct-marshal.h ├── pygi-struct.c ├── pygi-struct.h ├── pygi-type.c ├── pygi-type.h ├── pygi-util.c ├── pygi-util.h ├── pygi-value.c ├── pygi-value.h ├── pyginterface.c ├── pyginterface.h ├── pygobject-internal.h ├── pygobject-object.c ├── pygobject-object.h ├── pygobject.h ├── pygoptioncontext.c ├── pygoptioncontext.h ├── pygoptiongroup.c ├── pygoptiongroup.h ├── pygpointer.c ├── pygpointer.h ├── pygspawn.c ├── pygspawn.h ├── pygtkcompat.py ├── repository │ ├── __init__.py │ └── meson.build └── types.py ├── meson.build ├── meson_options.txt ├── pygobject-3.0.pc.in ├── pygobject.doap ├── pygtkcompat ├── __init__.py ├── meson.build └── pygtkcompat.py ├── pyproject.toml ├── subprojects ├── glib.wrap ├── gobject-introspection-tests.wrap ├── gobject-introspection.wrap ├── libffi.wrap ├── packagefiles │ ├── pythoncapi-compat-dist.py │ └── pythoncapi-compat-meson.diff ├── pycairo.wrap └── pythoncapi-compat.wrap ├── tests ├── conftest.py ├── gi │ └── overrides │ │ ├── Regress.py │ │ └── __init__.py ├── helper.py ├── meson.build ├── org.gnome.test.gschema.xml ├── test-floating.c ├── test-floating.h ├── test-thread.c ├── test-thread.h ├── test-unknown.c ├── test-unknown.h ├── test_async.py ├── test_atoms.py ├── test_cairo.py ├── test_docstring.py ├── test_enum.py ├── test_error.py ├── test_events.py ├── test_everything.py ├── test_fields.py ├── test_fundamental.py ├── test_gdbus.py ├── test_gi.py ├── test_gio.py ├── test_glib.py ├── test_gobject.py ├── test_gtk_template.py ├── test_gtype.py ├── test_import_machinery.py ├── test_interface.py ├── test_internal_api.py ├── test_iochannel.py ├── test_mainloop.py ├── test_object_marshaling.py ├── test_option.py ├── test_ossig.py ├── test_overrides_gdk.py ├── test_overrides_gdkpixbuf.py ├── test_overrides_gio.py ├── test_overrides_glib.py ├── test_overrides_gobject.py ├── test_overrides_gtk.py ├── test_overrides_pango.py ├── test_properties.py ├── test_pycapi.py ├── test_pygtkcompat.py ├── test_repository.py ├── test_resulttuple.py ├── test_signal.py ├── test_signature.py ├── test_source.py ├── test_subprocess.py ├── test_thread.py ├── test_typeclass.py ├── test_unknown.py ├── testhelpermodule.c └── valgrind.supp └── tools ├── mkmetadata.py └── pygi-convert.sh /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | relative_files = True 4 | include = 5 | gi/* 6 | tests/* 7 | pygtkcompat/* 8 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore=E501,E123,E124,E402,E731,E722,W504 3 | exclude=subprojects,build,.venv 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | .mypy_cache 3 | *.bak 4 | *.lo 5 | *.o 6 | *.orig 7 | *.pyc 8 | *.rej 9 | *.so 10 | *.la 11 | *.tab.c 12 | *~ 13 | .*.sw[nop] 14 | *.gir 15 | *.typelib 16 | *.dll 17 | *.dylib 18 | .DS_STORE 19 | .idea 20 | .cache 21 | .pytest_cache 22 | /tmp/* 23 | /build/ 24 | /dist/ 25 | /pygobject.egg-info/ 26 | /docs/_build 27 | /PyGObject.egg-info/ 28 | /subprojects/*/ 29 | !/subprojects/packagefiles/ 30 | *.pyd 31 | *.dll.a 32 | .coverage 33 | pdm.lock 34 | .pdm-python 35 | -------------------------------------------------------------------------------- /.gitlab-ci/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:noble 2 | 3 | ENV DEBIAN_FRONTEND=noninteractive 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | software-properties-common \ 7 | build-essential \ 8 | ccache \ 9 | curl \ 10 | dbus \ 11 | gir1.2-freedesktop-dev \ 12 | gir1.2-girepository-3.0-dev \ 13 | gir1.2-gtk-3.0 \ 14 | gir1.2-gtk-4.0 \ 15 | git \ 16 | gobject-introspection \ 17 | lcov \ 18 | libbz2-dev \ 19 | libcairo2-dev \ 20 | libffi-dev \ 21 | libgirepository-2.0-dev \ 22 | libglib2.0-dev \ 23 | libgtk-3-0 \ 24 | libgtk-4-1 \ 25 | libreadline-dev \ 26 | libsqlite3-dev \ 27 | libssl-dev \ 28 | liblzma-dev \ 29 | ninja-build \ 30 | python3-pip \ 31 | sudo \ 32 | xauth \ 33 | xvfb \ 34 | && rm -rf /var/lib/apt/lists/* 35 | 36 | RUN add-apt-repository -y ppa:pypy/ppa \ 37 | && apt-get update \ 38 | && apt-get install -y pypy3 pypy3-dev pypy3-venv \ 39 | && rm -rf /var/lib/apt/lists/* \ 40 | && sed -i 's#/build/pypy3-[^/]*/[^/]*#/usr#g' /usr/lib/pypy3.*/_sysconfigdata__x86_64-linux-gnu.py 41 | 42 | ARG HOST_USER_ID=5555 43 | ENV HOST_USER_ID=${HOST_USER_ID} 44 | RUN useradd -u $HOST_USER_ID -ms /bin/bash user \ 45 | && echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers 46 | 47 | USER user 48 | WORKDIR /home/user 49 | 50 | ENV LANG=C.UTF-8 51 | ENV CI=true 52 | ENV PYENV_ROOT=/home/user/.pyenv 53 | ENV PATH="${PYENV_ROOT}/shims:${PYENV_ROOT}/bin:${PATH}" 54 | ENV PYTHON_CONFIGURE_OPTS="--enable-shared" 55 | 56 | # https://github.com/pyenv/pyenv/releases 57 | ENV PYENV_GIT_TAG=v2.4.17 58 | RUN curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash 59 | 60 | # Register the pypy3 system installation 61 | RUN mkdir -p "${PYENV_ROOT}/versions/pypy3-system/bin/" \ 62 | && sudo ln -s /usr/bin/pypy3 "${PYENV_ROOT}/versions/pypy3-system/bin/python" \ 63 | && pyenv rehash 64 | 65 | RUN pyenv install --debug 3.9 66 | RUN pyenv install --debug 3.10 67 | RUN pyenv install --debug 3.11 68 | RUN pyenv install --debug 3.12 69 | RUN pyenv install --debug 3.13 70 | 71 | ENV PATH="/usr/lib/ccache:${PATH}" 72 | 73 | COPY --chown=user:user set_env.sh /home/user/set_env.sh 74 | RUN chmod +x /home/user/set_env.sh 75 | ENTRYPOINT ["/home/user/set_env.sh"] -------------------------------------------------------------------------------- /.gitlab-ci/README.rst: -------------------------------------------------------------------------------- 1 | CI Docker Images 2 | ================ 3 | 4 | There are two images which are used for CI and which can be found here: 5 | https://gitlab.gnome.org/GNOME/pygobject/container_registry 6 | 7 | * `Dockerfile` - contains various Python versions and a commonly used distro. 8 | Run `run-docker.sh` to build it and run a shell in it. After that it can be pushed. 9 | * `Dockerfile.old` - 32bit using the oldest supported distro, to test with old stuff. 10 | Run `run-docker-old.sh` to build it and run a shell in it. After that it can be pushed. 11 | 12 | The scripts spawn a shell in the container with the source code mounted, so 13 | things can be tested locally if needed. 14 | -------------------------------------------------------------------------------- /.gitlab-ci/build-sdists.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | python -m pip install --upgrade pdm 6 | python -m pdm build 7 | 8 | VERSION=$(grep version meson.build | head -1 | sed "s/^.*'\([0-9\.]*\)'.*$/\1/") 9 | 10 | if [[ "$VERSION" =~ ^[0-9]\.[0-9]*[13579]\. ]] 11 | then 12 | cat << EOF 13 | 14 | ****************** ATTENTION ****************** 15 | This is an UNstable release. 16 | Do NOT upload this release to PyPI. 17 | ****************** ATTENTION ****************** 18 | 19 | EOF 20 | fi -------------------------------------------------------------------------------- /.gitlab-ci/coverage-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # Make the Windows paths match our current layout 6 | python ./.gitlab-ci/fixup-lcov-paths.py coverage/*.lcov 7 | 8 | # Remove external headers (except gi tests) 9 | for path in coverage/*.lcov; do 10 | lcov --config-file .gitlab-ci/lcovrc -r "${path}" '/usr/include/*' -o "${path}" 11 | lcov --config-file .gitlab-ci/lcovrc -r "${path}" '/home/*' -o "${path}" 12 | lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*/msys64/*' -o "${path}" 13 | lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*site-packages/*' -o "${path}" 14 | lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*subprojects/*' -o "${path}" 15 | lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*tmp-introspect*' -o "${path}" 16 | lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*/meson-private/*' -o "${path}" 17 | 18 | test -s "${path}" || rm "${path}" 19 | done 20 | 21 | genhtml --config-file .gitlab-ci/lcovrc \ 22 | coverage/*.lcov -o coverage/ 23 | 24 | cd coverage 25 | rm -f .coverage* 26 | rm -f ./*.lcov 27 | -------------------------------------------------------------------------------- /.gitlab-ci/fixup-lcov-paths.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import re 4 | 5 | 6 | def main(argv): 7 | # Fix paths in lcov files generated on a Windows host so they match our 8 | # current source layout. 9 | paths = argv[1:] 10 | 11 | for path in paths: 12 | print("cov-fixup:", path) 13 | with open(path, "r", encoding="utf-8") as h: 14 | text = h.read() 15 | 16 | text = text.replace("\\\\", "/").replace("\\", "/") 17 | new_root = os.getcwd() 18 | 19 | def make_abs(m): 20 | p = m.group(1) 21 | if p.startswith("C:/"): 22 | p = p.replace("C:/", "/c/") 23 | if not p.startswith("/"): 24 | p = os.path.join(new_root, p) 25 | return "SF:" + p 26 | 27 | text = re.sub("SF:(.*?)$", make_abs, text, 0, re.MULTILINE) 28 | 29 | canidate = None 30 | for old_root in set(re.findall(":(.*?)/gi/.*?$", text, re.MULTILINE)): 31 | if canidate is None or len(old_root) < len(canidate): 32 | canidate = old_root 33 | 34 | if canidate: 35 | print("replacing %r with %r" % (canidate, new_root)) 36 | text = text.replace(canidate, new_root) 37 | 38 | with open(path, "w", encoding="utf-8") as h: 39 | h.write(text) 40 | 41 | 42 | if __name__ == "__main__": 43 | sys.exit(main(sys.argv)) 44 | -------------------------------------------------------------------------------- /.gitlab-ci/lcovrc: -------------------------------------------------------------------------------- 1 | # lcov and genhtml configuration 2 | # See http://ltp.sourceforge.net/coverage/lcov/lcovrc.5.php 3 | 4 | # Always enable branch coverage 5 | lcov_branch_coverage = 1 6 | 7 | stop_on_error = 0 8 | 9 | # Exclude precondition assertions, as we can never reasonably get full branch 10 | # coverage of them, as they should never normally fail. 11 | # See https://github.com/linux-test-project/lcov/issues/44 12 | lcov_excl_br_line = LCOV_EXCL_BR_LINE|g_return_if_fail|g_return_val_if_fail|g_assert|g_assert_ 13 | 14 | # Similarly for unreachable assertions. 15 | lcov_excl_line = LCOV_EXCL_LINE|g_return_if_reached|g_return_val_if_reached|g_assert_not_reached 16 | -------------------------------------------------------------------------------- /.gitlab-ci/run-docker-runtime.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | TAG="registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master" 6 | 7 | sudo docker pull "${TAG}" 8 | sudo docker run --privileged --rm --security-opt label=disable \ 9 | --volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \ 10 | --tty --interactive "${TAG}" xvfb-run -a flatpak run --filesystem=host \ 11 | --share=network --socket=x11 --devel --command=bash org.gnome.Sdk//master 12 | -------------------------------------------------------------------------------- /.gitlab-ci/run-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | TAG="registry.gitlab.gnome.org/gnome/pygobject/main:v25" 6 | 7 | sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \ 8 | --file "Dockerfile" . 9 | sudo docker run --rm --security-opt label=disable \ 10 | --volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \ 11 | --tty --interactive "${TAG}" bash 12 | -------------------------------------------------------------------------------- /.gitlab-ci/set_env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | export PYENV_VERSION 6 | PYENV_VERSION="$(pyenv latest "${PYTHON_VERSION:-3}")" 7 | exec "$@" 8 | -------------------------------------------------------------------------------- /.gitlab-ci/test-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | python --version 6 | 7 | SOURCE_DIR="$(pwd)" 8 | COV_DIR="${SOURCE_DIR}/coverage" 9 | COV_KEY="${CI_JOB_NAME_SLUG}" 10 | JUNIT_XML="${SOURCE_DIR}/test-results.xml" 11 | 12 | CFLAGS="-coverage -ftest-coverage -fprofile-arcs -Werror" 13 | MALLOC_CHECK_=3 14 | MALLOC_PERTURB_=$((RANDOM % 255 + 1)) 15 | G_SLICE="debug-blocks" 16 | COVERAGE_FILE="${COV_DIR}/.coverage.${COV_KEY}" 17 | CCACHE_BASEDIR="$(pwd)" 18 | CCACHE_DIR="${CCACHE_BASEDIR}/_ccache" 19 | export CFLAGS MALLOC_CHECK_ MALLOC_PERTURB_ G_SLICE COVERAGE_FILE \ 20 | CCACHE_BASEDIR CCACHE_DIR 21 | 22 | # https://docs.python.org/3/using/cmdline.html#envvar-PYTHONDEVMODE 23 | export PYTHONDEVMODE=1 24 | export MESONPY_EDITABLE_VERBOSE=1 25 | 26 | mkdir -p "${CCACHE_DIR}" 27 | mkdir -p "${COV_DIR}" 28 | 29 | python -m venv /tmp/venv 30 | # shellcheck disable=SC1091 31 | source /tmp/venv/bin/activate 32 | 33 | python -m pip install --upgrade pip 34 | python -m pip install meson meson-python pycairo pytest pytest-cov 35 | 36 | # BUILD & TEST 37 | python -m pip install --config-settings=setup-args="-Dtests=true" --no-build-isolation --editable . 38 | 39 | # TEST 40 | lcov --config-file .gitlab-ci/lcovrc --directory . --capture --initial --output-file \ 41 | "${COV_DIR}/${CI_JOB_NAME_SLUG}-baseline.lcov" 42 | 43 | xvfb-run -a python -m pytest -vs --cov --junit-xml="${JUNIT_XML}" 44 | python -m coverage lcov -o "${COV_DIR}/${COV_KEY}.py.lcov" 45 | 46 | # COLLECT GCOV COVERAGE 47 | lcov --config-file .gitlab-ci/lcovrc --directory . --capture --output-file \ 48 | "${COV_DIR}/${CI_JOB_NAME_SLUG}.lcov" 49 | -------------------------------------------------------------------------------- /.gitlab-ci/test-flatpak.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | DIR="$( cd "$( dirname "$0" )" && pwd )" 6 | 7 | if [[ "$1" == "inflatpak" ]]; then 8 | COV_DIR="$(pwd)/coverage" 9 | COV_KEY="flatpak-$TEST_GTK_VERSION" 10 | COVERAGE_FILE="${COV_DIR}/.coverage.${COV_KEY}" 11 | export COVERAGE_FILE 12 | mkdir -p "${COV_DIR}" 13 | 14 | python3 --version 15 | 16 | pip install pycairo meson meson-python pytest pytest-cov 17 | pip install --config-settings=setup-args="-Dtests=true" --no-build-isolation --editable . 18 | python -m pytest -vs --cov 19 | python3 -m coverage lcov -o "${COV_DIR}/${COV_KEY}.py.lcov" 20 | chmod -R 777 "${COV_DIR}" 21 | else 22 | # https://gitlab.gnome.org/GNOME/gnome-runtime-images/-/issues/7 23 | DBUS_SYSTEM_BUS_ADDRESS="$(dbus-daemon --session --print-address --fork)" 24 | export DBUS_SYSTEM_BUS_ADDRESS 25 | xvfb-run -a flatpak run --user --filesystem=host --share=network --socket=x11 --command=bash org.gnome.Sdk//master -x "${DIR}"/test-flatpak.sh inflatpak 26 | fi 27 | -------------------------------------------------------------------------------- /.gitlab-ci/test-msys2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | pacman --noconfirm -Suy 6 | 7 | pacman --noconfirm -S --needed \ 8 | "${MINGW_PACKAGE_PREFIX}"-ccache \ 9 | "${MINGW_PACKAGE_PREFIX}"-glib2 \ 10 | "${MINGW_PACKAGE_PREFIX}"-gobject-introspection \ 11 | "${MINGW_PACKAGE_PREFIX}"-gtk3 \ 12 | "${MINGW_PACKAGE_PREFIX}"-libffi \ 13 | "${MINGW_PACKAGE_PREFIX}"-meson \ 14 | "${MINGW_PACKAGE_PREFIX}"-ninja \ 15 | "${MINGW_PACKAGE_PREFIX}"-python \ 16 | "${MINGW_PACKAGE_PREFIX}"-python-cairo \ 17 | "${MINGW_PACKAGE_PREFIX}"-python-pip \ 18 | "${MINGW_PACKAGE_PREFIX}"-python-pytest \ 19 | "${MINGW_PACKAGE_PREFIX}"-python-pytest-cov \ 20 | "${MINGW_PACKAGE_PREFIX}"-toolchain \ 21 | git \ 22 | lcov 23 | 24 | # ccache setup 25 | export PATH="$MSYSTEM/lib/ccache/bin:$PATH" 26 | mkdir -p _ccache 27 | CCACHE_BASEDIR="$(pwd)" 28 | export CCACHE_BASEDIR 29 | CCACHE_DIR="${CCACHE_BASEDIR}/_ccache" 30 | export CCACHE_DIR 31 | 32 | # coverage setup 33 | COV_DIR="$(pwd)/coverage" 34 | COV_KEY="${CI_JOB_NAME_SLUG}" 35 | mkdir -p "${COV_DIR}" 36 | export COVERAGE_FILE="${COV_DIR}/.coverage.${COV_KEY}" 37 | 38 | # Test results 39 | JUNIT_XML="test-results.xml" 40 | 41 | # https://docs.python.org/3/using/cmdline.html#envvar-PYTHONDEVMODE 42 | export PYTHONDEVMODE=1 43 | 44 | 45 | MSYSTEM='' CFLAGS="-coverage -ftest-coverage -fprofile-arcs -Werror" meson setup _build 46 | 47 | lcov \ 48 | --config-file .gitlab-ci/lcovrc \ 49 | --directory "$(pwd)" --capture --initial --output-file \ 50 | "${COV_DIR}/${COV_KEY}-baseline.lcov" 51 | 52 | MSYSTEM='' PYTEST_ADDOPTS="--cov -sv --junit-xml=${JUNIT_XML}" meson test --suite pygobject --timeout-multiplier 4 -C _build -v 53 | MSYSTEM='' python -m coverage lcov -o "${COV_DIR}/${COV_KEY}.py.lcov" 54 | 55 | lcov \ 56 | --config-file .gitlab-ci/lcovrc \ 57 | --directory "$(pwd)" --capture --output-file \ 58 | "${COV_DIR}/${COV_KEY}.lcov" 59 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # This is a configuration file for the pre-commit tool. 2 | # Documentation is available at https://pre-commit.com/#plugins 3 | 4 | repos: 5 | - repo: https://github.com/shellcheck-py/shellcheck-py 6 | rev: a23f6b85d0fdd5bb9d564e2579e678033debbdff # frozen: v0.10.0.1 7 | hooks: 8 | - id: shellcheck 9 | - repo: https://github.com/PyCQA/flake8 10 | rev: 7.1.1 11 | hooks: 12 | - id: flake8 13 | -------------------------------------------------------------------------------- /METADATA.in: -------------------------------------------------------------------------------- 1 | Metadata-Version: 2.4 2 | Name: PyGObject 3 | Version: @VERSION@ 4 | Summary: Python bindings for GObject Introspection 5 | Author-Email: James Henstridge 6 | Maintainer-Email: Christoph Reiter , Arjan Molenaar , Dan Yeaw , Ignacio Casal Quinteiro 7 | License-Expression: LGPL-2.1-or-later 8 | License-File: COPYING 9 | Classifier: Development Status :: 5 - Production/Stable 10 | Classifier: Intended Audience :: Developers 11 | Classifier: Operating System :: POSIX 12 | Classifier: Operating System :: Microsoft :: Windows 13 | Classifier: Programming Language :: C 14 | Classifier: Programming Language :: Python 15 | Classifier: Topic :: Software Development :: Libraries :: Python Modules 16 | Project-URL: Homepage, https://pygobject.gnome.org 17 | Project-URL: Repository, https://gitlab.gnome.org/GNOME/pygobject.git 18 | Project-URL: Changelog, https://gitlab.gnome.org/GNOME/pygobject/-/blob/main/NEWS 19 | Requires-Python: <4.0,>=3.9 20 | 21 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. image:: https://gitlab.gnome.org/GNOME/pygobject/-/raw/main/docs/images/pygobject.svg?ref_type=heads 2 | :align: center 3 | :width: 400px 4 | :height: 98px 5 | 6 | | 7 | 8 | **PyGObject** is a Python package which provides bindings for `GObject 9 | `__ based libraries such as `GTK 10 | `__, `GStreamer `__, 11 | `WebKitGTK `__, `GLib 12 | `__, `GIO 13 | `__ and many more. 14 | 15 | It supports Linux, Windows, and macOS and works with **Python 3.9+** and 16 | **PyPy3**. PyGObject, including this documentation, is licensed under the 17 | **LGPLv2.1+**. 18 | 19 | Homepage 20 | -------- 21 | 22 | https://pygobject.gnome.org 23 | 24 | Installation 25 | ------------ 26 | 27 | The latest version from PyGObject can be installed from `PyPI `__: 28 | 29 | pip install PyGObject 30 | 31 | PyGObject is only distributed as source distribution, so you need a C compiler installed on your host. 32 | 33 | Please have a look at our `Getting Started `__ documentation 34 | for OS specific installation instructions. 35 | 36 | Development 37 | ~~~~~~~~~~~ 38 | 39 | Our website contains instructions on how to `set up a development environment 40 | `__. 41 | 42 | Default branch renamed to ``main`` 43 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 44 | 45 | The default development branch of PyGObject has been renamed 46 | to ``main``. To update your local checkout, use:: 47 | 48 | git checkout master 49 | git branch -m master main 50 | git fetch 51 | git branch --unset-upstream 52 | git branch -u origin/main 53 | git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main 54 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | DIAS = $(wildcard images/*.dia) 2 | DIA_SVGS = $(patsubst %.dia,%.svg,$(DIAS)) 3 | 4 | all: _build 5 | 6 | images/%.svg: images/%.dia 7 | dia $< --export=$@ --filter=dia-svg 8 | 9 | _build: Makefile *.rst devguide/*.rst guide/*/*.rst guide/*.rst conf.py images/*.png $(DIA_SVGS) ../README.rst ../NEWS 10 | python3 -m sphinx -b html . _build 11 | 12 | linkcheck: 13 | python3 -m sphinx -b linkcheck -n . _build 14 | 15 | clean: 16 | rm -R _build 17 | -------------------------------------------------------------------------------- /docs/bugs_repo.rst: -------------------------------------------------------------------------------- 1 | ========================== 2 | Bug Tracker / Git / Source 3 | ========================== 4 | 5 | .. include:: icons.rst 6 | 7 | |bug-logo| Bug Tracker 8 | ---------------------- 9 | 10 | We use the GNOME GitLab issue tracker: 11 | 12 | * List of existing issues: https://gitlab.gnome.org/GNOME/pygobject/-/issues 13 | * Create a new issue: https://gitlab.gnome.org/GNOME/pygobject/-/issues/new 14 | 15 | 16 | |git-logo| Git Repo 17 | ------------------- 18 | 19 | PyGObject uses `Git `_ for source control and the git 20 | repo is hosted on the `GNOME Gitlab instance `__: 21 | 22 | * https://gitlab.gnome.org/GNOME/pygobject 23 | * ``git clone https://gitlab.gnome.org/GNOME/pygobject.git`` 24 | 25 | 26 | |source-logo| Source Tarballs 27 | ----------------------------- 28 | 29 | Release tarballs of all releases can be found on the GNOME server: 30 | 31 | https://ftp.gnome.org/pub/GNOME/sources/pygobject 32 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | Versions with an odd minor version are unstable releases (e.g. 3.27.x) while 5 | versions with even minor version are stable releases (e.g. 3.28.x). This list 6 | is sorted by release date. 7 | 8 | For more details see the Git log: 9 | https://gitlab.gnome.org/GNOME/pygobject/-/commits/main 10 | 11 | .. include:: ../NEWS 12 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | extensions = [ 2 | 'sphinx.ext.todo', 3 | 'sphinx.ext.intersphinx', 4 | 'sphinx.ext.extlinks', 5 | 'sphinx_copybutton', 6 | ] 7 | 8 | intersphinx_mapping = { 9 | 'python': ('https://docs.python.org/3', None), 10 | 'cairo': ('https://pycairo.readthedocs.io/en/latest', None), 11 | 'apidocs': ( 12 | 'https://api.pygobject.gnome.org/', 13 | None, 14 | ), 15 | } 16 | 17 | source_suffix = {'.rst': 'restructuredtext'} 18 | master_doc = 'index' 19 | exclude_patterns = ['_build', 'README.rst'] 20 | 21 | pygments_style = 'tango' 22 | html_theme = "pydata_sphinx_theme" 23 | html_show_copyright = False 24 | html_favicon = "images/favicon.ico" 25 | project = "PyGObject" 26 | html_title = project 27 | 28 | html_context = { 29 | 'extra_css_files': [ 30 | 'https://quodlibet.github.io/fonts/font-mfizz.css', 31 | '_static/extra.css', 32 | ], 33 | "display_gitlab": True, 34 | "gitlab_user": "GNOME", 35 | "gitlab_repo": "pygobject", 36 | "gitlab_version": "main", 37 | "conf_py_path": "/docs/", 38 | "gitlab_host": "gitlab.gnome.org", 39 | } 40 | 41 | html_static_path = [ 42 | "extra.css", 43 | "images/pygobject-small.svg", 44 | ] 45 | 46 | extlinks = { 47 | 'bzbug': ('https://bugzilla.gnome.org/show_bug.cgi?id=%s', 'bz#%s'), 48 | 'issue': ('https://gitlab.gnome.org/GNOME/pygobject/-/issues/%s', '#%s'), 49 | 'commit': ('https://gitlab.gnome.org/GNOME/pygobject/commit/%s', '%s'), 50 | 'mr': ( 51 | 'https://gitlab.gnome.org/GNOME/pygobject/-/merge_requests/%s', '!%s'), 52 | 'user': ('https://gitlab.gnome.org/%s', '%s'), 53 | 'devdocs': ('https://developer.gnome.org/documentation/%s.html', None) 54 | } 55 | 56 | suppress_warnings = ["image.nonlocal_uri"] 57 | -------------------------------------------------------------------------------- /docs/contact.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Contact 3 | ======= 4 | 5 | Issue Tracker 6 | If you want to file a bug report please file an issue on `GitLab 7 | `__. 8 | 9 | Chat 10 | For chatting with the community we are on the GNOME [matrix] instance in 11 | the `GNOME Python channel `__. 12 | Historical logs for this channel and for the legacy IRC channel are 13 | available at https://quodlibet.duckdns.org/irc/pygobject. 14 | 15 | Forum 16 | If you are running in to an issue or want to give feedback, start a 17 | discussion with the Python GNOME community by using the `Python` tag at the 18 | GNOME Discourse at https://discourse.gnome.org/tag/python. 19 | 20 | StackOverflow / StackExchange 21 | If you have technical questions about PyGObject you can find answers on 22 | `Stack Overflow `__. 23 | When asking there please use the tag `PyGObject`. 24 | 25 | If you are unsure which communication channel to use, **please start with 26 | discourse**. 27 | -------------------------------------------------------------------------------- /docs/devguide/index.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | Development Guide 3 | ================= 4 | 5 | .. toctree:: 6 | :titlesonly: 7 | :maxdepth: 1 8 | 9 | overview 10 | dev_environ 11 | style_guide 12 | override_guidelines 13 | 14 | maintguide 15 | packagingguide -------------------------------------------------------------------------------- /docs/devguide/maintguide.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | Maintainer Guide 3 | ================ 4 | 5 | Making a Release 6 | ---------------- 7 | 8 | #. Make sure the `meson.build` file contains the right version number 9 | #. Update the NEWS file 10 | #. Build new version using ``python3 -m build --sdist`` 11 | #. Commit NEWS as ``"release 3.X.Y"`` and push 12 | #. Tag with: ``git tag -s 3.X.Y -m "release 3.X.Y"`` 13 | #. Push tag with: ``git push origin 3.X.Y`` 14 | #. In case of a stable release, upload to PyPI: 15 | ``twine upload dist/pygobject-3.X.Y.tar.gz`` 16 | #. Commit post-release version bump to pyproject.toml 17 | #. In case the release happens on a stable branch copy the NEWS changes to 18 | the main branch 19 | 20 | 21 | Branching 22 | --------- 23 | 24 | Each cycle after the feature freeze, we create a stable branch so development 25 | can continue in the main branch unaffected by the freezes. 26 | 27 | #. Create the branch locally with: ``git checkout -b pygobject-3-2`` 28 | #. Push new branch: ``git push origin pygobject-3-2`` 29 | #. In main, update pyproject.toml to what will be the next version number 30 | (3.3.0) 31 | -------------------------------------------------------------------------------- /docs/devguide/overview.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | Overview 3 | ======== 4 | 5 | 6 | See :doc:`/bugs_repo` for information on where to find the bug tracker and the 7 | source code. 8 | 9 | Continuous Testing 10 | ------------------ 11 | 12 | The test suite gets regularly run on all supported platforms. 13 | You can find the build pipelines in the [source code repository](https://gitlab.gnome.org/GNOME/pygobject). -------------------------------------------------------------------------------- /docs/devguide/packagingguide.rst: -------------------------------------------------------------------------------- 1 | Packaging Guide 2 | =============== 3 | 4 | PyGObject uses Meson, here are some notes on how to package PyGObject. 5 | 6 | Source packages can be found at 7 | https://download.gnome.org/sources/pygobject 8 | 9 | Existing Packages: 10 | 11 | * https://archlinux.org/packages/extra/x86_64/python-gobject 12 | * https://tracker.debian.org/pkg/pygobject 13 | * https://github.com/MSYS2/MINGW-packages/tree/master/mingw-w64-pygobject 14 | 15 | Building:: 16 | 17 | meson setup --prefix /usr --buildtype=plain _build -Dc_args=... -Dc_link_args=... 18 | meson compile -C _build 19 | meson test -C _build 20 | DESTDIR=/path/to/staging/root meson install -C _build 21 | 22 | Runtime dependencies: 23 | 24 | * glib 25 | * libgirepository-2.0 (shipped with GLib ≥ 2.80) 26 | * libffi 27 | * Python 3 28 | 29 | The overrides directory contains various files which includes various 30 | Python imports mentioning gtk, gdk etc. They are only used when the 31 | corresponding library is present, they are not direct dependencies. 32 | 33 | Build dependencies: 34 | 35 | * The runtime dependencies 36 | * cairo (optional) 37 | * pycairo (optional) 38 | * pkg-config 39 | * setuptools (optional) 40 | 41 | Test Suite dependencies: 42 | 43 | * The runtime dependencies 44 | * GTK 4 (optional) 45 | * pango (optional) 46 | * pycairo (optional) 47 | -------------------------------------------------------------------------------- /docs/extra.css: -------------------------------------------------------------------------------- 1 | .wy-side-nav-search { 2 | background-color: initial; 3 | } 4 | 5 | .wy-nav-top { 6 | background-color: #171A2F; 7 | } 8 | 9 | .wy-side-nav-search input[type="text"] { 10 | border-color: transparent; 11 | } 12 | 13 | .wy-nav-content { 14 | margin: initial; 15 | } 16 | 17 | .wy-nav-side { 18 | background-color: #171A2F; 19 | } 20 | 21 | .rst-content div[role=navigation], footer { 22 | font-size: 0.85em; 23 | color: #999; 24 | } 25 | 26 | .rst-content div[role=navigation] hr { 27 | margin-top: 6px; 28 | } 29 | 30 | footer hr { 31 | margin-bottom: 6px; 32 | } 33 | 34 | .rst-footer-buttons { 35 | display: none; 36 | } 37 | 38 | a.icon-home, a.icon-home:hover { 39 | display: inline-block; 40 | padding: 4px 4px 4px 21px; 41 | background: transparent url(pygobject-small.svg) center left no-repeat; 42 | background-size: 1.2em; 43 | margin-top: 0.2em; 44 | margin-bottom: 1em; 45 | } 46 | 47 | 48 | .fa-home::before, .icon-home::before { 49 | content: ""; 50 | } 51 | 52 | .wy-nav-top a { 53 | margin: -2em; 54 | background: transparent url(pygobject-small.svg) center left no-repeat; 55 | background-size: 1.2em; 56 | padding: 4px 4px 4px 24px; 57 | } 58 | -------------------------------------------------------------------------------- /docs/guide/api/api.rst: -------------------------------------------------------------------------------- 1 | .. _guide-api: 2 | 3 | ================ 4 | GI Documentation 5 | ================ 6 | 7 | This is the API provided by the toplevel "gi" package. 8 | 9 | 10 | .. function:: gi.require_version(namespace, version) 11 | 12 | :param str namespace: The namespace 13 | :param str version: The version of the namespace which should be loaded 14 | :raises: ..py:exception:: ValueError 15 | 16 | Ensures the namespace gets loaded with the given version. If the namespace 17 | was already loaded with a different version or a different version was 18 | required previously raises ValueError. 19 | 20 | :: 21 | 22 | import gi 23 | gi.require_version('Gtk', '3.0') 24 | 25 | 26 | .. function:: gi.require_foreign(namespace, symbol=None) 27 | 28 | :param str namespace: 29 | Introspection namespace of the foreign module (e.g. "cairo") 30 | :param symbol: 31 | Optional symbol typename to ensure a converter exists. 32 | :type symbol: :obj:`str` or :obj:`None` 33 | :raises: ..py:exception:: ImportError 34 | 35 | Ensure the given foreign marshaling module is available and loaded. 36 | 37 | Example: 38 | 39 | .. code-block:: python 40 | 41 | import gi 42 | import cairo 43 | gi.require_foreign('cairo') 44 | gi.require_foreign('cairo', 'Surface') 45 | 46 | 47 | .. function:: gi.check_version(version) 48 | 49 | :param tuple version: A version tuple 50 | :raises: ..py:exception:: ValueError 51 | 52 | Compares the passed in version tuple with the gi version and does nothing 53 | if gi version is the same or newer. Otherwise raises ValueError. 54 | 55 | 56 | .. function:: gi.get_required_version(namespace) 57 | 58 | :returns: The version successfully required previously by :func:`gi.require_version` or :obj:`None` 59 | :rtype: str or :obj:`None` 60 | 61 | 62 | .. data:: gi.version_info 63 | :annotation: = (3, 18, 1) 64 | 65 | The version of PyGObject 66 | 67 | 68 | .. class:: gi.PyGIDeprecationWarning 69 | 70 | The warning class used for deprecations in PyGObject and the included 71 | Python overrides. It inherits from DeprecationWarning and is hidden 72 | by default. 73 | 74 | 75 | .. class:: gi.PyGIWarning 76 | 77 | Like :class:`gi.PyGIDeprecationWarning` but visible by default. 78 | -------------------------------------------------------------------------------- /docs/guide/api/basic_types.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | Basic Types 3 | =========== 4 | 5 | PyGObject will automatically convert between C types and Python types. In 6 | cases where it's appropriate it will use default Python types like :obj:`int`, 7 | :obj:`list`, and :obj:`dict`. 8 | 9 | 10 | Number Types 11 | ------------ 12 | 13 | All glib integer types get mapped to :obj:`int` and :obj:`float`. 14 | Since the glib integer types are always range limited, conversions from Python 15 | int/long can fail with :class:`OverflowError`: 16 | 17 | .. code:: pycon 18 | 19 | >>> GLib.random_int_range(0, 2**31-1) 20 | 1684142898 21 | >>> GLib.random_int_range(0, 2**31) 22 | Traceback (most recent call last): 23 | File "", line 1, in 24 | OverflowError: 2147483648 not in range -2147483648 to 2147483647 25 | >>> 26 | 27 | 28 | Text Types 29 | ---------- 30 | 31 | Text types are mapped to :obj:`str`. 32 | 33 | 34 | Other Types 35 | ----------- 36 | 37 | * GList <-> :obj:`list` 38 | * GSList <-> :obj:`list` 39 | * GHashTable <-> :obj:`dict` 40 | * arrays <-> :obj:`list` 41 | -------------------------------------------------------------------------------- /docs/guide/api/error_handling.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | ============== 4 | Error Handling 5 | ============== 6 | 7 | GLib has its own method of handling errors using :obj:`GLib.Error`. These are 8 | raised as Python exceptions, but with a few small differences. 9 | 10 | It's common in Python for exception subclasses to be used (e.g., 11 | :obj:`ValueError` versus :obj:`IOError`) to distinguish different types of 12 | errors. Libraries often define their own :obj:`Exception` subclasses, and 13 | library users will handle these cases explicitly. 14 | 15 | In GLib-using libraries, errors are all :obj:`GLib.Error` instances, with no 16 | subclassing for different error types. Instead, every :obj:`GLib.Error` 17 | instance has attributes that distinguish types of error: 18 | 19 | * :attr:`GLib.Error.domain` is the error domain, usually a string that you can 20 | convert to a ``GLib`` quark with :func:`GLib.quark_from_string` 21 | * :attr:`GLib.Error.code` identifies a specific error within the domain 22 | * :attr:`GLib.Error.message` is a human-readable description of the error 23 | 24 | Error domains are defined per-module, and you can get an error domain from 25 | ``*_error_quark`` functions on the relevant module. For example, IO errors 26 | from ``Gio`` are in the domain returned by :func:`Gio.io_error_quark`, and 27 | possible error code values are enumerated in :obj:`Gio.IOErrorEnum`. 28 | 29 | Once you've caught a :obj:`GLib.Error`, you can call 30 | :meth:`GLib.Error.matches` to see whether it matches the specific error you 31 | want to handle. 32 | 33 | 34 | Examples 35 | -------- 36 | 37 | Catching a specific error: 38 | 39 | .. code:: pycon 40 | 41 | >>> from gi.repository import GLib, Gio 42 | >>> f = Gio.File.new_for_path('missing-path') 43 | >>> try: 44 | ... f.read() 45 | ... except GLib.Error as err: 46 | ... if err.matches(Gio.io_error_quark(), Gio.IOErrorEnum.NOT_FOUND): 47 | ... print('File not found') 48 | ... else: 49 | ... raise 50 | File not found 51 | -------------------------------------------------------------------------------- /docs/guide/api/flags_enums.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | ============= 4 | Flags & Enums 5 | ============= 6 | 7 | Flags are subclasses of :class:`GObject.GFlags`, which in turn is a 8 | subclass of the standard library :class:`enum.IntFlag`. They represent 9 | bit fields where some bits also have names: 10 | 11 | .. code:: pycon 12 | 13 | >>> Gtk.DialogFlags.MODAL 14 | 15 | >>> Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT 16 | 17 | >>> int(_) 18 | 3 19 | >>> Gtk.DialogFlags(3) 20 | 21 | >>> isinstance(Gtk.DialogFlags.MODAL, Gtk.DialogFlags) 22 | True 23 | >>> 24 | 25 | Bitwise operations on them will produce a value of the same type. 26 | 27 | 28 | Enums are subclasses of :class:`GObject.GEnum`, which in turn is a 29 | subclass of the standard library :class:`enum.IntEnum`. They represent 30 | a list of named constants: 31 | 32 | .. code:: pycon 33 | 34 | >>> Gtk.Align.CENTER 35 | 36 | >>> int(Gtk.Align.CENTER) 37 | 3 38 | >>> int(Gtk.Align.END) 39 | 2 40 | >>> Gtk.Align(1) 41 | 42 | >>> isinstance(Gtk.Align.CENTER, Gtk.Align) 43 | True 44 | 45 | Creating New Enums and Flags 46 | ---------------------------- 47 | 48 | New enumerations and flags types can be defined by subclassing 49 | :class:`GObject.GEnum` or :class:`GObject.GFlags` in the same way as 50 | standard library enumerations. A new GType is registered 51 | automatically. 52 | 53 | .. code:: pycon 54 | 55 | >>> from gi.repository import GObject 56 | >>> class E(GObject.GEnum): 57 | ... ONE = 1 58 | ... TWO = 2 59 | ... 60 | >>> E.ONE 61 | 62 | >>> E.ONE.value_name 63 | 'ONE' 64 | >>> E.ONE.value_nick 65 | 'one' 66 | >>> E.__gtype__ 67 | 68 | >>> E.__gtype__.name 69 | '__main__+E' 70 | 71 | The GType name can be set explicitly by providing a ``__gtype_name__`` 72 | attribute: 73 | 74 | .. code:: pycon 75 | 76 | >>> from gi.repository import GObject 77 | >>> class MyEnum(GObject.GEnum): 78 | ... __gtype_name__ = "MyEnum" 79 | ... ONE = 1 80 | ... 81 | >>> MyEnum.__gtype__ 82 | 83 | -------------------------------------------------------------------------------- /docs/guide/api/gobject.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | ============== 4 | GObject.Object 5 | ============== 6 | 7 | Compare to other types, :obj:`GObject.Object` has the best integration between 8 | the GObject and Python type system. 9 | 10 | 1) It is possible to subclass a :obj:`GObject.Object`. Subclassing 11 | creates a new :obj:`GObject.GType` which is connected to the new Python 12 | type. This means you can use it with API which takes :obj:`GObject.GType`. 13 | 2) The Python wrapper instance for a :obj:`GObject.Object` is always the same. 14 | For the same C instance you will always get the same Python instance. 15 | 16 | 17 | In addition :obj:`GObject.Object` has support for :any:`signals ` and 18 | :any:`properties ` 19 | 20 | .. toctree:: 21 | :titlesonly: 22 | :maxdepth: 1 23 | :hidden: 24 | 25 | signals 26 | properties 27 | weakrefs 28 | 29 | 30 | Examples 31 | -------- 32 | 33 | Subclassing: 34 | 35 | .. code:: pycon 36 | 37 | >>> from gi.repository import GObject 38 | >>> class A(GObject.Object): 39 | ... pass 40 | ... 41 | >>> A() 42 | <__main__.A object at 0x7f9113fc3280 (__main__+A at 0x559d9861acc0)> 43 | >>> A.__gtype__ 44 | 45 | >>> A.__gtype__.name 46 | '__main__+A' 47 | >>> 48 | 49 | In case you want to specify the GType name we have to provide a 50 | ``__gtype_name__``: 51 | 52 | .. code:: pycon 53 | 54 | >>> from gi.repository import GObject 55 | >>> class B(GObject.Object): 56 | ... __gtype_name__ = "MyName" 57 | ... 58 | >>> B.__gtype__ 59 | 60 | >>> 61 | 62 | :obj:`GObject.Object` only supports single inheritance, this means you can 63 | only subclass one :obj:`GObject.Object`, but multiple Python classes: 64 | 65 | .. code:: pycon 66 | 67 | >>> from gi.repository import GObject 68 | >>> class MixinA(object): 69 | ... pass 70 | ... 71 | >>> class MixinB(object): 72 | ... pass 73 | ... 74 | >>> class MyClass(GObject.Object, MixinA, MixinB): 75 | ... pass 76 | ... 77 | >>> instance = MyClass() 78 | 79 | 80 | Here we can see how we create a :obj:`Gio.ListStore` for our new subclass and 81 | that we get back the same Python instance we put into it: 82 | 83 | .. code:: pycon 84 | 85 | >>> from gi.repository import GObject, Gio 86 | >>> class A(GObject.Object): 87 | ... pass 88 | ... 89 | >>> store = Gio.ListStore.new(A) 90 | >>> instance = A() 91 | >>> store.append(instance) 92 | >>> store.get_item(0) is instance 93 | True 94 | >>> 95 | -------------------------------------------------------------------------------- /docs/guide/api/index.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | API Reference 3 | ============= 4 | 5 | .. toctree:: 6 | :titlesonly: 7 | :maxdepth: 1 8 | 9 | api 10 | basic_types 11 | flags_enums 12 | gobject 13 | error_handling 14 | -------------------------------------------------------------------------------- /docs/guide/api/weakrefs.rst: -------------------------------------------------------------------------------- 1 | Weak References 2 | =============== 3 | 4 | While Python has a builtin ``weakref`` module it only allows one to create 5 | weak references to Python objects, but with PyGObject the Python object 6 | "wrapping" a GObject and the GObject itself might not have the same lifetime. 7 | The wrapper can get garbage collected and a new wrapper created again at a 8 | later point. 9 | 10 | If you want to get notified when the underlying GObject gets finalized use 11 | :meth:`GObject.Object.weak_ref`: 12 | 13 | 14 | .. method:: GObject.Object.weak_ref(callback, *user_data) 15 | 16 | Registers a callback to be called when the underlying GObject gets 17 | finalized. The callback will receive the give `user_data`. 18 | 19 | To unregister the callback call the ``unref()`` method of the returned 20 | GObjectWeakRef object. 21 | 22 | :param callback: A callback which will be called when the object 23 | is finalized 24 | :type callback: :func:`callable` 25 | :param user_data: User data that will be passed to the callback 26 | :returns: GObjectWeakRef 27 | -------------------------------------------------------------------------------- /docs/guide/cairo_integration.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | Cairo Integration 3 | ================= 4 | 5 | Despite `cairo `__ not being a GObject based 6 | library, PyGObject provides special cairo integration through `pycairo 7 | `__. Functions returning and taking cairo data 8 | types get automatically converted to pycairo objects and vice versa. 9 | 10 | Some distros ship the PyGObject cairo support in a separate package. If you've 11 | followed the instructions on ":ref:`gettingstarted`" you should have everything 12 | installed. 13 | 14 | If your application requires the cairo integration you can use 15 | :func:`gi.require_foreign`: 16 | 17 | .. code:: python 18 | 19 | try: 20 | gi.require_foreign("cairo") 21 | except ImportError: 22 | print("No pycairo integration :(") 23 | 24 | Note that PyGObject currently does not support `cairocffi 25 | `__, only pycairo. 26 | 27 | 28 | Demo 29 | ---- 30 | 31 | The following example shows a :obj:`Gtk.Window` with a custom drawing in Python 32 | using pycairo. 33 | 34 | .. figure:: images/cairo_integration.png 35 | :scale: 75% 36 | :align: center 37 | 38 | .. literalinclude:: code/cairo-demo.py 39 | :linenos: 40 | -------------------------------------------------------------------------------- /docs/guide/faq.rst: -------------------------------------------------------------------------------- 1 | ========================== 2 | Frequently Asked Questions 3 | ========================== 4 | 5 | How can I use PyGObject with the official CPython builds on Windows? 6 | -------------------------------------------------------------------- 7 | 8 | https://sourceforge.net/projects/pygobjectwin32 provides binaries which should 9 | be ABI compatible with the official CPython binaries. I'd recommend using 10 | msys2 if at all possible, since there are more people involved and it's easier 11 | to fix/patch things yourself. 12 | -------------------------------------------------------------------------------- /docs/guide/flatpaking.rst: -------------------------------------------------------------------------------- 1 | Flatpaking 2 | ========== 3 | 4 | `Flatpak `_ is perfect for packaging applications for Linux. 5 | 6 | Flatpak comes with 7 | `great documentation `_ and a 8 | specific guide about using it to package Python applications can be found 9 | `here `_. 10 | -------------------------------------------------------------------------------- /docs/guide/images/cairo_integration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/guide/images/cairo_integration.png -------------------------------------------------------------------------------- /docs/guide/imports.rst: -------------------------------------------------------------------------------- 1 | Imports 2 | ======= 3 | 4 | The toplevel ``gi`` package allows you to import the different libraries 5 | namespaces and ensure specific versions of them. 6 | 7 | The next code line will import the ``GTK`` and ``GLib`` libraries from the 8 | ``gi.repository`` module. ``gi.repository`` holds the libraries bindings. 9 | 10 | .. code:: python 11 | 12 | from gi.repository import Gtk, GLib 13 | 14 | 15 | If you want to ensure a specific version of a library you can use :func:`gi.require_version`. 16 | 17 | .. code:: python 18 | 19 | import gi 20 | gi.require_version('Gtk', '4.0') 21 | gi.require_version('GLib', '2.0') 22 | from gi.repository import Gtk, GLib 23 | 24 | 25 | Currently, when importing ``Gdk`` or ``Gtk``, their init functions 26 | (``Gdk.init_check()`` and ``Gtk.init_check()`` respectively) will be 27 | automatically called for backwards-compatibility reasons. 28 | This prevents, among other things, to use ``Gtk.disable_setlocale()``, as 29 | it shall be called before ``Gtk`` initialization. 30 | 31 | This behavior may be dropped in the future, but in the meanwhile you can 32 | use :func:`gi.disable_legacy_autoinit` before the import to skip the 33 | auto-init. 34 | 35 | .. code:: python 36 | 37 | import gi 38 | gi.disable_legacy_autoinit() 39 | from gi.repository import Gtk 40 | 41 | 42 | To avoid `PEP8/E402 `_ you can 43 | use a try block. 44 | 45 | .. code:: python 46 | 47 | import sys 48 | 49 | import gi 50 | try: 51 | gi.require_version('Gtk', '4.0') 52 | gi.require_version('Adw', '1') 53 | from gi.repository import Adw, Gtk 54 | except ImportError or ValueError as exc: 55 | print('Error: Dependencies not met.', exc) 56 | sys.exit(1) 57 | 58 | 59 | .. seealso:: 60 | For more detailed information of the methods provided by the ``gi`` module 61 | checkout :ref:`guide-api`. 62 | -------------------------------------------------------------------------------- /docs/guide/index.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | User Guide 3 | ========== 4 | 5 | 6 | .. toctree:: 7 | :titlesonly: 8 | :maxdepth: 1 9 | 10 | imports 11 | api/index 12 | cairo_integration 13 | gtk_template 14 | asynchronous 15 | threading 16 | debug_profile 17 | deploy 18 | testing 19 | porting 20 | sysdeps 21 | flatpaking 22 | faq 23 | -------------------------------------------------------------------------------- /docs/guide/sysdeps.rst: -------------------------------------------------------------------------------- 1 | System Dependencies 2 | =================== 3 | 4 | PyGObject not only depends on packages available from PyPI, but also requires 5 | certain system dependencies to be installed. Because their version isn't taken 6 | into account by pip's dependency resolver, you may need to restrict the version 7 | of PyGObject itself for the installation to succeed. This lists the minimum 8 | version of the system dependencies over time. 9 | 10 | 3.50.0+: 11 | * glib: >= 2.80.0 12 | * libffi: >= 3.0 13 | * gobject-introspection: >= 1.64.0 (for tests only) 14 | 15 | 3.46.0+: 16 | * glib: >= 2.64.0 17 | * gobject-introspection: >= 1.64.0 18 | * libffi: >= 3.0 19 | 20 | Example distributions: Ubuntu 20.04, Debian Bullseye, or newer 21 | 22 | 3.40.0 - 3.44.x: 23 | * glib: >= 2.56.0 24 | * gobject-introspection: >= 1.56.0 25 | * libffi: >= 3.0 26 | 27 | Example distributions: Ubuntu 18.04, or newer 28 | -------------------------------------------------------------------------------- /docs/guide/testing.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../icons.rst 2 | 3 | ================================== 4 | Testing and Continuous Integration 5 | ================================== 6 | 7 | To get automated tests of GTK code running on a headless server use Mutter. It allows running your app on Wayland 8 | display server without real display hardware. 9 | 10 | :: 11 | 12 | export XDG_RUNTIME_DIR=/tmp 13 | eval $(dbus-launch --auto-syntax) 14 | mutter --wayland --no-x11 --sm-disable --headless -- python my_script.py 15 | -------------------------------------------------------------------------------- /docs/icons.rst: -------------------------------------------------------------------------------- 1 | .. |python-logo| raw:: html 2 | 3 | 4 | 5 | 6 | .. |ubuntu-logo| raw:: html 7 | 8 | 9 | 10 | .. |debian-logo| raw:: html 11 | 12 | 13 | 14 | .. |fedora-logo| raw:: html 15 | 16 | 17 | 18 | .. |opensuse-logo| raw:: html 19 | 20 | 21 | 22 | .. |windows-logo| raw:: html 23 | 24 | 25 | 26 | .. |source-logo| raw:: html 27 | 28 | 29 | 30 | .. |arch-logo| raw:: html 31 | 32 | 33 | 34 | .. |macosx-logo| raw:: html 35 | 36 | 37 | 38 | .. |github-logo| raw:: html 39 | 40 | 41 | 42 | .. |git-logo| raw:: html 43 | 44 | 45 | 46 | .. |bug-logo| raw:: html 47 | 48 | 49 | 50 | .. |linux-logo| raw:: html 51 | 52 | 53 | -------------------------------------------------------------------------------- /docs/images/LICENSE: -------------------------------------------------------------------------------- 1 | pygobject.svg and pygobject-small.svg are based on the GTK logo, created by 2 | Andreas Nilsson, licensed under CC BY-SA 3.0. For more info see 3 | https://commons.wikimedia.org/wiki/File:GTK%2B_logo.svg 4 | -------------------------------------------------------------------------------- /docs/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/images/favicon.ico -------------------------------------------------------------------------------- /docs/images/overview.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/images/overview.dia -------------------------------------------------------------------------------- /docs/images/start_linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/images/start_linux.png -------------------------------------------------------------------------------- /docs/images/start_macos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/images/start_macos.png -------------------------------------------------------------------------------- /docs/images/start_windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/images/start_windows.png -------------------------------------------------------------------------------- /docs/tutorials/_static/custom.css: -------------------------------------------------------------------------------- 1 | .toctree-wrapper .reference.external::after { 2 | content: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' stroke-width='1.5' stroke='white' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M0 0h24v24H0z' stroke='none'/%3E%3Cpath d='M11 7H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-5M10 14 20 4M15 4h5v5'/%3E%3C/svg%3E"); 3 | margin: 0 .25rem; 4 | vertical-align: middle; 5 | } 6 | -------------------------------------------------------------------------------- /docs/tutorials/gobject.rst: -------------------------------------------------------------------------------- 1 | GObject 2 | ======= 3 | 4 | GObject is the foundation for object-oriented programming in the GNOME 5 | libraries. 6 | For example :class:`GObject.Object` is the base providing the common attributes 7 | and methods for all object types in GTK and the other libraries in this guide. 8 | 9 | The :class:`GObject.Object` class provides methods for object construction and 10 | destruction, property access methods, and signal support. 11 | 12 | This chapter will introduce some important aspects about the GObject 13 | implementation in Python. 14 | 15 | .. toctree:: 16 | :maxdepth: 3 17 | :caption: Contents 18 | 19 | gobject/basics 20 | gobject/subclassing 21 | gobject/interfaces 22 | Weak References 23 | -------------------------------------------------------------------------------- /docs/tutorials/gobject/examples/listmodel.py: -------------------------------------------------------------------------------- 1 | from gi.repository import Gio, GObject 2 | 3 | 4 | class Person(GObject.Object): 5 | __gtype_name__ = 'Person' 6 | 7 | name = GObject.Property(type=str) 8 | 9 | def __init__(self, name): 10 | super().__init__() 11 | 12 | self.name = name 13 | 14 | 15 | class PersonsModel(GObject.GObject, Gio.ListModel): 16 | __gtype_name__ = 'PersonsModel' 17 | 18 | def __init__(self): 19 | super().__init__() 20 | 21 | # Private list to store the persons 22 | self._persons = [] 23 | 24 | ''' 25 | Interface Methods 26 | ''' 27 | 28 | def do_get_item(self, position): 29 | return self._persons[position] 30 | 31 | def do_get_item_type(self): 32 | return Person 33 | 34 | def do_get_n_items(self): 35 | return len(self._persons) 36 | 37 | ''' 38 | Our Helper Methods 39 | ''' 40 | 41 | def add(self, person): 42 | self._persons.append(person) 43 | 44 | ''' 45 | We must call Gio.ListModel.items_changed() every time we change the list. 46 | 47 | It's a helper to emit the "items-changed" signal, so consumer can know 48 | that the list changed at some point. We pass the position of the change, 49 | the number of removed items and the number of added items. 50 | ''' 51 | self.items_changed(len(self._persons) - 1, 0, 1) 52 | 53 | def remove(self, position): 54 | del self._persons[position] 55 | self.items_changed(position, 1, 0) 56 | 57 | def get_index_by_name(self, name): 58 | for i, person in enumerate(self._persons): 59 | if person.name == name: 60 | return i 61 | 62 | return None 63 | -------------------------------------------------------------------------------- /docs/tutorials/gobject/interfaces.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | Interfaces 4 | ========== 5 | GObject interfaces are a way of ensuring that objects passed to C code have the 6 | right capabilities. 7 | 8 | When a GObject implements an interface it should implement an expected set of 9 | methods, properties and signals. In the Python sense, an interface is another 10 | class that is inherited. 11 | 12 | For example in GTK, :class:`Gtk.Image` supports various sources for the image 13 | that it will display. 14 | Some of these sources can be a :class:`Gio.Icon` or a :class:`Gdk.Paintable`, 15 | both are actually interfaces so you don't pass a direct instance of these, 16 | instead you should use some of the gobjects that implement the interface. 17 | For :class:`Gio.Icon` those can be :class:`Gio.ThemedIcon` that represents an 18 | icon from the icon theme, or :class:`Gio.FileIcon` that represents an icon 19 | created from an image file. 20 | 21 | Another important interface of reference is :class:`Gio.ListModel`. 22 | It represents a mutable list of :class:`GObject.Objects `. 23 | If you want to implement :class:`Gio.ListModel` you must implement three methods, 24 | these are :meth:`Gio.ListModel.get_item_type`, :meth:`Gio.ListModel.get_n_items` 25 | and :meth:`Gio.ListModel.get_item`. 26 | The interfaces methods that you should implement are exposed as 27 | :ref:`virtual methods `. 28 | With these methods any consumer can iterate the list and use the objects for any 29 | purpose. 30 | 31 | .. tip:: 32 | A generic implementation of :class:`Gio.ListModel` is :class:`Gio.ListStore`. 33 | It allows you to set the :class:`GObject.Object` type that it will store and 34 | provides methods to append, insert, sort, find and remove gobjects. 35 | 36 | Example 37 | ------- 38 | 39 | In this examples we'll be implementing a :class:`Gio.ListModel` in Python. 40 | It will store a custom :class:`GObject.Object` and provide some helper methods 41 | for it. 42 | 43 | .. literalinclude:: examples/listmodel.py 44 | :linenos: 45 | -------------------------------------------------------------------------------- /docs/tutorials/gtk3.rst: -------------------------------------------------------------------------------- 1 | GTK3 2 | ==== 3 | 4 | You can find help about using Python with GTK3 in the following resources. 5 | 6 | * `The Python GTK+ 3 Tutorial `_ 7 | 8 | * `PyGObject API Reference `_ 9 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4.rst: -------------------------------------------------------------------------------- 1 | GTK4 2 | ==== 3 | 4 | GTK is a library for creating graphical user interfaces. 5 | The main objects of GTK are "widgets" which are components such as buttons, text 6 | input, or windows. 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | :caption: Contents 11 | 12 | gtk4/introduction 13 | gtk4/basics 14 | gtk4/application 15 | gtk4/layout-widgets 16 | gtk4/controls 17 | gtk4/display-widgets 18 | gtk4/popovers 19 | gtk4/textview 20 | gtk4/clipboard 21 | gtk4/drag-and-drop 22 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/basics.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | GTK4 Basics 4 | =========== 5 | 6 | Main loop and Signals 7 | --------------------- 8 | Like most GUI toolkits, GTK uses an event-driven programming model. 9 | When the user is doing nothing, GTK+ sits in the main loop and waits for input. 10 | If the user performs some action - say, a mouse click - then the main loop 11 | "wakes up" and delivers an event to GTK. 12 | 13 | When widgets receive an event, they frequently emit one or more signals. 14 | Signals notify your program that "something interesting happened" by invoking 15 | functions you've connected to the signal. Such functions are commonly known 16 | as *callbacks*. 17 | When your callbacks are invoked, you would typically take some action - for 18 | example, when an Open button is clicked you might display a file chooser 19 | dialog. After a callback finishes, GTK will return to the main loop and await 20 | more user input. 21 | 22 | :class:`Gtk.Application` will run the main loop for you, so you don't need to 23 | worry about it. 24 | 25 | A :class:`Gtk.Widget` it's also a :class:`GObject.Object`, so to know how to 26 | interact with these signals you must read the 27 | :ref:`GObject Basics `. 28 | 29 | .. seealso:: `Library initialization and main loop`_ in GTK documentation. 30 | 31 | Properties 32 | ---------- 33 | Read: :ref:`GObject Basics: Properties `. 34 | 35 | 36 | .. _Library initialization and main loop: https://docs.gtk.org/gtk4/initialization.html 37 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/clipboard.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | Clipboard 4 | ========= 5 | 6 | :class:`Gdk.Clipboard` provides a storage area for a variety of data, including 7 | text and images. Using a clipboard allows this data to be shared between 8 | applications through actions such as copying, cutting, and pasting. 9 | 10 | There are multiple clipboard selections for different purposes. 11 | In most circumstances, the selection named ``CLIPBOARD`` is used for everyday 12 | copying and pasting. ``PRIMARY`` is another common selection which stores text 13 | selected by the user with the cursor. 14 | 15 | :class:`Gdk.Display` will allow us to access these different clipboards. 16 | You can get the default display with :meth:`Gdk.Display.get_default`, then get 17 | the clipboard that you want; :meth:`Gdk.Display.get_clipboard` for ``CLIPBOARD`` 18 | and :meth:`Gdk.Display.get_primary_clipboard` for ``PRIMARY``. 19 | 20 | You can set any simple value like text with :meth:`Gdk.Clipboard.set`. 21 | For more complex data you must use the :meth:`Gdk.Clipboard.set_content` method 22 | were you have to pass a :class:`Gdk.ContentProvider`. 23 | A content provider is usually created using 24 | :meth:`Gdk.ContentProvider.new_for_value` where you only pass the value. 25 | 26 | To read the clipboard values :class:`Gdk.Clipboard` provides three async methods. 27 | For textual or image data use :meth:`Gdk.Clipboard.read_text_async` or 28 | :meth:`Gdk.Clipboard.read_texture_async`. 29 | For other data use :meth:`Gdk.Clipboard.read_value_async`. 30 | 31 | 32 | Example 33 | ------- 34 | 35 | .. image:: images/clipboard.png 36 | 37 | .. literalinclude:: examples/clipboard.py 38 | :linenos: 39 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls.rst: -------------------------------------------------------------------------------- 1 | Controls 2 | ======== 3 | 4 | Learn how to use the most basic interactive UI elements from GTK, such as 5 | entries, buttons and switches. 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | :caption: Contents 10 | 11 | controls/entries 12 | controls/buttons 13 | controls/check-radio-buttons 14 | controls/spinbutton 15 | controls/switch 16 | controls/dropdown 17 | controls/scale 18 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/buttons.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | Buttons 4 | ======= 5 | 6 | Button 7 | ------ 8 | The Button widget is another commonly used widget. It is generally used to 9 | attach a function that is called when the button is pressed. 10 | 11 | The :class:`Gtk.Button` widget can hold any valid child widget. That is it can 12 | hold most any other standard :class:`Gtk.Widget`. 13 | The most commonly used child is the :class:`Gtk.Label`. 14 | Normally you will use :attr:`Gtk.Button.props.label` to set the button label, or 15 | :attr:`Gtk.Button.props.icon_name` if you want an icon instead. 16 | 17 | Usually, you want to connect to the button's ``clicked`` signal which is emitted 18 | when the button has been pressed and released. 19 | 20 | Example 21 | ^^^^^^^ 22 | 23 | .. image:: images/button.png 24 | 25 | .. literalinclude:: examples/button.py 26 | :linenos: 27 | 28 | 29 | ToggleButton 30 | ------------ 31 | 32 | A :class:`Gtk.ToggleButton` is very similar to a normal :class:`Gtk.Button`, 33 | but when clicked they remain activated, or pressed, until clicked again. 34 | When the state of the button is changed, the `toggled` signal is emitted. 35 | 36 | To retrieve the state of the :class:`Gtk.ToggleButton`, you can use 37 | :attr:`Gtk.ToggleButton.props.active`. This returns ``True`` if the button 38 | is "down". You can also set the toggle button's state, with 39 | :attr:`Gtk.ToggleButton.props.active`. Note that, if you do this, and the state 40 | actually changes, it causes the "toggled" signal to be emitted. 41 | 42 | Example 43 | ^^^^^^^ 44 | 45 | .. image:: images/togglebutton.png 46 | 47 | .. literalinclude:: examples/togglebutton.py 48 | :linenos: 49 | 50 | 51 | LinkButton 52 | ---------- 53 | A :class:`Gtk.LinkButton` is a :class:`Gtk.Button` with a hyperlink, similar 54 | to the one used by web browsers, which triggers an action when clicked. It is 55 | useful to show quick links to resources. 56 | 57 | The URI bound to a :class:`Gtk.LinkButton` can be set specifically using 58 | :attr:`Gtk.LinkButton.props.uri`. 59 | 60 | Example 61 | ^^^^^^^ 62 | 63 | .. image:: images/linkbutton.png 64 | 65 | .. literalinclude:: examples/linkbutton.py 66 | :linenos: 67 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/check-radio-buttons.rst: -------------------------------------------------------------------------------- 1 | Check & Radio Buttons 2 | ===================== 3 | A :class:`Gtk.CheckButton` places a label next to an indicator. 4 | Check or Radio buttons are created through :class:`Gtk.CheckButton`, you create 5 | one or another depending grouping. 6 | 7 | :class:`Gtk.CheckButton` can be grouped together, to form mutually exclusive 8 | groups so only one of the buttons can be toggled at a time, this create what we 9 | usually refer to as a radio button. 10 | 11 | In addition to "on" and "off", :class:`Gtk.CheckButton` can be an "in between" 12 | state that is neither on nor off. This can be used e.g. when the user has 13 | selected a range of elements (such as some text or spreadsheet cells) that are 14 | affected by a check button, and the current values in that range are 15 | inconsistent. 16 | For this purpose use :attr:`Gtk.CheckButton.props.inconsistent`. 17 | 18 | Example 19 | ------- 20 | 21 | .. image:: images/check_radio_buttons.png 22 | 23 | .. literalinclude:: examples/check_radio_buttons.py 24 | :linenos: 25 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/dropdown.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | DropDown 4 | ======== 5 | :class:`Gtk.DropDown` allows the user to choose an item from a list of options. 6 | They are preferable to having many radio buttons on screen as they take up less 7 | room. 8 | 9 | To populate its options :class:`Gtk.DropDown` uses a :class:`Gio.ListModel`. 10 | :class:`Gio.ListModel` it's an interface that represents a mutable list of 11 | :class:`GObject.Objects `. For text-only uses cases GTK provides 12 | :class:`Gtk.StringList`, a list model that wraps an array of strings wrapped on 13 | :class:`Gtk.StringObject` and :class:`Gtk.DropDown` knows how to use it. 14 | 15 | :class:`Gtk.DropDown` can optionally allow search in the popup, which is useful 16 | if the list of options is long. To enable the search entry, use 17 | :attr:`Gtk.DropDown.props.enable_search`. 18 | 19 | .. attention:: 20 | If you use custom list models with custom gobjects you must provide a 21 | :class:`Gtk.Expression` through :attr:`Gtk.DropDown.props.expression` so 22 | :class:`Gtk.DropDown` can know how to filter the gobjects. 23 | :class:`Gtk.Expression` has been supported in PyGObject since release 3.48. 24 | 25 | :class:`Gtk.DropDown` stores the selected item from the list model in 26 | :attr:`Gtk.DropDown.props.selected_item`, and the position of that item on 27 | :attr:`Gtk.DropDown.props.selected`. To know when the selection has changed just 28 | connect to ``notify::selected-item`` or ``notify::selected``. 29 | 30 | 31 | Example 32 | ^^^^^^^ 33 | 34 | We are creating a simple :class:`Gtk.DropDown` using :class:`Gtk.StringList`. 35 | 36 | .. image:: images/dropdown.png 37 | 38 | .. literalinclude:: examples/dropdown.py 39 | :linenos: 40 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/examples/button.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class ButtonWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='Button Demo') 10 | 11 | hbox = Gtk.Box(spacing=6) 12 | self.set_child(hbox) 13 | 14 | button = Gtk.Button.new_with_label('Click Me') 15 | button.connect('clicked', self.on_click_me_clicked) 16 | hbox.append(button) 17 | 18 | button = Gtk.Button.new_with_mnemonic('_Open') 19 | button.connect('clicked', self.on_open_clicked) 20 | hbox.append(button) 21 | 22 | button = Gtk.Button.new_with_mnemonic('_Close') 23 | button.connect('clicked', self.on_close_clicked) 24 | hbox.append(button) 25 | 26 | def on_click_me_clicked(self, _button): 27 | print('[Click me] button was clicked') 28 | 29 | def on_open_clicked(self, _button): 30 | print('[Open] button was clicked') 31 | 32 | def on_close_clicked(self, _button): 33 | print('Closing application') 34 | self.close() 35 | 36 | 37 | def on_activate(app): 38 | win = ButtonWindow(application=app) 39 | win.present() 40 | 41 | 42 | app = Gtk.Application(application_id='com.example.App') 43 | app.connect('activate', on_activate) 44 | 45 | app.run(None) 46 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/examples/check_radio_buttons.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class CheckButtonWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='CheckButton Demo') 10 | 11 | box = Gtk.Box(spacing=6) 12 | self.set_child(box) 13 | 14 | check = Gtk.CheckButton(label='Checkbox') 15 | check.connect('toggled', self.on_check_toggled) 16 | box.append(check) 17 | 18 | radio1 = Gtk.CheckButton(label='Radio 1') 19 | radio1.connect('toggled', self.on_radio_toggled, '1') 20 | box.append(radio1) 21 | 22 | radio2 = Gtk.CheckButton(label='Radio 2') 23 | radio2.set_group(radio1) 24 | radio2.connect('toggled', self.on_radio_toggled, '2') 25 | box.append(radio2) 26 | 27 | radio3 = Gtk.CheckButton.new_with_mnemonic('R_adio 3') 28 | radio3.set_group(radio1) 29 | radio3.connect('toggled', self.on_radio_toggled, '3') 30 | box.append(radio3) 31 | 32 | def on_check_toggled(self, check): 33 | if check.props.active: 34 | state = 'on' 35 | else: 36 | state = 'off' 37 | print('Checkbox was turned', state) 38 | 39 | def on_radio_toggled(self, radio, name): 40 | if radio.props.active: 41 | state = 'on' 42 | else: 43 | state = 'off' 44 | print('Radio', name, 'was turned', state) 45 | 46 | 47 | def on_activate(app): 48 | win = CheckButtonWindow(application=app) 49 | win.present() 50 | 51 | 52 | app = Gtk.Application(application_id='com.example.App') 53 | app.connect('activate', on_activate) 54 | 55 | app.run(None) 56 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/examples/dropdown.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class DropDownWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='DropDown Demo') 10 | 11 | dropdown = Gtk.DropDown() 12 | dropdown.connect('notify::selected-item', self.on_string_selected) 13 | self.set_child(dropdown) 14 | 15 | strings = Gtk.StringList() 16 | dropdown.props.model = strings 17 | items = 'This is a long list of words to populate the dropdown'.split() 18 | 19 | # Populate the list 20 | for item in items: 21 | strings.append(item) 22 | 23 | def on_string_selected(self, dropdown, _pspec): 24 | # Selected Gtk.StringObject 25 | selected = dropdown.props.selected_item 26 | if selected is not None: 27 | print('Selected', selected.props.string) 28 | 29 | 30 | def on_activate(app): 31 | win = DropDownWindow(application=app) 32 | win.present() 33 | 34 | 35 | app = Gtk.Application(application_id='com.example.App') 36 | app.connect('activate', on_activate) 37 | 38 | app.run(None) 39 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/examples/linkbutton.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class LinkButtonWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='LinkButton Demo') 10 | 11 | button = Gtk.LinkButton( 12 | uri='https://www.gtk.org', label='Visit GTK Homepage' 13 | ) 14 | self.set_child(button) 15 | 16 | 17 | def on_activate(app): 18 | win = LinkButtonWindow(application=app) 19 | win.present() 20 | 21 | 22 | app = Gtk.Application(application_id='com.example.App') 23 | app.connect('activate', on_activate) 24 | 25 | app.run(None) 26 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/examples/spinbutton.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class SpinButtonWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='SpinButton Demo') 10 | 11 | hbox = Gtk.Box(spacing=6) 12 | self.set_child(hbox) 13 | 14 | adjustment = Gtk.Adjustment( 15 | upper=100, step_increment=1, page_increment=10 16 | ) 17 | self.spinbutton = Gtk.SpinButton() 18 | self.spinbutton.props.adjustment = adjustment 19 | self.spinbutton.connect('value-changed', self.on_value_changed) 20 | hbox.append(self.spinbutton) 21 | 22 | check_numeric = Gtk.CheckButton(label='Numeric') 23 | check_numeric.connect('toggled', self.on_numeric_toggled) 24 | hbox.append(check_numeric) 25 | 26 | check_ifvalid = Gtk.CheckButton(label='If Valid') 27 | check_ifvalid.connect('toggled', self.on_ifvalid_toggled) 28 | hbox.append(check_ifvalid) 29 | 30 | def on_value_changed(self, _scroll): 31 | print(self.spinbutton.get_value_as_int()) 32 | 33 | def on_numeric_toggled(self, button): 34 | self.spinbutton.props.numeric = button.props.active 35 | 36 | def on_ifvalid_toggled(self, button): 37 | if button.get_active(): 38 | policy = Gtk.SpinButtonUpdatePolicy.IF_VALID 39 | else: 40 | policy = Gtk.SpinButtonUpdatePolicy.ALWAYS 41 | self.spinbutton.props.update_policy = policy 42 | 43 | 44 | def on_activate(app): 45 | win = SpinButtonWindow(application=app) 46 | win.present() 47 | 48 | 49 | app = Gtk.Application(application_id='com.example.App') 50 | app.connect('activate', on_activate) 51 | 52 | app.run(None) 53 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/examples/switch.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class SwitcherWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='Switch Demo') 10 | 11 | hbox = Gtk.Box(spacing=6, homogeneous=True) 12 | hbox.props.margin_top = 24 13 | hbox.props.margin_bottom = 24 14 | self.set_child(hbox) 15 | 16 | switch = Gtk.Switch() 17 | switch.connect('notify::active', self.on_switch_activated) 18 | switch.props.active = False 19 | switch.props.halign = Gtk.Align.CENTER 20 | hbox.append(switch) 21 | 22 | switch = Gtk.Switch() 23 | switch.connect('notify::active', self.on_switch_activated) 24 | switch.props.active = True 25 | switch.props.halign = Gtk.Align.CENTER 26 | hbox.append(switch) 27 | 28 | def on_switch_activated(self, switch, _gparam): 29 | if switch.props.active: 30 | state = 'on' 31 | else: 32 | state = 'off' 33 | print('Switch was turned', state) 34 | 35 | 36 | def on_activate(app): 37 | win = SwitcherWindow(application=app) 38 | win.present() 39 | 40 | 41 | app = Gtk.Application(application_id='com.example.App') 42 | app.connect('activate', on_activate) 43 | 44 | app.run(None) 45 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/examples/togglebutton.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class ToggleButtonWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='ToggleButton Demo') 10 | 11 | hbox = Gtk.Box(spacing=6) 12 | self.set_child(hbox) 13 | 14 | button = Gtk.ToggleButton(label='Button 1') 15 | button.connect('toggled', self.on_button_toggled, '1') 16 | hbox.append(button) 17 | 18 | button = Gtk.ToggleButton(label='B_utton 2', use_underline=True) 19 | button.set_active(True) 20 | button.connect('toggled', self.on_button_toggled, '2') 21 | hbox.append(button) 22 | 23 | def on_button_toggled(self, button, name): 24 | if button.props.active: 25 | state = 'on' 26 | else: 27 | state = 'off' 28 | print('Button', name, 'was turned', state) 29 | 30 | 31 | def on_activate(app): 32 | win = ToggleButtonWindow(application=app) 33 | win.present() 34 | 35 | 36 | app = Gtk.Application(application_id='com.example.App') 37 | app.connect('activate', on_activate) 38 | 39 | app.run(None) 40 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/images/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/controls/images/button.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/images/check_radio_buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/controls/images/check_radio_buttons.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/images/dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/controls/images/dropdown.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/images/entries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/controls/images/entries.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/images/linkbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/controls/images/linkbutton.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/images/spinbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/controls/images/spinbutton.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/images/switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/controls/images/switch.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/images/togglebutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/controls/images/togglebutton.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/scale.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | Scale 4 | ===== 5 | A :class:`Gtk.Scale` is a slider control used to select a numeric value. -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/spinbutton.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | SpinButton 4 | ========== 5 | A :class:`Gtk.SpinButton` is an ideal way to allow the user to set the value of 6 | some attribute. Rather than having to directly type a number into a 7 | :class:`Gtk.Entry`, :class:`Gtk.SpinButton` allows the user to click on one of 8 | two arrows to increment or decrement the displayed value. A value can still be 9 | typed in, with the bonus that it can be checked to ensure it is in a given range. 10 | The main properties of a :class:`Gtk.SpinButton` are set through 11 | :class:`Gtk.Adjustment`. 12 | 13 | To change the value that :class:`Gtk.SpinButton` is showing, use 14 | :attr:`Gtk.SpinButton.props.value`. The value entered can either be an integer 15 | or float, depending on your requirements, use 16 | :meth:`Gtk.SpinButton.get_value_as_int` or :meth:`Gtk.SpinButton.get_value`, 17 | respectively. 18 | 19 | When you allow the displaying of float values in the spin button, you may wish 20 | to adjust the number of decimal spaces displayed by calling 21 | :attr:`Gtk.SpinButton.props.digits`. 22 | 23 | By default, :class:`Gtk.SpinButton` accepts textual data. If you wish to limit 24 | this to numerical values only, set :attr:`Gtk.SpinButton.props.numeric` to ``True``. 25 | 26 | We can also adjust the update policy of :class:`Gtk.SpinButton`. There are two 27 | options here; by default the spin button updates the value even if the data 28 | entered is invalid. Alternatively, we can set the policy to only update when the 29 | value entered is valid by changing :attr:`Gtk.SpinButton.props.update_policy` to 30 | :attr:`Gtk.SpinButtonUpdatePolicy.IF_VALID`. 31 | 32 | Example 33 | ^^^^^^^ 34 | 35 | .. image:: images/spinbutton.png 36 | 37 | .. literalinclude:: examples/spinbutton.py 38 | :linenos: 39 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/controls/switch.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | Switch 4 | ====== 5 | A :class:`Gtk.Switch` is a widget that has two states: on or off. The user can 6 | control which state should be active by clicking the empty area, or by dragging 7 | the handle. 8 | 9 | You shouldn't use the ``activate`` signal on the Gtk.Switch which is an action 10 | signal and emitting it causes the switch to animate. Applications should never 11 | connect to this signal, but use the ``notify::active`` signal, see the example 12 | here below. 13 | 14 | Example 15 | ^^^^^^^ 16 | 17 | .. image:: images/switch.png 18 | 19 | .. literalinclude:: examples/switch.py 20 | :linenos: 21 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets.rst: -------------------------------------------------------------------------------- 1 | Display Widgets 2 | =============== 3 | 4 | Learn how to use the most basic elements to display things, like text, images, 5 | icons or ongoing progress. 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | :caption: Contents 10 | 11 | display-widgets/label 12 | display-widgets/image 13 | display-widgets/picture 14 | display-widgets/progressbar 15 | display-widgets/spinner 16 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/examples/picture.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class PictureWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='Picture Demo') 10 | 11 | # Let's set a windows size so pictures don't start at their default size 12 | self.set_default_size(500, 400) 13 | 14 | box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) 15 | self.set_child(box) 16 | 17 | label = Gtk.Label(label='Here we can see some nice pictures:') 18 | box.append(label) 19 | 20 | picture = Gtk.Picture.new_for_filename('../images/spinner_ext.png') 21 | box.append(picture) 22 | 23 | cover_picture = Gtk.Picture.new_for_filename( 24 | '../images/spinner_ext.png' 25 | ) 26 | cover_picture.props.content_fit = Gtk.ContentFit.COVER 27 | box.append(cover_picture) 28 | 29 | 30 | def on_activate(app): 31 | win = PictureWindow(application=app) 32 | win.present() 33 | 34 | 35 | app = Gtk.Application(application_id='com.example.App') 36 | app.connect('activate', on_activate) 37 | 38 | app.run(None) 39 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/examples/progressbar.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk, GLib 5 | 6 | 7 | class ProgressBarWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='ProgressBar Demo') 10 | 11 | vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) 12 | self.set_child(vbox) 13 | 14 | self.progressbar = Gtk.ProgressBar() 15 | vbox.append(self.progressbar) 16 | 17 | button = Gtk.CheckButton(label='Show text') 18 | button.connect('toggled', self.on_show_text_toggled) 19 | vbox.append(button) 20 | 21 | button = Gtk.CheckButton(label='Activity mode') 22 | button.connect('toggled', self.on_activity_mode_toggled) 23 | vbox.append(button) 24 | 25 | button = Gtk.CheckButton(label='Right to Left') 26 | button.connect('toggled', self.on_right_to_left_toggled) 27 | vbox.append(button) 28 | 29 | self.timeout_id = GLib.timeout_add(50, self.on_timeout) 30 | self.activity_mode = False 31 | 32 | def on_show_text_toggled(self, button): 33 | show_text = button.props.active 34 | if show_text: 35 | text = 'some text' 36 | else: 37 | text = None 38 | self.progressbar.props.text = text 39 | self.progressbar.props.show_text = show_text 40 | 41 | def on_activity_mode_toggled(self, button): 42 | self.activity_mode = button.props.active 43 | if self.activity_mode: 44 | self.progressbar.pulse() 45 | else: 46 | self.progressbar.props.fraction = 0.0 47 | 48 | def on_right_to_left_toggled(self, button): 49 | value = button.props.active 50 | self.progressbar.props.inverted = value 51 | 52 | def on_timeout(self): 53 | ''' 54 | Update value on the progress bar 55 | ''' 56 | if self.activity_mode: 57 | self.progressbar.pulse() 58 | else: 59 | new_value = self.progressbar.props.fraction + 0.01 60 | 61 | if new_value > 1: 62 | new_value = 0 63 | 64 | self.progressbar.props.fraction = new_value 65 | 66 | # As this is a timeout function, return True so that it 67 | # continues to get called 68 | return True 69 | 70 | 71 | def on_activate(app): 72 | win = ProgressBarWindow(application=app) 73 | win.present() 74 | 75 | 76 | app = Gtk.Application(application_id='com.example.App') 77 | app.connect('activate', on_activate) 78 | 79 | app.run(None) 80 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/examples/spinner.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class SpinnerAnimation(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='Spinner Demo') 10 | 11 | button = Gtk.ToggleButton(label='Start Spinning') 12 | button.connect('toggled', self.on_button_toggled) 13 | button.props.active = False 14 | 15 | self.spinner = Gtk.Spinner() 16 | 17 | box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, homogeneous=True) 18 | box.append(button) 19 | box.append(self.spinner) 20 | self.set_child(box) 21 | 22 | def on_button_toggled(self, button): 23 | if button.props.active: 24 | self.spinner.start() 25 | button.set_label('Stop Spinning') 26 | 27 | else: 28 | self.spinner.stop() 29 | button.set_label('Start Spinning') 30 | 31 | 32 | def on_activate(app): 33 | win = SpinnerAnimation(application=app) 34 | win.present() 35 | 36 | 37 | app = Gtk.Application(application_id='com.example.App') 38 | app.connect('activate', on_activate) 39 | 40 | app.run(None) 41 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/image.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | Image 4 | ===== 5 | 6 | :class:`Gtk.Image` is a widget to display images. 7 | Various kinds of object can be displayed as an image. 8 | Most typically, you would load a :class:`Gdk.Texture` from a file, using the 9 | convenience function :meth:`Gtk.Image.new_from_file`, or 10 | :meth:`Gtk.Image.new_from_icon_name`. 11 | 12 | :class:`Gtk.Image` displays its image as an icon, with a size that is determined 13 | by the application. See :doc:`/tutorials/gtk4/display-widgets/picture` if you want to show 14 | an image at is actual size. 15 | 16 | Sometimes an application will want to avoid depending on external data files, 17 | such as image files. 18 | See the documentation of :class:`Gio.Resource` inside GIO, for details. 19 | In this case, :attr:`Gtk.Image.props.resource` and 20 | :meth:`Gtk.Image.new_from_resource`, should be used. 21 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/images/label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/display-widgets/images/label.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/images/picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/display-widgets/images/picture.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/images/progressbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/display-widgets/images/progressbar.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/images/spinner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/display-widgets/images/spinner.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/images/spinner_ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/display-widgets/images/spinner_ext.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/picture.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | Picture 4 | ======= 5 | 6 | :class:`Gtk.Picture` displays an image at its natural size. 7 | Many convenience functions are provided to make pictures simple to use. 8 | For example, if you want to load an image from a file you can use 9 | :meth:`Gtk.Picture.new_for_filename`. 10 | 11 | You can influence how the image is displayed inside the :class:`Gtk.Picture` by 12 | changing :attr:`Gtk.Picture.props.content_fit`. See :class:`Gtk.ContentFit` for 13 | details. 14 | Also :attr:`Gtk.Widget.props.halign` and :attr:`Gtk.Widget.props.valign` can be 15 | used to set whether the picture will fill all available space or is displayed at its 16 | original size. 17 | 18 | Sometimes an application will want to avoid depending on external data files, 19 | such as image files. 20 | See the documentation of :class:`Gio.Resource` inside GIO, for details. 21 | In this case, :meth:`Gtk.Picture.new_for_resource` and 22 | :meth:`Gtk.Picture.set_resource`, should be used. 23 | 24 | .. note:: This example requires a GTK version higher o equal to ``4.8``. 25 | 26 | Example 27 | ------- 28 | 29 | .. image:: images/picture.png 30 | 31 | .. literalinclude:: examples/picture.py 32 | :linenos: 33 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/progressbar.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | ProgressBar 4 | =========== 5 | The :class:`Gtk.ProgressBar` is typically used to display the progress of a 6 | long running operation. It provides a visual clue that processing is underway. 7 | The :class:`Gtk.ProgressBar` can be used in two different modes: *percentage 8 | mode* and *activity mode*. 9 | 10 | When an application can determine how much work needs to take place (e.g. read 11 | a fixed number of bytes from a file) and can monitor its progress, it can use 12 | the :class:`Gtk.ProgressBar` in *percentage mode* and the user sees a growing 13 | bar indicating the percentage of the work that has been completed. 14 | In this mode, the application is required to set 15 | :attr:`Gtk.ProgressBar.props.fraction` periodically to update the progress bar, 16 | setting a float between 0 and 1 to provide the new percentage value. 17 | 18 | When an application has no accurate way of knowing the amount of work to do, it 19 | can use *activity mode*, which shows activity by a block moving back and forth 20 | within the progress area. In this mode, the application is required to call 21 | :meth:`Gtk.ProgressBar.pulse` periodically to update the progress bar. 22 | You can also choose the step size, with the 23 | :attr:`Gtk.ProgressBar.props.pulse_step` property. 24 | 25 | By default, :class:`Gtk.ProgressBar` is horizontal and left-to-right, but you 26 | can change it to a vertical progress bar by changing the value of 27 | :attr:`Gtk.ProgressBar.props.orientation `. 28 | Changing the direction the progress bar grows can be done using 29 | :attr:`Gtk.ProgressBar.props.inverted`. :class:`Gtk.ProgressBar` can also 30 | contain text which can be set with :attr:`Gtk.ProgressBar.props.text` and 31 | :attr:`Gtk.ProgressBar.props.show_text`. 32 | 33 | Example 34 | ------- 35 | 36 | .. image:: images/progressbar.png 37 | 38 | .. literalinclude:: examples/progressbar.py 39 | :linenos: 40 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/display-widgets/spinner.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | Spinner 4 | ======= 5 | The :class:`Gtk.Spinner` displays an icon-size spinning animation. 6 | It is often used as an alternative to a :class:`Gtk.ProgressBar` 7 | for displaying indefinite activity, instead of actual progress. 8 | 9 | To start the animation, use :meth:`Gtk.Spinner.start`, 10 | to stop it use :meth:`Gtk.Spinner.stop`. 11 | 12 | Example 13 | ------- 14 | 15 | .. image:: images/spinner.png 16 | 17 | .. literalinclude:: examples/spinner.py 18 | :linenos: 19 | 20 | 21 | Extended example 22 | ---------------- 23 | An extended example that uses a timeout function to start and stop 24 | the spinning animation. 25 | The :func:`on_timeout` function is called at regular intervals 26 | until it returns ``False``, at which point the timeout is automatically 27 | destroyed and the function will not be called again. 28 | 29 | Example 30 | ^^^^^^^ 31 | 32 | .. image:: images/spinner_ext.png 33 | 34 | .. literalinclude:: examples/spinner_ext.py 35 | :linenos: 36 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/examples/extended_example.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class MyWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='Hello World') 10 | 11 | self.button = Gtk.Button(label='Click Here') 12 | self.button.connect('clicked', self.on_button_clicked) 13 | self.set_child(self.button) 14 | 15 | def on_button_clicked(self, _widget): 16 | print('Hello World') 17 | self.close() 18 | 19 | 20 | def on_activate(app): 21 | # Create window 22 | win = MyWindow(application=app) 23 | win.present() 24 | 25 | 26 | app = Gtk.Application(application_id='com.example.App') 27 | app.connect('activate', on_activate) 28 | 29 | app.run(None) 30 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/examples/layout_box.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class MyWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='Hello World') 10 | 11 | box = Gtk.Box(spacing=6) 12 | self.set_child(box) 13 | 14 | button1 = Gtk.Button(label='Hello') 15 | button1.connect('clicked', self.on_button1_clicked) 16 | box.append(button1) 17 | 18 | button2 = Gtk.Button(label='Goodbye') 19 | button2.props.hexpand = True 20 | button2.connect('clicked', self.on_button2_clicked) 21 | box.append(button2) 22 | 23 | def on_button1_clicked(self, _widget): 24 | print('Hello') 25 | 26 | def on_button2_clicked(self, _widget): 27 | print('Goodbye') 28 | 29 | 30 | def on_activate(app): 31 | # Create window 32 | win = MyWindow(application=app) 33 | win.present() 34 | 35 | 36 | app = Gtk.Application(application_id='com.example.App') 37 | app.connect('activate', on_activate) 38 | 39 | app.run(None) 40 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/examples/layout_center.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class CenterBoxWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, default_width=400, title='CenterBox Example') 10 | 11 | box = Gtk.CenterBox() 12 | self.set_child(box) 13 | 14 | button1 = Gtk.Button(label='Start') 15 | box.set_start_widget(button1) 16 | 17 | label = Gtk.Label(label='Center') 18 | box.set_center_widget(label) 19 | 20 | button2 = Gtk.Button(label='End') 21 | box.set_end_widget(button2) 22 | 23 | 24 | def on_activate(app): 25 | # Create window 26 | win = CenterBoxWindow(application=app) 27 | win.present() 28 | 29 | 30 | app = Gtk.Application(application_id='com.example.App') 31 | app.connect('activate', on_activate) 32 | 33 | app.run(None) 34 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/examples/layout_grid.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class GridWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='Grid Example') 10 | 11 | button1 = Gtk.Button(label='Button 1') 12 | button2 = Gtk.Button(label='Button 2') 13 | button3 = Gtk.Button(label='Button 3') 14 | button4 = Gtk.Button(label='Button 4') 15 | button5 = Gtk.Button(label='Button 5') 16 | button6 = Gtk.Button(label='Button 6') 17 | 18 | grid = Gtk.Grid() 19 | grid.attach(button1, 0, 0, 1, 1) 20 | grid.attach(button2, 1, 0, 2, 1) 21 | grid.attach_next_to(button3, button1, Gtk.PositionType.BOTTOM, 1, 2) 22 | grid.attach_next_to(button4, button3, Gtk.PositionType.RIGHT, 2, 1) 23 | grid.attach(button5, 1, 2, 1, 1) 24 | grid.attach_next_to(button6, button5, Gtk.PositionType.RIGHT, 1, 1) 25 | 26 | self.set_child(grid) 27 | 28 | 29 | def on_activate(app): 30 | # Create window 31 | win = GridWindow(application=app) 32 | win.present() 33 | 34 | 35 | app = Gtk.Application(application_id='com.example.App') 36 | app.connect('activate', on_activate) 37 | 38 | app.run(None) 39 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/examples/layout_headerbar.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class HeaderBarWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, default_width=400, title='HeaderBar Example') 10 | 11 | header_bar = Gtk.HeaderBar() 12 | self.set_titlebar(header_bar) 13 | 14 | button = Gtk.Button(label='Button') 15 | header_bar.pack_start(button) 16 | 17 | icon_button = Gtk.Button(icon_name='open-menu-symbolic') 18 | header_bar.pack_end(icon_button) 19 | 20 | 21 | def on_activate(app): 22 | # Create window 23 | win = HeaderBarWindow(application=app) 24 | win.present() 25 | 26 | 27 | app = Gtk.Application(application_id='com.example.App') 28 | app.connect('activate', on_activate) 29 | 30 | app.run(None) 31 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/examples/layout_notebook.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class NotebookWindow(Gtk.Window): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='Simple Notebook Example') 10 | 11 | notebook = Gtk.Notebook() 12 | self.set_child(notebook) 13 | 14 | page1 = Gtk.Box() 15 | page1.append(Gtk.Label(label='Default Page!')) 16 | notebook.append_page(page1, Gtk.Label(label='Plain Title')) 17 | 18 | page2 = Gtk.Box() 19 | page2.append(Gtk.Label(label='A page with an image for a Title.')) 20 | notebook.append_page(page2, Gtk.Image(icon_name='help-about')) 21 | 22 | 23 | def on_activate(app): 24 | # Create window 25 | win = NotebookWindow(application=app) 26 | win.present() 27 | 28 | 29 | app = Gtk.Application(application_id='com.example.App') 30 | app.connect('activate', on_activate) 31 | 32 | app.run(None) 33 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/examples/layout_stack.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk, GObject 5 | 6 | 7 | class StackWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='Stack Demo') 10 | 11 | self.set_default_size(300, 250) 12 | 13 | header = Gtk.HeaderBar() 14 | self.set_titlebar(header) 15 | 16 | stack = Gtk.Stack() 17 | stack.props.transition_type = Gtk.StackTransitionType.SLIDE_LEFT_RIGHT 18 | stack.props.transition_duration = 1000 19 | self.set_child(stack) 20 | 21 | checkbutton = Gtk.CheckButton(label='Click me!') 22 | checkbutton.props.hexpand = True 23 | checkbutton.props.halign = Gtk.Align.CENTER 24 | page1 = stack.add_titled(checkbutton, 'check', 'Check Button') 25 | checkbutton.bind_property( 26 | 'active', page1, 'needs-attention', GObject.BindingFlags.DEFAULT 27 | ) 28 | 29 | label = Gtk.Label() 30 | label.set_markup('A fancy label') 31 | stack.add_titled(label, 'label', 'A label') 32 | 33 | stack_switcher = Gtk.StackSwitcher() 34 | stack_switcher.set_stack(stack) 35 | header.set_title_widget(stack_switcher) 36 | 37 | # Let's start in the second page 38 | stack.set_visible_child_name('label') 39 | 40 | 41 | def on_activate(app): 42 | # Create window 43 | win = StackWindow(application=app) 44 | win.present() 45 | 46 | 47 | app = Gtk.Application(application_id='com.example.App') 48 | app.connect('activate', on_activate) 49 | 50 | app.run(None) 51 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/examples/popover.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | class PopoverWindow(Gtk.ApplicationWindow): 8 | def __init__(self, **kargs): 9 | super().__init__(**kargs, title='Popover Demo') 10 | 11 | self.set_default_size(300, 200) 12 | 13 | box = Gtk.Box(spacing=6, orientation=Gtk.Orientation.VERTICAL) 14 | box.props.halign = box.props.valign = Gtk.Align.CENTER 15 | self.set_child(box) 16 | 17 | popover = Gtk.Popover() 18 | popover_box = Gtk.Box() 19 | popover_box.append(Gtk.Label(label='Item')) 20 | popover.set_child(popover_box) 21 | 22 | button = Gtk.MenuButton(label='Click Me', popover=popover) 23 | box.append(button) 24 | 25 | button2 = Gtk.Button(label='Click Me 2') 26 | button2.connect('clicked', self.on_button_clicked) 27 | box.append(button2) 28 | 29 | self.popover2 = Gtk.Popover() 30 | self.popover2.set_child(Gtk.Label(label='Another Popup!')) 31 | self.popover2.set_parent(button2) 32 | self.popover2.props.position = Gtk.PositionType.LEFT 33 | 34 | def on_button_clicked(self, _button): 35 | self.popover2.popup() 36 | 37 | 38 | def on_activate(app): 39 | win = PopoverWindow(application=app) 40 | win.present() 41 | 42 | 43 | app = Gtk.Application(application_id='com.example.App') 44 | app.connect('activate', on_activate) 45 | 46 | app.run(None) 47 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/examples/popover_menu.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gio, Gtk 5 | 6 | # This would typically be its own file 7 | MENU_XML = """ 8 | 9 | 10 | 11 |
12 | 13 | About 14 | app.about 15 | 16 | 17 | Quit 18 | app.quit 19 | 20 |
21 |
22 |
23 | """ 24 | 25 | 26 | class AppWindow(Gtk.ApplicationWindow): 27 | def __init__(self, **kwargs): 28 | super().__init__(**kwargs) 29 | 30 | self.set_default_size(300, 200) 31 | 32 | headerbar = Gtk.HeaderBar() 33 | self.set_titlebar(headerbar) 34 | 35 | builder = Gtk.Builder.new_from_string(MENU_XML, -1) 36 | menu_model = builder.get_object('app-menu') 37 | 38 | button = Gtk.MenuButton(menu_model=menu_model) 39 | headerbar.pack_end(button) 40 | 41 | 42 | class Application(Gtk.Application): 43 | def __init__(self, **kwargs): 44 | super().__init__(application_id='com.example.App', **kwargs) 45 | self.window = None 46 | 47 | def do_startup(self): 48 | Gtk.Application.do_startup(self) 49 | 50 | action = Gio.SimpleAction(name='about') 51 | action.connect('activate', self.on_about) 52 | self.add_action(action) 53 | 54 | action = Gio.SimpleAction(name='quit') 55 | action.connect('activate', self.on_quit) 56 | self.add_action(action) 57 | 58 | def do_activate(self): 59 | # We only allow a single window and raise any existing ones 60 | if not self.window: 61 | # Windows are associated with the application 62 | # when the last one is closed the application shuts down 63 | self.window = AppWindow(application=self, title='Main Window') 64 | 65 | self.window.present() 66 | 67 | def on_about(self, action, param): 68 | about_dialog = Gtk.AboutDialog(transient_for=self.window, modal=True) 69 | about_dialog.present() 70 | 71 | def on_quit(self, action, param): 72 | self.quit() 73 | 74 | 75 | app = Application() 76 | app.run(None) 77 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/examples/simple_example.py: -------------------------------------------------------------------------------- 1 | import gi 2 | 3 | gi.require_version('Gtk', '4.0') 4 | from gi.repository import Gtk 5 | 6 | 7 | def on_activate(app): 8 | # Create window 9 | win = Gtk.ApplicationWindow(application=app) 10 | win.present() 11 | 12 | 13 | # Create a new application 14 | app = Gtk.Application(application_id='com.example.App') 15 | app.connect('activate', on_activate) 16 | 17 | # Run the application 18 | app.run(None) 19 | -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/application.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/basic_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/basic_example.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/clipboard.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/drag_and_drop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/drag_and_drop.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/extended_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/extended_example.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/layout_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/layout_box.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/layout_center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/layout_center.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/layout_flowbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/layout_flowbox.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/layout_grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/layout_grid.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/layout_headerbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/layout_headerbar.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/layout_listbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/layout_listbox.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/layout_notebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/layout_notebook.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/layout_stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/layout_stack.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/popover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/popover.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/popover_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/popover_menu.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/images/textview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/pygobject/889a58398be4cde742341a265e5a3c3b27645a9c/docs/tutorials/gtk4/images/textview.png -------------------------------------------------------------------------------- /docs/tutorials/gtk4/popovers.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | Popovers 4 | ======== 5 | 6 | The :class:`Gtk.Popover` is an special kind of window used for displaying 7 | additional information and is often used with button menus and context menus. 8 | Popovers are attached to a parent widget and point to it. 9 | It's position can be configured with :attr:`Gtk.Popover.props.position`. 10 | :class:`Gtk.Popover` shows an arrow to visually connect where it points to, 11 | this can be disabled setting :attr:`Gtk.Popover.props.has_arrow` to ``False``. 12 | 13 | A :class:`Gtk.Popover` can be opened using :meth:`Gtk.Popover.popup` and hidden 14 | with :meth:`Gtk.Widget.hide`. 15 | 16 | GTK also provides :class:`Gtk.MenuButton`, it's an special button that can show 17 | and hide a :class:`Gtk.Popover` attached to it using 18 | :attr:`Gtk.MenuButton.props.popover`. 19 | 20 | Custom Popover 21 | -------------- 22 | 23 | A child widget can be added to a popover using :meth:`Gtk.Popover.set_child`. 24 | The parent of the popover can be set using :meth:`Gtk.Widget.set_parent`. 25 | 26 | Example 27 | ^^^^^^^ 28 | 29 | .. image:: images/popover.png 30 | 31 | .. literalinclude:: examples/popover.py 32 | :linenos: 33 | 34 | 35 | Menu Popover 36 | ------------ 37 | 38 | GTK also has :class:`Gtk.PopoverMenu`, it's a :class:`Gtk.Popover` subclass 39 | designed to display a menu model. 40 | 41 | A popover can be created from a :class:`Gio.MenuModel` using 42 | :meth:`Gtk.PopoverMenu.new_from_model` and can be changed after creation with 43 | :attr:`Gtk.PopoverMenu.props.menu_model`. 44 | 45 | :class:`Gtk.MenuButton` also can construct a :class:`Gtk.PopoverMenu` passing it 46 | a :class:`Gio.MenuModel` to :attr:`Gtk.MenuButton.props.menu_model`. 47 | 48 | .. seealso:: 49 | In :doc:`GTK Application ` we also showed examples of menu 50 | models. 51 | 52 | Example 53 | ^^^^^^^ 54 | 55 | .. image:: images/popover_menu.png 56 | 57 | .. literalinclude:: examples/popover_menu.py 58 | -------------------------------------------------------------------------------- /docs/tutorials/index.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | Tutorials 3 | ========= 4 | 5 | These tutorials give an introduction to writing GTK/GNOME applications in 6 | Python. 7 | 8 | Prior to working through these tutorials, it is recommended that you have a 9 | reasonable grasp of the Python programming language. It is necessary for you to 10 | know how to create and run Python files, understand basic interpreter errors, 11 | and work with strings, integers, floats and boolean values. For the more 12 | advanced parts of these examples, good knowledge of lists and tuples will be 13 | needed. 14 | 15 | Although here we try to describe the most important classes and methods from 16 | GObject based libraries like GTK, it is not supposed to serve as an API 17 | reference. Please refer to the :ref:`api-references` list where you will 18 | find a detailed description of the API for each library. Also there's a 19 | `Python-specific reference `_ 20 | available. 21 | 22 | .. note:: 23 | Our tutorial list is still not as extensive as we would like, so if you 24 | have experience with PyGObject, contributing docs is a great way to help. 25 | 26 | Some areas that could use your help: libadwaita components, GLib and Gio 27 | features. 28 | 29 | 30 | .. _api-references: 31 | 32 | API References 33 | -------------- 34 | 35 | * `GObject `_ 36 | * `Gtk 4 `_ 37 | * `Gdk 4 `_ 38 | * `Gio `_ 39 | * `GLib `_ 40 | * `Adwaita `_ 41 | * `Python-specific references `_ 42 | 43 | Other Resources 44 | --------------- 45 | 46 | * The :devdocs:`GNOME Developer Documentation ` 47 | has some tutorials that include Python examples. 48 | 49 | 50 | .. toctree:: 51 | :maxdepth: 1 52 | :hidden: 53 | :caption: Contents 54 | 55 | gobject 56 | gtk4 57 | libadwaita 58 | gtk3 59 | 60 | .. toctree:: 61 | :maxdepth: 1 62 | :hidden: 63 | :caption: External Resources 64 | 65 | .. toctree:: 66 | :maxdepth: 1 67 | :hidden: 68 | :caption: About 69 | -------------------------------------------------------------------------------- /docs/tutorials/libadwaita.rst: -------------------------------------------------------------------------------- 1 | Adwaita 2 | ======= 3 | 4 | `Adwaita `_ (``libadwaita``) 5 | offers application developers many widgets and objects to build GNOME 6 | applications scaling from desktop workstations to mobile phones. 7 | 8 | Adwaita is the library you must use if you want to build applications targeting 9 | the GNOME desktop and follow its `Human Interface Guidelines `_. 10 | 11 | .. toctree:: 12 | :maxdepth: 3 13 | :caption: Contents 14 | 15 | libadwaita/application 16 | -------------------------------------------------------------------------------- /docs/tutorials/libadwaita/application.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: gi.repository 2 | 3 | Adwaita Application 4 | =================== 5 | 6 | :class:`Adw.Application` extends :class:`Gtk.Application` to ease some task 7 | related to creating applications for GNOME. 8 | 9 | .. seealso:: 10 | 11 | We previously touched :class:`Gtk.Application` in :doc:`this tutorial `. 12 | 13 | 14 | Adwaita also have :class:`Adw.ApplicationWindow`, it's a subclass of :class:`Gtk.ApplicationWindow` 15 | that provides the same "freform" features from :class:`Adw.Window`. 16 | 17 | .. note:: 18 | Using :class:`Adw.Application` will also call :func:`Adw.init` for you, this 19 | function initialize de library, making sure that translations, types, 20 | themes, icons and stylesheets needed by the library are set up properly. 21 | 22 | 23 | Stylesheets 24 | ----------- 25 | 26 | If you make use of :class:`Gio.Resource`, :class:`Adw.Application` will 27 | automatically load stylesheets located in the application's resource base path. 28 | 29 | This way you don't need to manually load stylesheets, and it will load the 30 | matching stylesheets depending on the system appearance settings exposed by 31 | :class:`Adw.StyleManager`. 32 | 33 | 34 | * ``style.css`` contains the base styles. 35 | 36 | * ``style-dark.css`` contains styles only used when :attr:`Adw.StyleManager.props.dark` 37 | is ``True``. 38 | 39 | * ``style-hc.css`` contains styles used when :attr:`Adw.StyleManager.props.high_contrast` is ``True``. 40 | 41 | * ``style-hc-dark.css`` contains styles used when :attr:`Adw.StyleManager.props.high_contrast` 42 | and :attr:`Adw.StyleManager.props.dark` are both ``True``. 43 | -------------------------------------------------------------------------------- /gi/_constants.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python; py-indent-offset: 4 -*- 2 | # pygobject - Python bindings for the GObject library 3 | # Copyright (C) 2006-2007 Johan Dahlin 4 | # 5 | # gi/_constants.py: GObject type constants 6 | # 7 | # This library is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU Lesser General Public 9 | # License as published by the Free Software Foundation; either 10 | # version 2.1 of the License, or (at your option) any later version. 11 | # 12 | # This library is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # Lesser General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Lesser General Public 18 | # License along with this library; if not, see . 19 | 20 | from . import _gi 21 | 22 | TYPE_INVALID = _gi.TYPE_INVALID 23 | TYPE_NONE = _gi.GType.from_name('void') 24 | TYPE_INTERFACE = _gi.GType.from_name('GInterface') 25 | TYPE_CHAR = _gi.GType.from_name('gchar') 26 | TYPE_UCHAR = _gi.GType.from_name('guchar') 27 | TYPE_BOOLEAN = _gi.GType.from_name('gboolean') 28 | TYPE_INT = _gi.GType.from_name('gint') 29 | TYPE_UINT = _gi.GType.from_name('guint') 30 | TYPE_LONG = _gi.GType.from_name('glong') 31 | TYPE_ULONG = _gi.GType.from_name('gulong') 32 | TYPE_INT64 = _gi.GType.from_name('gint64') 33 | TYPE_UINT64 = _gi.GType.from_name('guint64') 34 | TYPE_ENUM = _gi.GType.from_name('GEnum') 35 | TYPE_FLAGS = _gi.GType.from_name('GFlags') 36 | TYPE_FLOAT = _gi.GType.from_name('gfloat') 37 | TYPE_DOUBLE = _gi.GType.from_name('gdouble') 38 | TYPE_STRING = _gi.GType.from_name('gchararray') 39 | TYPE_POINTER = _gi.GType.from_name('gpointer') 40 | TYPE_BOXED = _gi.GType.from_name('GBoxed') 41 | TYPE_PARAM = _gi.GType.from_name('GParam') 42 | TYPE_OBJECT = _gi.GType.from_name('GObject') 43 | TYPE_PYOBJECT = _gi.GType.from_name('PyObject') 44 | TYPE_GTYPE = _gi.GType.from_name('GType') 45 | TYPE_STRV = _gi.GType.from_name('GStrv') 46 | TYPE_VARIANT = _gi.GType.from_name('GVariant') 47 | TYPE_UNICHAR = TYPE_UINT 48 | -------------------------------------------------------------------------------- /gi/_error.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python; py-indent-offset: 4 -*- 2 | # vim: tabstop=4 shiftwidth=4 expandtab 3 | # 4 | # Copyright (C) 2014 Simon Feltman 5 | # 6 | # _error.py: GError Python implementation 7 | # 8 | # This library is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU Lesser General Public 10 | # License as published by the Free Software Foundation; either 11 | # version 2.1 of the License, or (at your option) any later version. 12 | # 13 | # This library is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public 19 | # License along with this library; if not, write to the Free Software 20 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 21 | # USA 22 | 23 | 24 | # NOTE: This file should not have any dependencies on introspection libs 25 | # like gi.repository.GLib because it would cause a circular dependency. 26 | # Developers wanting to use the GError class in their applications should 27 | # use gi.repository.GLib.GError 28 | 29 | 30 | class GError(RuntimeError): 31 | def __init__(self, message='unknown error', domain='pygi-error', code=0): 32 | super(GError, self).__init__(message) 33 | self.message = message 34 | self.domain = domain 35 | self.code = code 36 | 37 | def __str__(self): 38 | return "%s: %s (%d)" % (self.domain, self.message, self.code) 39 | 40 | def __repr__(self): 41 | return "%s.%s('%s', '%s', %d)" % ( 42 | GError.__module__.rsplit(".", 1)[-1], GError.__name__, 43 | self.message, self.domain, self.code) 44 | 45 | def copy(self): 46 | return GError(self.message, self.domain, self.code) 47 | 48 | def matches(self, domain, code): 49 | """Placeholder that will be monkey patched in GLib overrides.""" 50 | raise NotImplementedError 51 | 52 | @staticmethod 53 | def new_literal(domain, message, code): 54 | """Placeholder that will be monkey patched in GLib overrides.""" 55 | raise NotImplementedError 56 | -------------------------------------------------------------------------------- /gi/gimodule.h: -------------------------------------------------------------------------------- 1 | #ifndef _PYGOBJECT_GIMODULE_H_ 2 | #define _PYGOBJECT_GIMODULE_H_ 3 | 4 | #include "pygobject-internal.h" 5 | 6 | int pygobject_constructv (PyGObject *self, 7 | guint n_properties, 8 | const char *names[], 9 | const GValue values[]); 10 | 11 | GObject * 12 | pygobject_object_new_with_properties(GType object_type, 13 | guint n_properties, 14 | const char *names[], 15 | const GValue values[]); 16 | 17 | #endif /*_PYGOBJECT_GIMODULE_H_*/ 18 | -------------------------------------------------------------------------------- /gi/meson.build: -------------------------------------------------------------------------------- 1 | sources = [ 2 | 'pygboxed.c', 3 | 'pygenum.c', 4 | 'pygflags.c', 5 | 'pyginterface.c', 6 | 'pygobject-object.c', 7 | 'pygpointer.c', 8 | 'pygoptioncontext.c', 9 | 'pygoptiongroup.c', 10 | 'pygspawn.c', 11 | 'gimodule.c', 12 | 'pygi-repository.c', 13 | 'pygi-info.c', 14 | 'pygi-foreign.c', 15 | 'pygi-struct.c', 16 | 'pygi-source.c', 17 | 'pygi-argument.c', 18 | 'pygi-resulttuple.c', 19 | 'pygi-async.c', 20 | 'pygi-type.c', 21 | 'pygi-boxed.c', 22 | 'pygi-closure.c', 23 | 'pygi-ccallback.c', 24 | 'pygi-util.c', 25 | 'pygi-property.c', 26 | 'pygi-signal-closure.c', 27 | 'pygi-invoke.c', 28 | 'pygi-cache.c', 29 | 'pygi-marshal-cleanup.c', 30 | 'pygi-basictype.c', 31 | 'pygi-list.c', 32 | 'pygi-array.c', 33 | 'pygi-error.c', 34 | 'pygi-object.c', 35 | 'pygi-fundamental.c', 36 | 'pygi-value.c', 37 | 'pygi-enum-marshal.c', 38 | 'pygi-struct-marshal.c', 39 | 'pygi-hashtable.c'] 40 | 41 | headers = [ 42 | 'pygobject.h' 43 | ] 44 | 45 | install_headers(headers, subdir : 'pygobject-@0@'.format(platform_version)) 46 | 47 | python_sources = [ 48 | 'events.py', 49 | '_constants.py', 50 | 'docstring.py', 51 | '_enum.py', 52 | '_error.py', 53 | '_gtktemplate.py', 54 | 'importer.py', 55 | '__init__.py', 56 | 'module.py', 57 | '_option.py', 58 | '_ossighelper.py', 59 | '_propertyhelper.py', 60 | 'pygtkcompat.py', 61 | '_signalhelper.py', 62 | '_signature.py', 63 | 'types.py', 64 | ] 65 | 66 | python.install_sources(python_sources, 67 | pure : false, 68 | subdir : 'gi' 69 | ) 70 | 71 | # https://github.com/mesonbuild/meson/issues/4117 72 | if host_machine.system() == 'windows' 73 | python_ext_dep = python_dep 74 | else 75 | python_ext_dep = python_dep.partial_dependency(compile_args: true) 76 | endif 77 | 78 | configure_file(output : 'config.h', configuration : cdata) 79 | 80 | giext = python.extension_module('_gi', sources, 81 | dependencies : [python_ext_dep, glib_dep, gi_dep, ffi_dep, pythoncapi_compat_dep], 82 | install: true, 83 | subdir : 'gi', 84 | c_args: pyext_c_args + main_c_args 85 | ) 86 | 87 | if cairo_dep.found() 88 | gicairoext = python.extension_module('_gi_cairo', ['pygi-foreign-cairo.c'], 89 | dependencies : [python_ext_dep, glib_dep, gi_dep, ffi_dep, pycairo_dep, cairo_dep, cairo_gobject_dep, pythoncapi_compat_dep], 90 | install: true, 91 | subdir : 'gi', 92 | c_args: pyext_c_args + main_c_args) 93 | endif 94 | 95 | subdir('overrides') 96 | subdir('repository') 97 | -------------------------------------------------------------------------------- /gi/overrides/GIMarshallingTests.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python; py-indent-offset: 4 -*- 2 | # vim: tabstop=4 shiftwidth=4 expandtab 3 | # 4 | # Copyright (C) 2010 Simon van der Linden 5 | # 6 | # This library is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU Lesser General Public 8 | # License as published by the Free Software Foundation; either 9 | # version 2.1 of the License, or (at your option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public 17 | # License along with this library; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19 | # USA 20 | 21 | from ..overrides import override 22 | from ..module import get_introspection_module 23 | 24 | GIMarshallingTests = get_introspection_module('GIMarshallingTests') 25 | 26 | __all__ = [] 27 | 28 | OVERRIDES_CONSTANT = 7 29 | __all__.append('OVERRIDES_CONSTANT') 30 | 31 | 32 | class OverridesStruct(GIMarshallingTests.OverridesStruct): 33 | 34 | def __new__(cls, long_): 35 | return GIMarshallingTests.OverridesStruct.__new__(cls) 36 | 37 | def __init__(self, long_): 38 | GIMarshallingTests.OverridesStruct.__init__(self) 39 | self.long_ = long_ 40 | 41 | def method(self): 42 | return GIMarshallingTests.OverridesStruct.method(self) / 7 43 | 44 | 45 | OverridesStruct = override(OverridesStruct) 46 | __all__.append('OverridesStruct') 47 | 48 | 49 | class OverridesObject(GIMarshallingTests.OverridesObject): 50 | 51 | def __new__(cls, long_): 52 | return GIMarshallingTests.OverridesObject.__new__(cls) 53 | 54 | def __init__(self, long_): 55 | GIMarshallingTests.OverridesObject.__init__(self) 56 | # FIXME: doesn't work yet 57 | # self.long_ = long_ 58 | 59 | @classmethod 60 | def new(cls, long_): 61 | self = GIMarshallingTests.OverridesObject.new() 62 | # FIXME: doesn't work yet 63 | # self.long_ = long_ 64 | return self 65 | 66 | def method(self): 67 | """Overridden doc string.""" 68 | return GIMarshallingTests.OverridesObject.method(self) / 7 69 | 70 | 71 | OverridesObject = override(OverridesObject) 72 | __all__.append('OverridesObject') 73 | -------------------------------------------------------------------------------- /gi/overrides/GdkPixbuf.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Christoph Reiter 2 | # 3 | # This library is free software; you can redistribute it and/or 4 | # modify it under the terms of the GNU Lesser General Public 5 | # License as published by the Free Software Foundation; either 6 | # version 2.1 of the License, or (at your option) any later version. 7 | # 8 | # This library is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | # Lesser General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU Lesser General Public 14 | # License along with this library; if not, write to the Free Software 15 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 16 | # USA 17 | 18 | import warnings 19 | 20 | from gi import PyGIDeprecationWarning 21 | from gi.repository import GLib 22 | 23 | from ..overrides import override 24 | from ..module import get_introspection_module 25 | 26 | 27 | GdkPixbuf = get_introspection_module('GdkPixbuf') 28 | __all__ = [] 29 | 30 | 31 | @override 32 | class Pixbuf(GdkPixbuf.Pixbuf): 33 | 34 | @classmethod 35 | def new_from_data( 36 | cls, data, colorspace, has_alpha, bits_per_sample, 37 | width, height, rowstride, 38 | destroy_fn=None, *destroy_fn_data): 39 | 40 | if destroy_fn is not None: 41 | w = PyGIDeprecationWarning("destroy_fn argument deprecated") 42 | warnings.warn(w, stacklevel=2) 43 | if destroy_fn_data: 44 | w = PyGIDeprecationWarning("destroy_fn_data argument deprecated") 45 | warnings.warn(w, stacklevel=2) 46 | 47 | data = GLib.Bytes.new(data) 48 | return cls.new_from_bytes( 49 | data, colorspace, has_alpha, bits_per_sample, 50 | width, height, rowstride) 51 | 52 | 53 | __all__.append('Pixbuf') 54 | -------------------------------------------------------------------------------- /gi/overrides/Pango.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python; py-indent-offset: 4 -*- 2 | # vim: tabstop=4 shiftwidth=4 expandtab 3 | # 4 | # Copyright (C) 2010 Paolo Borelli 5 | # 6 | # This library is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU Lesser General Public 8 | # License as published by the Free Software Foundation; either 9 | # version 2.1 of the License, or (at your option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public 17 | # License along with this library; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19 | # USA 20 | 21 | from ..overrides import override 22 | from ..module import get_introspection_module 23 | 24 | Pango = get_introspection_module('Pango') 25 | 26 | __all__ = [] 27 | 28 | 29 | class FontDescription(Pango.FontDescription): 30 | 31 | def __new__(cls, string=None): 32 | if string is not None: 33 | return Pango.font_description_from_string(string) 34 | else: 35 | return Pango.FontDescription.__new__(cls) 36 | 37 | def __init__(self, *args, **kwargs): 38 | return super(FontDescription, self).__init__() 39 | 40 | 41 | FontDescription = override(FontDescription) 42 | __all__.append('FontDescription') 43 | 44 | 45 | class Layout(Pango.Layout): 46 | 47 | def __new__(cls, context): 48 | return Pango.Layout.new(context) 49 | 50 | def set_markup(self, text, length=-1): 51 | super(Layout, self).set_markup(text, length) 52 | 53 | def set_text(self, text, length=-1): 54 | super(Layout, self).set_text(text, length) 55 | 56 | 57 | Layout = override(Layout) 58 | __all__.append('Layout') 59 | -------------------------------------------------------------------------------- /gi/overrides/meson.build: -------------------------------------------------------------------------------- 1 | python_sources = [ 2 | 'GLib.py', 3 | 'Gtk.py', 4 | 'Gdk.py', 5 | 'GdkPixbuf.py', 6 | 'GObject.py', 7 | 'Gio.py', 8 | 'GIMarshallingTests.py', 9 | 'Pango.py', 10 | '__init__.py'] 11 | 12 | python.install_sources(python_sources, 13 | subdir : join_paths('gi', 'overrides') 14 | ) 15 | -------------------------------------------------------------------------------- /gi/pygboxed.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * pygtk- Python bindings for the GTK toolkit. 3 | * Copyright (C) 1998-2003 James Henstridge 4 | * 2004-2008 Johan Dahlin 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGOBJECT_BOXED_H__ 21 | #define __PYGOBJECT_BOXED_H__ 22 | 23 | extern GQuark pygboxed_type_key; 24 | 25 | extern PyTypeObject PyGBoxed_Type; 26 | 27 | void pygi_register_gboxed (PyObject *dict, const gchar *class_name, 28 | GType boxed_type, PyTypeObject *type); 29 | PyObject * pygi_gboxed_new (GType boxed_type, gpointer boxed, 30 | gboolean copy_boxed, gboolean own_ref); 31 | 32 | int pygi_gboxed_register_types(PyObject *d); 33 | 34 | #endif /* __PYGOBJECT_BOXED_H__ */ 35 | -------------------------------------------------------------------------------- /gi/pygenum.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * pygtk- Python bindings for the GTK toolkit. 3 | * Copyright (C) 1998-2003 James Henstridge 4 | * 2004-2008 Johan Dahlin 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGOBJECT_ENUM_H__ 21 | #define __PYGOBJECT_ENUM_H__ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | extern GQuark pygenum_class_key; 28 | 29 | extern PyTypeObject *PyGEnum_Type; 30 | 31 | PyObject * pyg_enum_add (PyObject * module, 32 | const char * type_name, 33 | const char * strip_prefix, 34 | GType gtype); 35 | 36 | PyObject *pyg_enum_add_full (PyObject *module, 37 | const char *typename, 38 | GType gtype, 39 | GIEnumInfo *info); 40 | 41 | gboolean pyg_enum_register (PyTypeObject *enum_class, 42 | char *type_name); 43 | 44 | PyObject *pyg_enum_val_new (PyObject *pyclass, int value); 45 | 46 | PyObject * pyg_enum_from_gtype (GType gtype, 47 | int value); 48 | 49 | int pyg_enum_check_type (PyObject *obj, GType expected_type); 50 | 51 | gint pyg_enum_get_value (GType enum_type, PyObject *obj, gint *val); 52 | 53 | int pygi_enum_register_types(PyObject *mod); 54 | 55 | #endif /* __PYGOBJECT_ENUM_H__ */ 56 | -------------------------------------------------------------------------------- /gi/pygflags.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * pygtk- Python bindings for the GTK toolkit. 3 | * Copyright (C) 1998-2003 James Henstridge 4 | * 2004-2008 Johan Dahlin 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGOBJECT_FLAGS_H__ 21 | #define __PYGOBJECT_FLAGS_H__ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | extern GQuark pygflags_class_key; 28 | 29 | extern PyTypeObject *PyGFlags_Type; 30 | 31 | PyObject * pyg_flags_add (PyObject * module, 32 | const char * type_name, 33 | const char * strip_prefix, 34 | GType gtype); 35 | PyObject *pyg_flags_add_full (PyObject *module, 36 | const char *typename, 37 | GType gtype, 38 | GIFlagsInfo *info); 39 | gboolean pyg_flags_register (PyTypeObject *flags_class, 40 | char *type_name); 41 | PyObject *pyg_flags_val_new (PyObject *pyclass, guint value); 42 | PyObject *pyg_flags_from_gtype (GType gtype, 43 | guint value); 44 | 45 | gint pyg_flags_get_value (GType flag_type, PyObject *obj, guint *val); 46 | 47 | int pygi_flags_register_types(PyObject *d); 48 | 49 | #endif /* __PYGOBJECT_FLAGS_H__ */ 50 | -------------------------------------------------------------------------------- /gi/pygi-array.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2014 Simon Feltman 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_ARRAY_H__ 21 | #define __PYGI_ARRAY_H__ 22 | 23 | #include 24 | #include "pygi-cache.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | PyGIArgCache *pygi_arg_garray_new_from_info (GITypeInfo *type_info, 29 | GIArgInfo *arg_info, /* may be null */ 30 | GITransfer transfer, 31 | PyGIDirection direction, 32 | PyGICallableCache *callable_cache); 33 | 34 | PyGIArgCache *pygi_arg_garray_len_arg_setup (PyGIArgCache *arg_cache, 35 | GITypeInfo *type_info, 36 | PyGICallableCache *callable_cache, 37 | PyGIDirection direction, 38 | gssize arg_index, 39 | gssize *py_arg_index); 40 | 41 | G_END_DECLS 42 | 43 | #endif /*__PYGI_ARRAY_H__*/ 44 | -------------------------------------------------------------------------------- /gi/pygi-async.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2015 Christoph Reiter 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_ASYNC_H__ 21 | #define __PYGI_ASYNC_H__ 22 | 23 | #include "Python.h" 24 | 25 | #include "pygi-info.h" 26 | #include "pygi-cache.h" 27 | 28 | typedef struct { 29 | PyObject *func; 30 | PyObject *context; 31 | } PyGIAsyncCallback; 32 | 33 | typedef struct { 34 | PyObject_HEAD 35 | 36 | /* Everything for the instance, finish_func is kept in the class. */ 37 | PyGICallableInfo *finish_func; 38 | PyObject *loop; 39 | PyObject *cancellable; 40 | char _asyncio_future_blocking; 41 | PyObject *result; 42 | PyObject *exception; 43 | 44 | gboolean log_tb; 45 | 46 | GArray *callbacks; 47 | } PyGIAsync; 48 | 49 | 50 | int 51 | pygi_async_register_types (PyObject *d); 52 | 53 | void 54 | pygi_async_finish_cb (GObject *source_object, gpointer res, PyGIAsync *async); 55 | 56 | PyObject* 57 | pygi_async_new (PyObject *async_finish, PyObject *cancellable); 58 | 59 | #endif /* __PYGI_ASYNCRESULT_H__ */ 60 | -------------------------------------------------------------------------------- /gi/pygi-boxed.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2009 Simon van der Linden 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_BOXED_H__ 21 | #define __PYGI_BOXED_H__ 22 | 23 | #include 24 | #include 25 | 26 | #include "pygobject-internal.h" 27 | 28 | G_BEGIN_DECLS 29 | 30 | typedef struct _PyGIBoxed PyGIBoxed; 31 | 32 | extern PyTypeObject PyGIBoxed_Type; 33 | 34 | PyObject * pygi_boxed_new (PyTypeObject *type, 35 | gpointer boxed, 36 | gboolean free_on_dealloc, 37 | gsize allocated_slice); 38 | 39 | void * pygi_boxed_alloc (GIBaseInfo *info, gsize *size); 40 | 41 | void pygi_boxed_copy_in_place (PyGIBoxed *self); 42 | 43 | int pygi_boxed_register_types (PyObject *m); 44 | 45 | G_END_DECLS 46 | 47 | #endif /* __PYGI_BOXED_H__ */ 48 | -------------------------------------------------------------------------------- /gi/pygi-ccallback.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2011 John (J5) Palmieri , Red Hat, Inc. 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_CCLOSURE_H__ 21 | #define __PYGI_CCLOSURE_H__ 22 | 23 | #include 24 | 25 | #include "pygi-cache.h" 26 | 27 | G_BEGIN_DECLS 28 | 29 | typedef struct { 30 | PyObject_HEAD 31 | GCallback callback; 32 | GICallableInfo *info; 33 | gpointer user_data; 34 | GIScopeType scope; 35 | GDestroyNotify destroy_notify_func; 36 | PyGICCallbackCache *cache; 37 | vectorcallfunc vectorcall; 38 | } PyGICCallback; 39 | 40 | extern PyTypeObject PyGICCallback_Type; 41 | 42 | PyObject * _pygi_ccallback_new (GCallback callback, 43 | gpointer user_data, 44 | GIScopeType scope, 45 | GICallableInfo *info, 46 | GDestroyNotify destroy_notify); 47 | 48 | int pygi_ccallback_register_types (PyObject *m); 49 | 50 | G_END_DECLS 51 | 52 | #endif /* __PYGI_CCLOSURE_H__ */ 53 | -------------------------------------------------------------------------------- /gi/pygi-enum-marshal.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2014 Simon Feltman 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_ENUM_MARSHAL_H__ 21 | #define __PYGI_ENUM_MARSHAL_H__ 22 | 23 | #include 24 | #include "pygi-cache.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | PyGIArgCache *pygi_arg_enum_new_from_info (GITypeInfo *type_info, 29 | GIArgInfo *arg_info, /* may be null */ 30 | GITransfer transfer, 31 | PyGIDirection direction, 32 | GIEnumInfo *iface_info); 33 | 34 | PyGIArgCache *pygi_arg_flags_new_from_info (GITypeInfo *type_info, 35 | GIArgInfo *arg_info, /* may be null */ 36 | GITransfer transfer, 37 | PyGIDirection direction, 38 | GIFlagsInfo *iface_info); 39 | 40 | G_END_DECLS 41 | 42 | #endif /*__PYGI_ENUM_MARSHAL_H__*/ 43 | -------------------------------------------------------------------------------- /gi/pygi-error.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 1998-2003 James Henstridge 5 | * 2004-2008 Johan Dahlin 6 | * Copyright (C) 2014 Simon Feltman 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, see . 20 | */ 21 | 22 | #ifndef __PYGI_ERROR_H__ 23 | #define __PYGI_ERROR_H__ 24 | 25 | #include 26 | #include "pygi-cache.h" 27 | 28 | G_BEGIN_DECLS 29 | 30 | extern PyObject *PyGError; 31 | 32 | gboolean pygi_error_check (GError **error); 33 | 34 | PyObject* pygi_error_marshal_to_py (GError **error); 35 | 36 | gboolean pygi_error_marshal_from_py (PyObject *pyerr, 37 | GError **error); 38 | 39 | gboolean pygi_gerror_exception_check (GError **error); 40 | 41 | PyGIArgCache* pygi_arg_gerror_new_from_info (GITypeInfo *type_info, 42 | GIArgInfo *arg_info, /* may be null */ 43 | GITransfer transfer, 44 | PyGIDirection direction); 45 | 46 | int pygi_error_register_types (PyObject *module); 47 | 48 | G_END_DECLS 49 | 50 | #endif /*__PYGI_ERROR_H__*/ 51 | -------------------------------------------------------------------------------- /gi/pygi-fundamental.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2009 Simon van der Linden 5 | * Copyright (C) 2010 Tomeu Vizoso 6 | * Copyright (C) 2012 Bastian Winkler 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA 22 | */ 23 | 24 | #ifndef __PYGI_FUNDAMENTAL_H__ 25 | #define __PYGI_FUNDAMENTAL_H__ 26 | 27 | #include 28 | #include 29 | 30 | #include "pygobject-internal.h" 31 | #include "pygpointer.h" 32 | #include "pygi-type.h" 33 | 34 | G_BEGIN_DECLS 35 | 36 | extern PyTypeObject PyGIFundamental_Type; 37 | 38 | typedef struct { 39 | PyObject_HEAD 40 | PyObject* weaklist; 41 | gpointer instance; 42 | GType gtype; 43 | GIObjectInfoRefFunction ref_func; 44 | GIObjectInfoUnrefFunction unref_func; 45 | } PyGIFundamental; 46 | 47 | 48 | PyObject* pygi_fundamental_new (gpointer instance); 49 | 50 | void pygi_fundamental_ref (PyGIFundamental *self); 51 | void pygi_fundamental_unref (PyGIFundamental *self); 52 | 53 | GTypeInstance* pygi_fundamental_get (PyObject *self); 54 | 55 | int pygi_fundamental_register_types (PyObject *m); 56 | 57 | #define pygi_check_fundamental(info) \ 58 | (GI_IS_OBJECT_INFO (info) && \ 59 | gi_object_info_get_fundamental ((GIObjectInfo *)(info))) 60 | 61 | GTypeInstance* pygi_fundamental_from_value (const GValue *value); 62 | 63 | gboolean pygi_fundamental_set_value (GValue *value, GTypeInstance *instance); 64 | 65 | #endif /* __PYGI_FUNDAMENTAL_H__ */ 66 | -------------------------------------------------------------------------------- /gi/pygi-hashtable.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2013 Simon Feltman 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_HASHTABLE_H__ 21 | #define __PYGI_HASHTABLE_H__ 22 | 23 | #include "pygi-cache.h" 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | PyGIArgCache *pygi_arg_hash_table_new_from_info (GITypeInfo *type_info, 29 | GIArgInfo *arg_info, /* may be null */ 30 | GITransfer transfer, 31 | PyGIDirection direction, 32 | PyGICallableCache *callable_cache); 33 | 34 | G_END_DECLS 35 | 36 | #endif /*__PYGI_HASHTABLE_H__*/ 37 | -------------------------------------------------------------------------------- /gi/pygi-invoke-state-struct.h: -------------------------------------------------------------------------------- 1 | #ifndef __PYGI_INVOKE_STATE_STRUCT_H__ 2 | #define __PYGI_INVOKE_STATE_STRUCT_H__ 3 | 4 | #include 5 | #include 6 | 7 | G_BEGIN_DECLS 8 | 9 | typedef struct _PyGIInvokeArgState 10 | { 11 | /* Holds memory for the C value of arguments marshaled "to" or "from" Python. */ 12 | GIArgument arg_value; 13 | 14 | /* Holds pointers to values in arg_values or a caller allocated chunk of 15 | * memory via arg_pointer.v_pointer. 16 | */ 17 | GIArgument arg_pointer; 18 | 19 | /* Holds from_py marshaler cleanup data. */ 20 | gpointer arg_cleanup_data; 21 | 22 | /* Holds to_py marshaler cleanup data. */ 23 | gpointer to_py_arg_cleanup_data; 24 | } PyGIInvokeArgState; 25 | 26 | 27 | typedef struct _PyGIInvokeState 28 | { 29 | PyObject *py_in_args; 30 | gssize n_py_in_args; 31 | 32 | /* Number of arguments the ffi wrapped C function takes. Used as the exact 33 | * count for argument related arrays held in this struct. 34 | */ 35 | gssize n_args; 36 | 37 | /* List of arguments passed to ffi. Elements can point directly to values held in 38 | * arg_values for "in/from Python" or indirectly via arg_pointers for 39 | * "out/inout/to Python". In the latter case, the args[x].arg_pointer.v_pointer 40 | * member points to memory for the value storage. 41 | */ 42 | GIArgument **ffi_args; 43 | 44 | /* Array of size n_args containing per argument state */ 45 | PyGIInvokeArgState *args; 46 | 47 | /* Memory to receive the result of the C ffi function call. */ 48 | GIArgument return_arg; 49 | gpointer to_py_return_arg_cleanup_data; 50 | 51 | /* A GError exception which is indirectly bound into the last position of 52 | * the "args" array if the callable caches "throws" member is set. 53 | */ 54 | GError *error; 55 | 56 | gboolean failed; 57 | 58 | /* An awaitable to return for an async function that was called with 59 | * default arguments. 60 | */ 61 | PyObject *py_async; 62 | 63 | gpointer user_data; 64 | 65 | /* Function pointer to call with ffi. */ 66 | gpointer function_ptr; 67 | 68 | } PyGIInvokeState; 69 | 70 | G_END_DECLS 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /gi/pygi-invoke.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2005-2009 Johan Dahlin 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_INVOKE_H__ 21 | #define __PYGI_INVOKE_H__ 22 | 23 | #include 24 | #include 25 | 26 | #include "pygi-info.h" 27 | #include "pygi-invoke-state-struct.h" 28 | 29 | G_BEGIN_DECLS 30 | 31 | PyObject *pygi_invoke_c_callable (PyGIFunctionCache *function_cache, 32 | PyGIInvokeState *state, 33 | PyObject *const *py_args, size_t py_nargsf, 34 | PyObject *py_kwnames); 35 | PyObject *pygi_callable_info_invoke (PyGICallableInfo *self, 36 | PyObject *const *py_args, size_t py_nargsf, 37 | PyObject *kwnames); 38 | 39 | gboolean _pygi_invoke_arg_state_init (PyGIInvokeState *state); 40 | 41 | void _pygi_invoke_arg_state_free (PyGIInvokeState *state); 42 | 43 | G_END_DECLS 44 | 45 | #endif /* __PYGI_INVOKE_H__ */ 46 | -------------------------------------------------------------------------------- /gi/pygi-list.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2014 Simon Feltman 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_LIST_H__ 21 | #define __PYGI_LIST_H__ 22 | 23 | #include 24 | #include "pygi-cache.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | PyGIArgCache *pygi_arg_glist_new_from_info (GITypeInfo *type_info, 29 | GIArgInfo *arg_info, /* may be null */ 30 | GITransfer transfer, 31 | PyGIDirection direction, 32 | PyGICallableCache *callable_cache); 33 | 34 | /* Internally dispatches GList and GSList */ 35 | #define pygi_arg_gslist_new_from_info pygi_arg_glist_new_from_info 36 | 37 | G_END_DECLS 38 | 39 | #endif /*__PYGI_LIST_H__*/ 40 | -------------------------------------------------------------------------------- /gi/pygi-marshal-cleanup.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2011 John (J5) Palmieri , Red Hat, Inc. 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_MARSHAL_CLEANUP_H__ 21 | #define __PYGI_MARSHAL_CLEANUP_H__ 22 | 23 | #include "pygi-struct.h" 24 | #include "pygi-invoke-state-struct.h" 25 | #include "pygi-cache.h" 26 | 27 | G_BEGIN_DECLS 28 | 29 | void pygi_marshal_cleanup_args_from_py_marshal_success (PyGIInvokeState *state, 30 | PyGICallableCache *cache); 31 | void pygi_marshal_cleanup_args_from_py_parameter_fail (PyGIInvokeState *state, 32 | PyGICallableCache *cache, 33 | gssize failed_arg_index); 34 | 35 | void pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState *state, 36 | PyGICallableCache *cache); 37 | void pygi_marshal_cleanup_args_return_fail (PyGIInvokeState *state, 38 | PyGICallableCache *cache); 39 | void pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState *state, 40 | PyGICallableCache *cache, 41 | gssize failed_to_py_arg_index); 42 | G_END_DECLS 43 | 44 | #endif /* __PYGI_MARSHAL_CLEANUP_H__ */ 45 | -------------------------------------------------------------------------------- /gi/pygi-object.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2014 Simon Feltman 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_OBJECT_H__ 21 | #define __PYGI_OBJECT_H__ 22 | 23 | #include 24 | #include "pygi-cache.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | gboolean 29 | pygi_arg_gobject_out_arg_from_py (PyObject *py_arg, /* in */ 30 | GIArgument *arg, /* out */ 31 | GITransfer transfer); 32 | 33 | PyObject * 34 | pygi_arg_object_to_py_called_from_c (GIArgument *arg, 35 | GITransfer transfer); 36 | 37 | PyGIArgCache * 38 | pygi_arg_gobject_new_from_info (GITypeInfo *type_info, 39 | GIArgInfo *arg_info, /* may be null */ 40 | GITransfer transfer, 41 | PyGIDirection direction, 42 | GIRegisteredTypeInfo *iface_info, 43 | PyGICallableCache *callable_cache); 44 | 45 | G_END_DECLS 46 | 47 | #endif /*__PYGI_OBJECT_H__*/ 48 | -------------------------------------------------------------------------------- /gi/pygi-property.h: -------------------------------------------------------------------------------- 1 | /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ 2 | /* 3 | * Copyright (c) 2010 Collabora Ltd. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to 7 | * deal in the Software without restriction, including without limitation the 8 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | * sell copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __PYGI_PROPERTY_H__ 25 | #define __PYGI_PROPERTY_H__ 26 | 27 | #include 28 | #include 29 | 30 | #include "pygobject-internal.h" 31 | 32 | PyObject * 33 | pygi_get_property_value (PyGObject *instance, 34 | GParamSpec *pspec); 35 | 36 | PyObject * 37 | pygi_get_property_value_by_name (PyGObject *self, 38 | gchar *param_name); 39 | PyObject * 40 | pygi_call_do_get_property (PyObject *instance, 41 | GParamSpec *pspec); 42 | 43 | gint 44 | pygi_set_property_value (PyGObject *instance, 45 | GParamSpec *pspec, 46 | PyObject *py_value); 47 | 48 | #endif /* __PYGI_PROPERTY_H__ */ 49 | -------------------------------------------------------------------------------- /gi/pygi-repository.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2005-2009 Johan Dahlin 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_REPOSITORY_H__ 21 | #define __PYGI_REPOSITORY_H__ 22 | 23 | #include 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | typedef struct { 29 | PyObject_HEAD 30 | GIRepository *repository; 31 | } PyGIRepository; 32 | 33 | /* Private */ 34 | 35 | extern PyTypeObject PyGIRepository_Type; 36 | 37 | extern PyObject *PyGIRepositoryError; 38 | 39 | GIRepository* pygi_repository_get_default (void); 40 | 41 | int pygi_repository_register_types (PyObject *m); 42 | 43 | G_END_DECLS 44 | 45 | #endif /* __PYGI_REPOSITORY_H__ */ 46 | -------------------------------------------------------------------------------- /gi/pygi-resulttuple.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2015 Christoph Reiter 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_RESULTTUPLE_H__ 21 | #define __PYGI_RESULTTUPLE_H__ 22 | 23 | #include "Python.h" 24 | 25 | int 26 | pygi_resulttuple_register_types (PyObject *d); 27 | 28 | PyTypeObject * 29 | pygi_resulttuple_new_type (PyObject *tuple_names); 30 | 31 | PyObject* 32 | pygi_resulttuple_new (PyTypeObject *subclass, Py_ssize_t len); 33 | 34 | #endif /* __PYGI_RESULTTUPLE_H__ */ 35 | -------------------------------------------------------------------------------- /gi/pygi-signal-closure.h: -------------------------------------------------------------------------------- 1 | /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ 2 | /* 3 | * Copyright (c) 2011 Laszlo Pandy 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to 7 | * deal in the Software without restriction, including without limitation the 8 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | * sell copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __PYGI_SIGNAL_CLOSURE_H__ 25 | #define __PYGI_SIGNAL_CLOSURE_H__ 26 | 27 | #include 28 | #include 29 | 30 | #include "pygobject-internal.h" 31 | 32 | G_BEGIN_DECLS 33 | 34 | /* Private */ 35 | typedef struct _PyGISignalClosure 36 | { 37 | PyGClosure pyg_closure; 38 | GISignalInfo *signal_info; 39 | } PyGISignalClosure; 40 | 41 | GClosure * 42 | pygi_signal_closure_new (PyGObject *instance, 43 | GType g_type, 44 | const gchar *sig_name, 45 | PyObject *callback, 46 | PyObject *extra_args, 47 | PyObject *swap_data); 48 | 49 | G_END_DECLS 50 | 51 | #endif /* __PYGI_SIGNAL_CLOSURE_H__ */ 52 | -------------------------------------------------------------------------------- /gi/pygi-source.h: -------------------------------------------------------------------------------- 1 | /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ 2 | /* 3 | * Copyright (c) 2012 Canonical Ltd. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to 7 | * deal in the Software without restriction, including without limitation the 8 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | * sell copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __PYGI_SOURCE_H__ 25 | #define __PYGI_SOURCE_H__ 26 | 27 | PyObject *pygi_source_new (PyObject *self, PyObject *args); 28 | PyObject *pygi_source_set_callback (PyGObject *self, PyObject *args); 29 | 30 | #endif /* __PYGI_SOURCE_H__ */ 31 | 32 | -------------------------------------------------------------------------------- /gi/pygi-struct.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * Copyright (C) 2009 Simon van der Linden 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGI_STRUCT_H__ 21 | #define __PYGI_STRUCT_H__ 22 | 23 | #include 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | typedef struct { 29 | PyGPointer base; 30 | gboolean free_on_dealloc; 31 | } PyGIStruct; 32 | 33 | extern PyTypeObject PyGIStruct_Type; 34 | 35 | PyObject * 36 | pygi_struct_new (PyTypeObject *type, 37 | gpointer pointer, 38 | gboolean free_on_dealloc); 39 | 40 | PyObject * 41 | pygi_struct_new_from_g_type (GType g_type, 42 | gpointer pointer, 43 | gboolean free_on_dealloc); 44 | 45 | int pygi_struct_register_types (PyObject *m); 46 | 47 | G_END_DECLS 48 | 49 | #endif /* __PYGI_STRUCT_H__ */ 50 | -------------------------------------------------------------------------------- /gi/pygi-util.h: -------------------------------------------------------------------------------- 1 | #ifndef __PYGI_UTIL_H__ 2 | #define __PYGI_UTIL_H__ 3 | 4 | #include 5 | #include 6 | 7 | G_BEGIN_DECLS 8 | 9 | PyObject * pyg_integer_richcompare(PyObject *v, PyObject *w, int op); 10 | PyObject * pyg_ptr_richcompare(void* a, void *b, int op); 11 | const gchar * pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix); 12 | 13 | gboolean pygi_guint_from_pyssize (Py_ssize_t pyval, guint *result); 14 | 15 | #if PY_VERSION_HEX < 0x030900A4 16 | # define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0) 17 | #endif 18 | 19 | #if PY_VERSION_HEX >= 0x03080000 20 | # define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_BEGIN(op, dealloc) 21 | # define CPy_TRASHCAN_END(op) Py_TRASHCAN_END 22 | #else 23 | # define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_SAFE_BEGIN(op) 24 | # define CPy_TRASHCAN_END(op) Py_TRASHCAN_SAFE_END(op) 25 | #endif 26 | 27 | #define PYGI_DEFINE_TYPE(typename, symbol, csymbol) \ 28 | PyTypeObject symbol = { \ 29 | PyVarObject_HEAD_INIT(NULL, 0) \ 30 | typename, \ 31 | sizeof(csymbol) \ 32 | }; 33 | 34 | #define _PyGI_ERROR_PREFIX(format, ...) G_STMT_START { \ 35 | PyObject *py_error_prefix; \ 36 | py_error_prefix = PyUnicode_FromFormat(format, ## __VA_ARGS__); \ 37 | if (py_error_prefix != NULL) { \ 38 | PyObject *py_error_type, *py_error_value, *py_error_traceback; \ 39 | PyErr_Fetch(&py_error_type, &py_error_value, &py_error_traceback); \ 40 | if (PyUnicode_Check(py_error_value)) { \ 41 | PyObject *new; \ 42 | new = PyUnicode_Concat(py_error_prefix, py_error_value); \ 43 | Py_DECREF(py_error_value); \ 44 | if (new != NULL) { \ 45 | py_error_value = new; \ 46 | } \ 47 | } \ 48 | PyErr_Restore(py_error_type, py_error_value, py_error_traceback); \ 49 | Py_DECREF(py_error_prefix); \ 50 | } \ 51 | } G_STMT_END 52 | 53 | 54 | G_END_DECLS 55 | 56 | #endif /* __PYGI_UTIL_H__ */ 57 | -------------------------------------------------------------------------------- /gi/pygi-value.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * vim: tabstop=4 shiftwidth=4 expandtab 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, see . 16 | */ 17 | 18 | #ifndef __PYGI_VALUE_H__ 19 | #define __PYGI_VALUE_H__ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | GIArgument _pygi_argument_from_g_value(const GValue *value, 28 | GITypeInfo *type_info); 29 | 30 | int pyg_value_from_pyobject(GValue *value, PyObject *obj); 31 | int pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj); 32 | PyObject *pyg_value_as_pyobject(const GValue *value, gboolean copy_boxed); 33 | int pyg_param_gvalue_from_pyobject(GValue* value, 34 | PyObject* py_obj, 35 | const GParamSpec* pspec); 36 | PyObject *pyg_param_gvalue_as_pyobject(const GValue* gvalue, 37 | gboolean copy_boxed, 38 | const GParamSpec* pspec); 39 | PyObject *pyg_strv_from_gvalue(const GValue *value); 40 | int pyg_strv_to_gvalue(GValue *value, PyObject *obj); 41 | 42 | PyObject *pygi_value_to_py_basic_type (const GValue *value, 43 | GType fundamental, 44 | gboolean *handled); 45 | 46 | PyObject *pyg__gvalue_get(PyObject *module, PyObject *pygvalue); 47 | PyObject *pyg__gvalue_set(PyObject *module, PyObject *args); 48 | PyObject *pyg__gvalue_get_type(PyObject *module, PyObject *pygvalue); 49 | 50 | G_END_DECLS 51 | 52 | #endif /* __PYGI_VALUE_H__ */ 53 | -------------------------------------------------------------------------------- /gi/pyginterface.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * pygtk- Python bindings for the GTK toolkit. 3 | * Copyright (C) 1998-2003 James Henstridge 4 | * 2004-2008 Johan Dahlin 5 | * pyginterface.c: wrapper for the gobject library. 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, see . 19 | */ 20 | 21 | #ifndef __PYGOBJECT_INTERFACE_H__ 22 | #define __PYGOBJECT_INTERFACE_H__ 23 | 24 | extern GQuark pyginterface_type_key; 25 | extern GQuark pyginterface_info_key; 26 | 27 | extern PyTypeObject PyGInterface_Type; 28 | 29 | void pyg_register_interface(PyObject *dict, 30 | const gchar *class_name, 31 | GType gtype, 32 | PyTypeObject *type); 33 | const GInterfaceInfo * pyg_lookup_interface_info(GType gtype); 34 | void pyg_register_interface_info(GType gtype, const 35 | GInterfaceInfo *info); 36 | int pygi_interface_register_types(PyObject *d); 37 | 38 | #endif /* __PYGOBJECT_INTERFACE_H__ */ 39 | -------------------------------------------------------------------------------- /gi/pygobject-internal.h: -------------------------------------------------------------------------------- 1 | #ifndef _PYGOBJECT_INTERNAL_H_ 2 | #define _PYGOBJECT_INTERNAL_H_ 3 | 4 | #define _INSIDE_PYGOBJECT_ 5 | #include "pygobject.h" 6 | 7 | #endif /*_PYGOBJECT_INTERNAL_H_*/ 8 | -------------------------------------------------------------------------------- /gi/pygobject-object.h: -------------------------------------------------------------------------------- 1 | #ifndef _PYGOBJECT_OBJECT_H_ 2 | #define _PYGOBJECT_OBJECT_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "pygobject-internal.h" 8 | 9 | /* Data that belongs to the GObject instance, not the Python wrapper */ 10 | struct _PyGObjectData { 11 | PyTypeObject *type; /* wrapper type for this instance */ 12 | GSList *closures; 13 | }; 14 | 15 | extern GType PY_TYPE_OBJECT; 16 | extern GQuark pygobject_instance_data_key; 17 | extern GQuark pygobject_custom_key; 18 | extern GQuark pygobject_wrapper_key; 19 | extern GQuark pygobject_class_key; 20 | extern GQuark pygobject_class_init_key; 21 | 22 | extern PyTypeObject PyGObjectWeakRef_Type; 23 | extern PyTypeObject PyGPropsIter_Type; 24 | extern PyTypeObject PyGPropsDescr_Type; 25 | extern PyTypeObject PyGProps_Type; 26 | extern PyTypeObject PyGObject_Type; 27 | extern PyTypeObject *PyGObject_MetaType; 28 | 29 | static inline PyGObjectData * 30 | pyg_object_peek_inst_data(GObject *obj) 31 | { 32 | return ((PyGObjectData *) 33 | g_object_get_qdata(obj, pygobject_instance_data_key)); 34 | } 35 | 36 | void pygobject_register_class (PyObject *dict, 37 | const gchar *type_name, 38 | GType gtype, PyTypeObject *type, 39 | PyObject *bases); 40 | void pygobject_register_wrapper (PyObject *self); 41 | PyObject * pygobject_new (GObject *obj); 42 | PyObject * pygobject_new_full (GObject *obj, gboolean steal, gpointer g_class); 43 | void pygobject_sink (GObject *obj); 44 | PyTypeObject *pygobject_lookup_class (GType gtype); 45 | void pygobject_watch_closure (PyObject *self, GClosure *closure); 46 | int pyi_object_register_types (PyObject *d); 47 | void pygobject_ref_float(PyGObject *self); 48 | void pygobject_ref_sink(PyGObject *self); 49 | PyObject * pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs); 50 | 51 | GClosure * gclosure_from_pyfunc(PyGObject *object, PyObject *func); 52 | 53 | #endif /*_PYGOBJECT_OBJECT_H_*/ 54 | -------------------------------------------------------------------------------- /gi/pygoptioncontext.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * pyglib - Python bindings for GLib toolkit. 3 | * Copyright (C) 1998-2003 James Henstridge 4 | * 2004-2008 Johan Dahlin 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYG_OPTIONCONTEXT_H__ 21 | #define __PYG_OPTIONCONTEXT_H__ 22 | 23 | #include "pygoptiongroup.h" 24 | 25 | extern PyTypeObject PyGOptionContext_Type; 26 | 27 | typedef struct { 28 | PyObject_HEAD 29 | PyGOptionGroup *main_group; 30 | GOptionContext *context; 31 | } PyGOptionContext; 32 | 33 | PyObject* pyg_option_context_new(GOptionContext *context); 34 | 35 | int pygi_option_context_register_types(PyObject *d); 36 | 37 | #endif /* __PYG_OPTIONCONTEXT_H__ */ 38 | -------------------------------------------------------------------------------- /gi/pygoptiongroup.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * pyglib - Python bindings for GLib toolkit. 3 | * Copyright (C) 1998-2003 James Henstridge 4 | * 2004-2008 Johan Dahlin 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYG_OPTIONGROUP_H__ 21 | #define __PYG_OPTIONGROUP_H__ 22 | 23 | #include 24 | #include 25 | 26 | extern PyTypeObject PyGOptionGroup_Type; 27 | 28 | typedef struct { 29 | PyObject_HEAD 30 | GOptionGroup *group; 31 | gboolean other_owner, is_in_context; 32 | PyObject *callback; 33 | GSList *strings; /* all strings added with the entries, are freed on 34 | GOptionGroup.destroy() */ 35 | } PyGOptionGroup; 36 | 37 | PyObject* pyg_option_group_new(GOptionGroup *group); 38 | 39 | int pygi_option_group_register_types(PyObject *d); 40 | 41 | #endif /* __PYG_OPTIONGROUP_H__ */ 42 | 43 | 44 | -------------------------------------------------------------------------------- /gi/pygpointer.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * pygtk- Python bindings for the GTK toolkit. 3 | * Copyright (C) 1998-2003 James Henstridge 4 | * 2004-2008 Johan Dahlin 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYGOBJECT_POINTER_H__ 21 | #define __PYGOBJECT_POINTER_H__ 22 | 23 | #include 24 | 25 | extern GQuark pygpointer_class_key; 26 | 27 | extern PyTypeObject PyGPointer_Type; 28 | 29 | void pyg_register_pointer (PyObject *dict, const gchar *class_name, 30 | GType pointer_type, PyTypeObject *type); 31 | PyObject * pyg_pointer_new (GType pointer_type, gpointer pointer); 32 | 33 | int pygi_pointer_register_types(PyObject *d); 34 | 35 | #endif /* __PYGOBJECT_POINTER_H__ */ 36 | -------------------------------------------------------------------------------- /gi/pygspawn.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset: 4 -*- 2 | * pyglib - Python bindings for GLib toolkit. 3 | * Copyright (C) 1998-2003 James Henstridge 4 | * 2004-2008 Johan Dahlin 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __PYG_PID_H__ 21 | #define __PYG_PID_H__ 22 | 23 | PyObject * pyg_pid_new(GPid pid); 24 | int pygi_spawn_register_types(PyObject *d); 25 | 26 | PyObject * pyglib_spawn_async(PyObject *self, PyObject *args, PyObject *kwargs); 27 | 28 | 29 | #endif /* __PYG_PID_H__ */ 30 | 31 | -------------------------------------------------------------------------------- /gi/pygtkcompat.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | from gi import PyGIDeprecationWarning 4 | 5 | warnings.warn('gi.pygtkcompat is being deprecated in favor of using "pygtkcompat" directly.', 6 | PyGIDeprecationWarning) 7 | 8 | # pyflakes.ignore 9 | from pygtkcompat import enable 10 | 11 | 12 | __all__ = ['enable'] 13 | -------------------------------------------------------------------------------- /gi/repository/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python; py-indent-offset: 4 -*- 2 | # vim: tabstop=4 shiftwidth=4 expandtab 3 | # 4 | # Copyright (C) 2009 Johan Dahlin 5 | # 6 | # This library is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU Lesser General Public 8 | # License as published by the Free Software Foundation; either 9 | # version 2.1 of the License, or (at your option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public 17 | # License along with this library; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19 | # USA 20 | 21 | import sys 22 | 23 | from ..importer import DynamicImporter 24 | 25 | sys.meta_path.append(DynamicImporter('gi.repository')) 26 | 27 | del DynamicImporter 28 | del sys 29 | -------------------------------------------------------------------------------- /gi/repository/meson.build: -------------------------------------------------------------------------------- 1 | python_sources = ['__init__.py'] 2 | 3 | python.install_sources(python_sources, 4 | subdir : join_paths('gi', 'repository') 5 | ) 6 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('python', type : 'string', value : 'python3') 2 | option('pycairo', type : 'feature', value : 'auto', description : 'build with pycairo integration') 3 | option('tests', type : 'boolean', value : true, description : 'build unit tests') 4 | option('wheel', type : 'boolean', value : false, description : 'build for a Python wheel') 5 | -------------------------------------------------------------------------------- /pygobject-3.0.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | includedir=@includedir@ 4 | datarootdir=@datarootdir@ 5 | datadir=@datadir@ 6 | 7 | # you can use the --variable=pygobjectincludedir argument to 8 | # pkg-config to get this value. You might want to use this to 9 | # install additional headers. 10 | pygobjectincludedir=${includedir}/pygobject-3.0 11 | 12 | Name: PyGObject 13 | Description: Python bindings for GObject 14 | Requires: gobject-2.0 15 | Requires.private: libffi 16 | Version: @VERSION@ 17 | Cflags: -I${pygobjectincludedir} 18 | 19 | # overridesdir has now moved to the gi module 20 | # third parties can access it in a python script: 21 | # 22 | # import gi 23 | # installdir = gi._overridesdir 24 | # 25 | # the version of python you run the script from 26 | # will determine the actual overrides path 27 | -------------------------------------------------------------------------------- /pygtkcompat/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # pyflakes.ignore 3 | from .pygtkcompat import enable 4 | 5 | 6 | __all__ = ['enable'] 7 | -------------------------------------------------------------------------------- /pygtkcompat/meson.build: -------------------------------------------------------------------------------- 1 | python_sources = [ 2 | '__init__.py', 3 | 'pygtkcompat.py'] 4 | 5 | python.install_sources(python_sources, 6 | subdir : 'pygtkcompat' 7 | ) 8 | -------------------------------------------------------------------------------- /pygtkcompat/pygtkcompat.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python; py-indent-offset: 4 -*- 2 | # vim: tabstop=4 shiftwidth=4 expandtab 3 | # 4 | # Copyright (C) 2011-2012 Johan Dahlin 5 | # 6 | # This library is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU Lesser General Public 8 | # License as published by the Free Software Foundation; either 9 | # version 2.1 of the License, or (at your option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public 17 | # License along with this library; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19 | # USA 20 | 21 | """ 22 | PyGTK compatibility layer. 23 | 24 | DEPRECATED. DO NOT USE. 25 | 26 | """ 27 | 28 | 29 | def enable(): 30 | raise RuntimeError("pygtkcompat is deprecated in 3.48 and has been removed in 3.51, see https://pygobject.gnome.org/guide/porting.html for migration instructions") 31 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "PyGObject" 3 | description = "Python bindings for GObject Introspection" 4 | readme = 'README.rst' 5 | license = { file = 'COPYING' } 6 | authors = [ 7 | { name="James Henstridge", email="james@daa.com.au" } 8 | ] 9 | maintainers = [ 10 | { name="Christoph Reiter", email="creiter@src.gnome.org" }, 11 | { name="Arjan Molenaar", email="amolenaar@gnome.org" }, 12 | { name="Dan Yeaw", email="danyeaw@gnome.org" }, 13 | { name="Ignacio Casal Quinteiro", email="icq@gnome.org" }, 14 | ] 15 | classifiers = [ 16 | "Development Status :: 5 - Production/Stable", 17 | "Intended Audience :: Developers", 18 | "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)", 19 | "Operating System :: POSIX", 20 | "Operating System :: Microsoft :: Windows", 21 | "Programming Language :: C", 22 | "Programming Language :: Python", 23 | "Topic :: Software Development :: Libraries :: Python Modules", 24 | ] 25 | requires-python = ">=3.9" 26 | dependencies = [ 27 | "pycairo>=1.16" 28 | ] 29 | dynamic = ["version"] 30 | 31 | [project.urls] 32 | Homepage = "https://pygobject.gnome.org" 33 | Repository = "https://gitlab.gnome.org/GNOME/pygobject.git" 34 | Changelog = "https://gitlab.gnome.org/GNOME/pygobject/-/blob/main/NEWS" 35 | 36 | [tool.pdm.dev-dependencies] 37 | lint = [ 38 | "pre-commit", 39 | ] 40 | build = [ 41 | # Setuptools 74 removed msvccompiler, required by g-ir-scanner (<1.82.0) 42 | # See https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/515 43 | "setuptools<74", 44 | "meson-python", 45 | "ninja", 46 | "pycairo", 47 | ] 48 | test = [ 49 | "pytest", 50 | "pytest-cov", 51 | "flake8", 52 | ] 53 | docs = [ 54 | "sphinx", 55 | "pydata-sphinx-theme", 56 | "sphinx-copybutton>=0.5.2", 57 | ] 58 | 59 | [tool.pdm.options] 60 | install = [ 61 | "--no-isolation", 62 | "--config-setting=setup-args=-Dtests=true", 63 | "--config-setting=setup-args=-Dbuildtype=debug", 64 | "--config-setting=editable-verbose=true", 65 | ] 66 | build = [ 67 | "--no-wheel", 68 | "--config-setting=setup-args=-Dtests=true", 69 | ] 70 | 71 | [tool.meson-python.args] 72 | setup = ["-Dtests=false", "-Dwheel=true", "--wrap-mode=nofallback"] 73 | dist = ["--include-subprojects"] 74 | 75 | [tool.pytest.ini_options] 76 | testpaths = [ 77 | "tests", 78 | ] 79 | python_files = "test_*.py" 80 | addopts = [ 81 | "--import-mode=importlib", 82 | ] 83 | 84 | [build-system] 85 | build-backend = "mesonpy" 86 | requires = ["meson-python>=0.12.1", "pycairo>=1.16"] 87 | -------------------------------------------------------------------------------- /subprojects/glib.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory=glib 3 | url=https://gitlab.gnome.org/GNOME/glib.git 4 | push-url=git@gitlab.gnome.org:GNOME/glib.git 5 | revision=main 6 | depth=1 7 | -------------------------------------------------------------------------------- /subprojects/gobject-introspection-tests.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory=gobject-introspection-tests 3 | url=https://gitlab.gnome.org/GNOME/gobject-introspection-tests.git 4 | push-url=git@gitlab.gnome.org:GNOME/gobject-introspection-tests.git 5 | revision=33dca8ac76c4ccae76e462ce069853e7c12247c3 6 | depth=1 7 | -------------------------------------------------------------------------------- /subprojects/gobject-introspection.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory=gobject-introspection 3 | url=https://gitlab.gnome.org/GNOME/gobject-introspection.git 4 | push-url=git@gitlab.gnome.org:GNOME/gobject-introspection.git 5 | revision=main 6 | depth=1 7 | clone-recursive=true -------------------------------------------------------------------------------- /subprojects/libffi.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory=libffi 3 | url=https://gitlab.freedesktop.org/gstreamer/meson-ports/libffi.git 4 | revision=meson 5 | depth=1 6 | 7 | [provide] 8 | libffi = ffi_dep 9 | -------------------------------------------------------------------------------- /subprojects/packagefiles/pythoncapi-compat-dist.py: -------------------------------------------------------------------------------- 1 | # Remove the .git folder from pythoncapi-compat 2 | # Workaround for https://github.com/mesonbuild/meson/issues/11750 3 | 4 | import shutil 5 | import os 6 | from pathlib import Path 7 | 8 | shutil.rmtree(Path(os.environ["MESON_DIST_ROOT"]) / "subprojects" / "pythoncapi-compat" / ".git") 9 | -------------------------------------------------------------------------------- /subprojects/packagefiles/pythoncapi-compat-meson.diff: -------------------------------------------------------------------------------- 1 | diff --git a/meson.build b/meson.build 2 | new file mode 100644 3 | index 0000000..7c5f9fc 4 | --- /dev/null 5 | +++ b/meson.build 6 | @@ -0,0 +1,6 @@ 7 | +project( 8 | + 'pythoncapi-compat', 9 | + 'c' 10 | +) 11 | + 12 | +incdir = include_directories('.') 13 | -------------------------------------------------------------------------------- /subprojects/pycairo.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory=pycairo 3 | url=https://github.com/pygobject/pycairo.git 4 | revision=main 5 | depth=1 6 | -------------------------------------------------------------------------------- /subprojects/pythoncapi-compat.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory=pythoncapi-compat 3 | url=https://github.com/python/pythoncapi-compat.git 4 | revision=632d1aa0c4be6c67498d6b97630ddd7d7eb0f90a 5 | depth=1 6 | diff_files=pythoncapi-compat-meson.diff -------------------------------------------------------------------------------- /tests/gi/overrides/Regress.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python; py-indent-offset: 4 -*- 2 | # vim: tabstop=4 shiftwidth=4 expandtab 3 | # 4 | # Copyright (C) 2012 Martin Pitt 5 | # 6 | # This library is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU Lesser General Public 8 | # License as published by the Free Software Foundation; either 9 | # version 2.1 of the License, or (at your option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public 17 | # License along with this library; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19 | # USA 20 | 21 | from ..importer import get_introspection_module 22 | from ..overrides import override 23 | 24 | Regress = get_introspection_module('Regress') 25 | 26 | REGRESS_OVERRIDE = 42 27 | 28 | 29 | class Bitmask(Regress.Bitmask): 30 | """Replicate override of Bitmask (uint64), similar to GStreamer.""" 31 | 32 | def __init__(self, v): 33 | if not isinstance(v, int): 34 | raise TypeError("%s is not an int." % (type(v))) 35 | 36 | self.v = int(v) 37 | 38 | def __str__(self): 39 | return hex(self.v) 40 | 41 | def __eq__(self, other): 42 | return self.v == other 43 | 44 | 45 | Bitmask = override(Bitmask) 46 | 47 | __all__ = ['REGRESS_OVERRIDE', "Bitmask"] 48 | -------------------------------------------------------------------------------- /tests/gi/overrides/__init__.py: -------------------------------------------------------------------------------- 1 | from pkgutil import extend_path 2 | __path__ = extend_path(__path__, __name__) 3 | -------------------------------------------------------------------------------- /tests/meson.build: -------------------------------------------------------------------------------- 1 | gnome = import('gnome') 2 | 3 | host_system = host_machine.system() 4 | 5 | cc = meson.get_compiler('c') 6 | 7 | helper_sources = [ 8 | 'testhelpermodule.c', 9 | 'test-floating.c', 10 | 'test-thread.c', 11 | 'test-unknown.c'] 12 | 13 | helperext = python.extension_module('testhelper', helper_sources, 14 | dependencies : [python_dep, glib_dep, gobject_dep, pythoncapi_compat_dep], 15 | c_args: pyext_c_args + main_c_args, 16 | include_directories: include_directories(join_paths('..', 'gi')) 17 | ) 18 | 19 | schemas = gnome.compile_schemas(build_by_default: true) 20 | 21 | envdata = environment() 22 | if host_machine.system() == 'windows' 23 | envdata.prepend('PATH', join_paths(get_option('prefix'), get_option('bindir'))) 24 | endif 25 | 26 | test_deps = [ 27 | giext, 28 | helperext, 29 | schemas, 30 | gi_tests.get_variable('gimarshallingtests_typelib'), 31 | gi_tests.get_variable('regress_typelib'), 32 | gi_tests.get_variable('utility_typelib')] 33 | 34 | python_paths = [join_paths(meson.current_build_dir(), '..')] 35 | if pycairo_dep.found() and pycairo_dep.type_name() == 'internal' 36 | python_paths += [join_paths(meson.project_build_root(), 'subprojects', 'pycairo')] 37 | test_deps += [gicairoext] 38 | endif 39 | envdata.append('PYTHONPATH', python_paths) 40 | 41 | test('pygobject-test-suite', 42 | python, 43 | args: ['-m', 'pytest'], 44 | workdir: meson.project_source_root(), 45 | env: envdata, 46 | timeout: 90, 47 | depends: test_deps) 48 | -------------------------------------------------------------------------------- /tests/org.gnome.test.gschema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | true 11 | 12 | 13 | "Hello" 14 | 15 | 16 | (1,2) 17 | 18 | 19 | [1,2] 20 | 21 | 22 | 'banana' 23 | 24 | 25 | 26 | 123 27 | 28 | 29 | 30 | 31 | 32 | 42 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/test-thread.c: -------------------------------------------------------------------------------- 1 | #include "test-thread.h" 2 | 3 | enum 4 | { 5 | /* methods */ 6 | SIGNAL_EMIT_SIGNAL, 7 | SIGNAL_FROM_THREAD, 8 | LAST_SIGNAL 9 | }; 10 | 11 | static guint test_thread_signals[LAST_SIGNAL] = { 0 }; 12 | 13 | typedef enum { 14 | TEST_THREAD_A, 15 | TEST_THREAD_B 16 | } ThreadEnumType; 17 | 18 | static GType 19 | test_thread_enum_get_type (void) 20 | { 21 | static GType enum_type = 0; 22 | static GEnumValue enum_values[] = { 23 | {TEST_THREAD_A, "TEST_THREAD_A", "a as in apple"}, 24 | {0, NULL, NULL}, 25 | }; 26 | 27 | if (!enum_type) { 28 | enum_type = 29 | g_enum_register_static ("TestThreadEnum", enum_values); 30 | } 31 | return enum_type; 32 | } 33 | 34 | G_DEFINE_TYPE(TestThread, test_thread, G_TYPE_OBJECT); 35 | 36 | static G_NORETURN void 37 | other_thread_cb (TestThread *self) 38 | { 39 | g_signal_emit_by_name (self, "from-thread", 0, NULL); 40 | g_thread_exit (0); 41 | } 42 | 43 | static void 44 | test_thread_emit_signal (TestThread *self) 45 | { 46 | self->thread = g_thread_new ("t", (GThreadFunc)other_thread_cb, self); 47 | } 48 | 49 | static void test_thread_init (TestThread *self) {} 50 | static void test_thread_class_init (TestThreadClass *klass) 51 | { 52 | test_thread_signals[SIGNAL_EMIT_SIGNAL] = 53 | g_signal_new ("emit-signal", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 54 | G_STRUCT_OFFSET (TestThreadClass, emit_signal), 55 | NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); 56 | test_thread_signals[SIGNAL_FROM_THREAD] = 57 | g_signal_new ("from-thread", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 58 | G_STRUCT_OFFSET (TestThreadClass, from_thread), 59 | NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, 60 | test_thread_enum_get_type ()); 61 | 62 | klass->emit_signal = test_thread_emit_signal; 63 | } 64 | -------------------------------------------------------------------------------- /tests/test-thread.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct { 4 | GObject parent; 5 | GThread *thread; 6 | } TestThread; 7 | 8 | typedef struct { 9 | GObjectClass parent_class; 10 | void (*emit_signal) (TestThread *sink); 11 | void (*from_thread) (TestThread *sink); 12 | } TestThreadClass; 13 | 14 | GType test_thread_get_type (void); 15 | 16 | #define TEST_TYPE_THREAD (test_thread_get_type()) 17 | #define TEST_THREAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_THREAD, TestTHREAD)) 18 | #define TEST_THREAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_THREAD, TestTHREADClass)) 19 | #define TEST_IS_THREAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_THREAD)) 20 | #define TEST_IS_THREAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), TEST_TYPE_THREAD)) 21 | #define TEST_THREAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TEST_TYPE_THREAD, TestTHREADClass)) 22 | 23 | -------------------------------------------------------------------------------- /tests/test-unknown.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* TestUnknown */ 4 | 5 | typedef struct { 6 | GObject parent; 7 | } TestUnknown; 8 | 9 | typedef struct { 10 | GObjectClass parent_class; 11 | } TestUnknownClass; 12 | 13 | #define TEST_TYPE_UNKNOWN (test_unknown_get_type()) 14 | #define TEST_UNKNOWN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_UNKNOWN, TestUnknown)) 15 | #define TEST_UNKNOWN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_UNKNOWN, TestUnknownClass)) 16 | #define TEST_IS_UNKNOWN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_UNKNOWN)) 17 | #define TEST_IS_UNKNOWN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), TEST_TYPE_UNKNOWN)) 18 | #define TEST_UNKNOWN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TEST_TYPE_UNKNOWN, TestUnknownClass)) 19 | 20 | GType test_unknown_get_type (void); 21 | 22 | /* TestInterface */ 23 | typedef struct _TestInterface TestInterface; 24 | typedef struct _TestInterfaceIface TestInterfaceIface; 25 | 26 | struct _TestInterfaceIface 27 | { 28 | GTypeInterface g_iface; 29 | /* VTable */ 30 | void (* iface_method) (TestInterface *iface); 31 | }; 32 | 33 | #define TEST_TYPE_INTERFACE (test_interface_get_type ()) 34 | #define TEST_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_INTERFACE, TestInterface)) 35 | #define TEST_IS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_INTERFACE)) 36 | #define TEST_INTERFACE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_INTERFACE, TestInterfaceIface)) 37 | 38 | GType test_interface_get_type (void); 39 | 40 | void test_interface_iface_method (TestInterface *iface); 41 | -------------------------------------------------------------------------------- /tests/test_interface.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python -*- 2 | 3 | import unittest 4 | 5 | from gi.repository import GObject 6 | import testhelper 7 | 8 | 9 | GUnknown = GObject.type_from_name("TestUnknown") 10 | Unknown = GUnknown.pytype 11 | 12 | 13 | class MyUnknown(Unknown, testhelper.Interface): 14 | some_property = GObject.Property(type=str) 15 | 16 | def __init__(self): 17 | Unknown.__init__(self) 18 | self.called = False 19 | 20 | def do_iface_method(self): 21 | self.called = True 22 | Unknown.do_iface_method(self) 23 | 24 | 25 | GObject.type_register(MyUnknown) 26 | 27 | 28 | class MyObject(GObject.GObject, testhelper.Interface): 29 | some_property = GObject.Property(type=str) 30 | 31 | def __init__(self): 32 | GObject.GObject.__init__(self) 33 | self.called = False 34 | 35 | def do_iface_method(self): 36 | self.called = True 37 | 38 | 39 | GObject.type_register(MyObject) 40 | 41 | 42 | class TestIfaceImpl(unittest.TestCase): 43 | 44 | def test_reimplement_interface(self): 45 | m = MyUnknown() 46 | m.iface_method() 47 | self.assertEqual(m.called, True) 48 | 49 | def test_implement_interface(self): 50 | m = MyObject() 51 | m.iface_method() 52 | self.assertEqual(m.called, True) 53 | -------------------------------------------------------------------------------- /tests/test_mainloop.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python -*- 2 | 3 | import os 4 | import select 5 | import signal 6 | import unittest 7 | import warnings 8 | 9 | from gi.repository import GLib 10 | 11 | from .helper import capture_exceptions 12 | 13 | 14 | class TestMainLoop(unittest.TestCase): 15 | 16 | @unittest.skipUnless(hasattr(os, "fork"), "no os.fork available") 17 | def test_exception_handling(self): 18 | pipe_r, pipe_w = os.pipe() 19 | 20 | with warnings.catch_warnings(): 21 | warnings.filterwarnings("ignore", ".*may lead to deadlock.*") 22 | pid = os.fork() 23 | if pid == 0: 24 | os.close(pipe_w) 25 | select.select([pipe_r], [], []) 26 | os.close(pipe_r) 27 | os._exit(1) 28 | 29 | def child_died(pid, status, loop): 30 | loop.quit() 31 | raise Exception("deadbabe") 32 | 33 | loop = GLib.MainLoop() 34 | GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, child_died, loop) 35 | 36 | os.close(pipe_r) 37 | os.write(pipe_w, b"Y") 38 | os.close(pipe_w) 39 | 40 | with capture_exceptions() as exc: 41 | loop.run() 42 | 43 | assert len(exc) == 1 44 | assert exc[0].type is Exception 45 | assert exc[0].value.args[0] == "deadbabe" 46 | 47 | @unittest.skipUnless(hasattr(os, "fork"), "no os.fork available") 48 | @unittest.skipIf(os.environ.get("PYGI_TEST_GDB"), "SIGINT stops gdb") 49 | def test_sigint(self): 50 | r, w = os.pipe() 51 | with warnings.catch_warnings(): 52 | warnings.filterwarnings("ignore", ".*may lead to deadlock.*") 53 | pid = os.fork() 54 | if pid == 0: 55 | # wait for the parent process loop to start 56 | os.read(r, 1) 57 | os.close(r) 58 | 59 | os.kill(os.getppid(), signal.SIGINT) 60 | os._exit(0) 61 | 62 | def notify_child(): 63 | # tell the child that it can kill the parent 64 | os.write(w, b"X") 65 | os.close(w) 66 | 67 | GLib.idle_add(notify_child) 68 | loop = GLib.MainLoop() 69 | try: 70 | loop.run() 71 | self.fail('expected KeyboardInterrupt exception') 72 | except KeyboardInterrupt: 73 | pass 74 | self.assertFalse(loop.is_running()) 75 | os.waitpid(pid, 0) 76 | -------------------------------------------------------------------------------- /tests/test_overrides_gdkpixbuf.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Christoph Reiter 2 | # 3 | # This library is free software; you can redistribute it and/or 4 | # modify it under the terms of the GNU Lesser General Public 5 | # License as published by the Free Software Foundation; either 6 | # version 2.1 of the License, or (at your option) any later version. 7 | # 8 | # This library is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | # Lesser General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU Lesser General Public 14 | # License along with this library; if not, write to the Free Software 15 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 16 | # USA 17 | 18 | import pytest 19 | 20 | from gi import PyGIDeprecationWarning 21 | GdkPixbuf = pytest.importorskip("gi.repository.GdkPixbuf") 22 | 23 | 24 | def test_new_from_data(): 25 | width = 600 26 | height = 32769 27 | pixbuf = GdkPixbuf.Pixbuf.new( 28 | GdkPixbuf.Colorspace.RGB, True, 8, width, height) 29 | pixels = pixbuf.get_pixels() 30 | new_pixbuf = GdkPixbuf.Pixbuf.new_from_data( 31 | pixels, GdkPixbuf.Colorspace.RGB, True, 8, 32 | pixbuf.get_width(), pixbuf.get_height(), pixbuf.get_rowstride()) 33 | del pixbuf 34 | del pixels 35 | new_pixels = new_pixbuf.get_pixels() 36 | assert len(new_pixels) == width * height * 4 37 | 38 | 39 | def test_new_from_data_deprecated_args(): 40 | GdkPixbuf.Pixbuf.new_from_data(b"1234", 0, True, 8, 1, 1, 4) 41 | GdkPixbuf.Pixbuf.new_from_data(b"1234", 0, True, 8, 1, 1, 4, None) 42 | with (pytest.warns(PyGIDeprecationWarning, match=".*destroy_fn argument.*"), 43 | pytest.warns(PyGIDeprecationWarning, match=".*destroy_fn_data argument.*")): 44 | GdkPixbuf.Pixbuf.new_from_data( 45 | b"1234", 0, True, 8, 1, 1, 4, object(), object(), object()) 46 | -------------------------------------------------------------------------------- /tests/test_overrides_pango.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python; py-indent-offset: 4 -*- 2 | # vim: tabstop=4 shiftwidth=4 expandtab 3 | 4 | import unittest 5 | 6 | try: 7 | from gi.repository import Pango 8 | from gi.repository import PangoCairo 9 | except ImportError: 10 | Pango = None 11 | PangoCairo = None 12 | 13 | 14 | @unittest.skipUnless(Pango, 'Pango not available') 15 | class TestPango(unittest.TestCase): 16 | 17 | def test_default_font_description(self): 18 | desc = Pango.FontDescription() 19 | self.assertEqual(desc.get_variant(), Pango.Variant.NORMAL) 20 | 21 | def test_font_description(self): 22 | desc = Pango.FontDescription('monospace') 23 | self.assertEqual(desc.get_family(), 'monospace') 24 | self.assertEqual(desc.get_variant(), Pango.Variant.NORMAL) 25 | 26 | def test_layout(self): 27 | self.assertRaises(TypeError, Pango.Layout) 28 | context = Pango.Context() 29 | layout = Pango.Layout(context) 30 | self.assertEqual(layout.get_context(), context) 31 | 32 | layout.set_markup("Foobar") 33 | self.assertEqual(layout.get_text(), "Foobar") 34 | 35 | def test_layout_set_markup(self): 36 | context = Pango.Context() 37 | layout = Pango.Layout(context) 38 | layout.set_markup("abc") 39 | assert layout.get_text() == "abc" 40 | layout.set_markup("abc", -1) 41 | assert layout.get_text() == "abc" 42 | layout.set_markup("abc", 2) 43 | assert layout.get_text() == "ab" 44 | 45 | def test_layout_set_test(self): 46 | context = Pango.Context() 47 | layout = Pango.Layout(context) 48 | layout.set_text("abc") 49 | assert layout.get_text() == "abc" 50 | layout.set_text("abc", -1) 51 | assert layout.get_text() == "abc" 52 | layout.set_text("abc", 2) 53 | assert layout.get_text() == "ab" 54 | 55 | def test_break_keyword_escape(self): 56 | # https://bugzilla.gnome.org/show_bug.cgi?id=697363 57 | self.assertTrue(hasattr(Pango, 'break_')) 58 | self.assertTrue(Pango.break_ is not None) 59 | 60 | def test_context_get_metrics(self): 61 | # Test default "language" argument 62 | font_map = PangoCairo.font_map_get_default() 63 | context = font_map.create_context() 64 | desc = Pango.FontDescription('monospace') 65 | metrics1 = context.get_metrics(desc) 66 | metrics2 = context.get_metrics(desc, context.get_language()) 67 | self.assertEqual(metrics1.get_ascent(), metrics2.get_ascent()) 68 | -------------------------------------------------------------------------------- /tests/test_pycapi.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import ctypes 3 | from ctypes import c_void_p, py_object, c_char_p 4 | 5 | import gi 6 | from gi.repository import Gio 7 | 8 | 9 | def get_capi(): 10 | 11 | if not hasattr(ctypes, "pythonapi"): 12 | return 13 | 14 | class CAPI(ctypes.Structure): 15 | _fields_ = [ 16 | ("", c_void_p), 17 | ("", c_void_p), 18 | ("", c_void_p), 19 | ("newgobj", ctypes.PYFUNCTYPE(py_object, c_void_p)), 20 | ] 21 | 22 | api_obj = gi._gobject._PyGObject_API 23 | func_type = ctypes.PYFUNCTYPE(c_void_p, py_object, c_char_p) 24 | PyCapsule_GetPointer = func_type( 25 | ('PyCapsule_GetPointer', ctypes.pythonapi)) 26 | ptr = PyCapsule_GetPointer(api_obj, b"gobject._PyGObject_API") 27 | 28 | ptr = ctypes.cast(ptr, ctypes.POINTER(CAPI)) 29 | return ptr.contents 30 | 31 | 32 | API = get_capi() 33 | 34 | 35 | @unittest.skipUnless(API, "no pythonapi support") 36 | class TestPythonCAPI(unittest.TestCase): 37 | 38 | def test_newgobj(self): 39 | w = Gio.FileInfo() 40 | # XXX: ugh :/ 41 | ptr = int(repr(w).split()[-1].split(")")[0], 16) 42 | 43 | capi = get_capi() 44 | new_w = capi.newgobj(ptr) 45 | assert w == new_w 46 | -------------------------------------------------------------------------------- /tests/test_pygtkcompat.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python; py-indent-offset: 4 -*- 2 | # vim: tabstop=4 shiftwidth=4 expandtab 3 | 4 | import pytest 5 | 6 | import pygtkcompat 7 | 8 | 9 | def test_pygtkcompat(): 10 | with pytest.raises(RuntimeError, match="pygtkcompat is deprecated"): 11 | pygtkcompat.enable() 12 | -------------------------------------------------------------------------------- /tests/test_thread.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python -*- 2 | 3 | import unittest 4 | 5 | from gi.repository import GLib 6 | 7 | import testhelper 8 | 9 | 10 | class TestThread(unittest.TestCase): 11 | def setUp(self): 12 | self.main = GLib.MainLoop() 13 | self.called = False 14 | 15 | def from_thread_cb(self, test, enum): 16 | assert test == self.obj 17 | assert int(enum) == 0 18 | assert type(enum) is not int 19 | self.called = True 20 | GLib.idle_add(self.timeout_cb) 21 | 22 | def idle_cb(self): 23 | self.obj = testhelper.get_test_thread() 24 | self.obj.connect('from-thread', self.from_thread_cb) 25 | self.obj.emit('emit-signal') 26 | 27 | def test_extension_module(self): 28 | GLib.idle_add(self.idle_cb) 29 | GLib.timeout_add(2000, self.timeout_cb) 30 | self.main.run() 31 | self.assertTrue(self.called) 32 | 33 | def timeout_cb(self): 34 | self.main.quit() 35 | -------------------------------------------------------------------------------- /tests/test_unknown.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: Python -*- 2 | 3 | import unittest 4 | 5 | from gi.repository import GObject 6 | 7 | import testhelper 8 | 9 | 10 | TestInterface = GObject.GType.from_name('TestInterface') 11 | 12 | 13 | class TestUnknown(unittest.TestCase): 14 | def test_unknown_interface(self): 15 | obj = testhelper.get_unknown() 16 | TestUnknownGType = GObject.GType.from_name('TestUnknown') 17 | TestUnknown = GObject.new(TestUnknownGType).__class__ 18 | assert isinstance(obj, testhelper.Interface) 19 | assert isinstance(obj, TestUnknown) 20 | 21 | def test_property(self): 22 | obj = testhelper.get_unknown() 23 | self.assertEqual(obj.get_property('some-property'), None) 24 | obj.set_property('some-property', 'foo') 25 | 26 | def test_unknown_property(self): 27 | obj = testhelper.get_unknown() 28 | self.assertRaises(TypeError, obj.get_property, 'unknown') 29 | self.assertRaises(TypeError, obj.set_property, 'unknown', '1') 30 | -------------------------------------------------------------------------------- /tests/valgrind.supp: -------------------------------------------------------------------------------- 1 | # https://bugzilla.redhat.com/show_bug.cgi?id=1538073 2 | 3 | { 4 | 5 | Memcheck:Cond 6 | fun:__wcsnlen_sse4_1 7 | fun:wcsrtombs 8 | fun:wcstombs 9 | fun:wcstombs 10 | fun:encode_current_locale* 11 | } 12 | 13 | { 14 | 15 | Memcheck:Leak 16 | match-leak-kinds: definite 17 | fun:malloc 18 | fun:FcPatternObjectInsertElt 19 | fun:FcPatternObjectAddWithBinding 20 | } 21 | 22 | { 23 | 24 | Memcheck:Leak 25 | match-leak-kinds: definite 26 | fun:malloc 27 | fun:FcPatternCreate 28 | fun:FcParsePattern 29 | fun:FcEndElement 30 | } 31 | -------------------------------------------------------------------------------- /tools/mkmetadata.py: -------------------------------------------------------------------------------- 1 | import tomllib 2 | 3 | from pyproject_metadata import StandardMetadata 4 | 5 | 6 | def update_metadata_in(): 7 | with open("pyproject.toml", "rb") as fd: 8 | pyproject = tomllib.load(fd) 9 | 10 | metadata = StandardMetadata.from_pyproject(pyproject, allow_extra_keys=False) 11 | metadata.version = "@VERSION@" 12 | del metadata.readme 13 | del metadata.dependencies[:] 14 | 15 | with open("METADATA.in", "wb") as fd: 16 | fd.write(metadata.as_rfc822().as_bytes()) 17 | 18 | 19 | if __name__ == "__main__": 20 | update_metadata_in() 21 | --------------------------------------------------------------------------------