././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.clang-format0000664000000000000000000001266715074673150014735 0ustar00rootroot--- # Reference: https://clang.llvm.org/docs/ClangFormatStyleOptions.html Language: Cpp BasedOnStyle: LLVM AccessModifierOffset: -4 AlignAfterOpenBracket: Align AlignArrayOfStructures: None AlignConsecutiveAssignments: None AlignConsecutiveBitFields: AcrossEmptyLines AlignConsecutiveDeclarations: None AlignConsecutiveMacros: Consecutive AlignEscapedNewlines: Right AlignOperands: Align AlignTrailingComments: Kind: Always OverEmptyLines: 1 AllowAllArgumentsOnNextLine: false AllowAllParametersOfDeclarationOnNextLine: false AllowBreakBeforeNoexceptSpecifier: OnlyWithParen AllowShortBlocksOnASingleLine: Never AllowShortCaseExpressionOnASingleLine: true AllowShortCaseLabelsOnASingleLine: false AllowShortCompoundRequirementOnASingleLine: true AllowShortEnumsOnASingleLine: true AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: WithoutElse AllowShortLambdasOnASingleLine: All AllowShortLoopsOnASingleLine: true AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakBeforeMultilineStrings: true BinPackArguments: true BinPackParameters: true BitFieldColonSpacing: None BraceWrapping: AfterCaseLabel: false AfterClass: false AfterControlStatement: Never AfterEnum: false AfterExternBlock: false AfterFunction: true AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false BeforeCatch: true BeforeElse: false BeforeLambdaBody: false BeforeWhile: false IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true BreakAdjacentStringLiterals: true BreakAfterAttributes: Leave BreakAfterReturnType: AllDefinitions BreakBeforeBinaryOperators: NonAssignment BreakBeforeConceptDeclarations: Always BreakBeforeBraces: Custom BreakBeforeInlineASMColon: OnlyMultiline BreakBeforeTernaryOperators: true BreakConstructorInitializers: BeforeColon BreakFunctionDefinitionParameters: false BreakInheritanceList: BeforeColon BreakStringLiterals: true BreakTemplateDeclarations: Yes ColumnLimit: 79 CompactNamespaces: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: false DerivePointerAlignment: true EmptyLineAfterAccessModifier: Never EmptyLineBeforeAccessModifier: LogicalBlock FixNamespaceComments: true IncludeBlocks: Preserve IncludeCategories: - Regex: '^[<"]Python\.h[">]$' Priority: 2 CaseSensitive: true - Regex: '^<[[:alnum:]_/]+(\.h)?>$' Priority: 1 - Regex: '.*' Priority: 3 IndentAccessModifiers: false IndentCaseBlocks: false IndentCaseLabels: false IndentExternBlock: NoIndent IndentGotoLabels: false IndentPPDirectives: None IndentRequiresClause: true IndentWidth: 4 IndentWrappedFunctionNames: false InsertBraces: false InsertNewlineAtEOF: true InsertTrailingCommas: None KeepEmptyLines: AtEndOfFile: false AtStartOfBlock: false AtStartOfFile: false LambdaBodyIndentation: Signature LineEnding: DeriveLF MacroBlockBegin: '' MacroBlockEnd: '' Macros: - >- PyObject_HEAD_INIT(type)={ /* this is not exactly match with PyObject_HEAD_INIT in Python source code * but it is enough for clang-format */ { 0xFFFFFFFF }, (type) }, - >- PyVarObject_HEAD_INIT(type, size)={ { /* manually expand PyObject_HEAD_INIT(type) above * because clang-format do not support recursive expansion */ { 0xFFFFFFFF }, (type) }, (size) }, - PyMODINIT_FUNC=PyObject * - _PyGI_ENUM_BEGIN(name)={ - _PyGI_ENUM_ADD_VALUE(prefix, name)=(prefix##_##name); - _PyGI_ENUM_END=} MainIncludeChar: Quote MaxEmptyLinesToKeep: 2 NamespaceIndentation: None PackConstructorInitializers: NextLine PenaltyBreakAssignment: 20 PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakOpenParenthesis: 0 PenaltyBreakScopeResolution: 500 PenaltyBreakString: 1000 PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyIndentedWhitespace: 0 PenaltyReturnTypeOnItsOwnLine: 1000000000 PointerAlignment: Right PPIndentWidth: -1 QualifierAlignment: Custom QualifierOrder: [friend, static, inline, const, constexpr, volatile, type, restrict] ReferenceAlignment: Right ReflowComments: false RemoveBracesLLVM: false RemoveParentheses: MultipleParentheses RemoveSemicolon: true RequiresClausePosition: OwnLine RequiresExpressionIndentation: OuterScope SeparateDefinitionBlocks: Leave ShortNamespaceLines: 1 SkipMacroDefinitionBody: false SortIncludes: Never SortUsingDeclarations: LexicographicNumeric SpaceAfterCStyleCast: false SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true SpaceAroundPointerQualifiers: Default SpaceBeforeAssignmentOperators: true SpaceBeforeCaseColon: false SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true SpaceBeforeJsonColon: false SpaceBeforeParens: Always SpaceBeforeRangeBasedForLoopColon: true SpaceBeforeSquareBrackets: false SpaceInEmptyBlock: false SpacesBeforeTrailingComments: 2 SpacesInAngles: Never SpacesInContainerLiterals: true SpacesInLineCommentPrefix: Minimum: 1 Maximum: -1 SpacesInParens: Never SpacesInSquareBrackets: false Standard: c++11 StatementAttributeLikeMacros: StatementMacros: - PyObject_HEAD TableGenBreakInsideDAGArg: DontBreak TabWidth: 4 TypeNames: # Defined in Include/pytypedefs.h - PyModuleDef - PyModuleDef_Slot - PyMethodDef - PyGetSetDef - PyMemberDef - PyObject - PyLongObject - PyTypeObject - PyThreadState - PyInterpreterState UseTab: Never ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.coveragerc0000664000000000000000000000013315074673150014464 0ustar00rootroot[run] branch = True relative_files = True include = gi/* tests/* pygtkcompat/* ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.git-blame-ignore-revs0000664000000000000000000000012215074673150016441 0ustar00rootroot768e2330498f419bb3daf2548a167b112ef833c8 2cbe93875dd91bfc1d17284fe9bf86148f2ea80d ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitignore0000664000000000000000000000050615074673150014337 0ustar00rootroot.venv .mypy_cache *.bak *.lo *.o *.orig *.pyc *.rej *.so *.la *.tab.c *~ .*.sw[nop] *.gir *.typelib *.dll *.dylib .DS_STORE .idea .cache .pytest_cache /tmp/* /build/ /dist/ /pygobject.egg-info/ /docs/_build /PyGObject.egg-info/ /subprojects/*/ !/subprojects/packagefiles/ *.pyd *.dll.a .coverage pdm.lock .pdm-python public/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/Dockerfile0000664000000000000000000000163115074673150016252 0ustar00rootrootARG BASE=python:3 FROM docker.io/library/$BASE ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y \ build-essential \ ccache \ curl \ dbus \ gir1.2-freedesktop-dev \ gir1.2-girepository-3.0-dev \ gir1.2-gtk-3.0 \ gir1.2-gtk-4.0 \ git \ gobject-introspection \ lcov \ libbz2-dev \ libcairo2-dev \ libffi-dev \ libgirepository-2.0-dev \ libglib2.0-dev \ libgtk-3-0 \ libgtk-4-1 \ libreadline-dev \ libsqlite3-dev \ libssl-dev \ liblzma-dev \ ninja-build \ python3-pip \ sudo \ xauth \ xvfb \ && rm -rf /var/lib/apt/lists/* ARG HOST_USER_ID=5555 ENV HOST_USER_ID=${HOST_USER_ID} RUN useradd -u $HOST_USER_ID -ms /bin/bash user \ && echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers USER user WORKDIR /home/user ENV LANG=C.UTF-8 ENV CI=true ENV PATH="/usr/lib/ccache:${PATH}" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/README.rst0000664000000000000000000000116115074673150015745 0ustar00rootrootCI Docker Images ================ There are two images which are used for CI and which can be found here: https://gitlab.gnome.org/GNOME/pygobject/container_registry * `Dockerfile` - contains various Python versions and a commonly used distro. Run `run-docker.sh` to build it and run a shell in it. After that it can be pushed. * `Dockerfile.old` - 32bit using the oldest supported distro, to test with old stuff. Run `run-docker-old.sh` to build it and run a shell in it. After that it can be pushed. The scripts spawn a shell in the container with the source code mounted, so things can be tested locally if needed. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/build-sdists.sh0000775000000000000000000000063115074673150017224 0ustar00rootroot#!/bin/bash set -e python -m pip install --upgrade pdm python -m pdm build VERSION=$(grep version meson.build | head -1 | sed "s/^.*'\([0-9\.]*\)'.*$/\1/") if [[ "$VERSION" =~ ^[0-9]\.[0-9]*[13579]\. ]] then cat << EOF ****************** ATTENTION ****************** This is an UNstable release. Do NOT upload this release to PyPI. ****************** ATTENTION ****************** EOF fi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/coverage-docker.sh0000775000000000000000000000215415074673150017660 0ustar00rootroot#!/bin/bash set -e # Make the Windows paths match our current layout python ./.gitlab-ci/fixup-lcov-paths.py coverage/*.lcov # Remove external headers (except gi tests) for path in coverage/*.lcov; do lcov --config-file .gitlab-ci/lcovrc -r "${path}" '/usr/include/*' -o "${path}" lcov --config-file .gitlab-ci/lcovrc -r "${path}" '/usr/local/include/*' -o "${path}" lcov --config-file .gitlab-ci/lcovrc -r "${path}" '/opt/pypy/include/*' -o "${path}" lcov --config-file .gitlab-ci/lcovrc -r "${path}" '/home/*' -o "${path}" lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*/msys64/*' -o "${path}" lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*site-packages/*' -o "${path}" lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*subprojects/*' -o "${path}" lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*tmp-introspect*' -o "${path}" lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*/meson-private/*' -o "${path}" test -s "${path}" || rm "${path}" done genhtml --config-file .gitlab-ci/lcovrc \ coverage/*.lcov -o coverage/ cd coverage rm -f .coverage* rm -f ./*.lcov ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/fixup-lcov-paths.py0000664000000000000000000000226415074673150020046 0ustar00rootrootimport sys import os import re def main(argv): # Fix paths in lcov files generated on a Windows host so they match our # current source layout. paths = argv[1:] for path in paths: print(f"cov-fixup: {path}") with open(path, encoding="utf-8") as h: text = h.read() text = text.replace("\\\\", "/").replace("\\", "/") new_root = os.getcwd() def make_abs(m): p = m.group(1) if p.startswith("C:/"): p = p.replace("C:/", "/c/") if not p.startswith("/"): p = os.path.join(new_root, p) return "SF:" + p text = re.sub(r"SF:(.*?)$", make_abs, text, 0, re.MULTILINE) candidate = None for old_root in set(re.findall(r":(.*?)/gi/.*?$", text, re.MULTILINE)): if candidate is None or len(old_root) < len(candidate): candidate = old_root if candidate: print(f"replacing {candidate} with {new_root}") text = text.replace(candidate, new_root) with open(path, "w", encoding="utf-8") as h: h.write(text) if __name__ == "__main__": sys.exit(main(sys.argv)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/lcovrc0000664000000000000000000000122715074673150015474 0ustar00rootroot# lcov and genhtml configuration # See http://ltp.sourceforge.net/coverage/lcov/lcovrc.5.php # Always enable branch coverage branch_coverage = 1 stop_on_error = 0 ignore_errors = inconsistent,unused,empty check_data_consistency = 0 # Exclude precondition assertions, as we can never reasonably get full branch # coverage of them, as they should never normally fail. # See https://github.com/linux-test-project/lcov/issues/44 lcov_excl_br_line = LCOV_EXCL_BR_LINE|g_return_if_fail|g_return_val_if_fail|g_assert|g_assert_ # Similarly for unreachable assertions. lcov_excl_line = LCOV_EXCL_LINE|g_return_if_reached|g_return_val_if_reached|g_assert_not_reached ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/org.gnome.PyGObject.Devel.yaml0000664000000000000000000000173715074673150021731 0ustar00rootrootapp-id: org.gnome.PyGObject.Devel runtime: org.gnome.Sdk runtime-version: master sdk: org.gnome.Sdk build-options: build-args: - '--share=network' test-args: - '--socket=x11' - '--share=network' env: PYTEST_ADDOPTS: '-vs --cov' TEST_GTK_VERSION: '3.0' modules: - name: dependencies buildsystem: simple build-commands: - python3 --version - echo "GTK VERSION ${TEST_GTK_VERSION}" - pip3 install --prefix=${FLATPAK_DEST} pycairo pytest pytest-cov - name: pygobject buildsystem: meson builddir: true config-opts: - '-Dtests=true' sources: - type: dir path: .. run-tests: true test-rule: '' test-commands: # Remove vala-nightly, since it contains an incompatible version of libdbus - >- LD_LIBRARY_PATH=$(echo $LD_LIBRARY_PATH | sed s/vala-nightly/foobar/) meson test -v - cd .. && python3 -m coverage lcov -o "coverage/flatpak-${TEST_GTK_VERSION}.py.lcov" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/run-docker-runtime.sh0000775000000000000000000000063115074673150020350 0ustar00rootroot#!/bin/bash set -e TAG="registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master" sudo docker pull "${TAG}" sudo docker run --privileged --rm --security-opt label=disable \ --volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \ --tty --interactive "${TAG}" xvfb-run -a flatpak run --filesystem=host \ --share=network --socket=x11 --devel --command=bash org.gnome.Sdk//master ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/run-docker.sh0000775000000000000000000000051315074673150016666 0ustar00rootroot#!/bin/bash set -e TAG="registry.gitlab.gnome.org/gnome/pygobject/main:v25" sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \ --file "Dockerfile" . sudo docker run --rm --security-opt label=disable \ --volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \ --tty --interactive "${TAG}" bash ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/test-docker.sh0000775000000000000000000000257715074673150017055 0ustar00rootroot#!/bin/bash set -e python --version SOURCE_DIR="$(pwd)" COV_DIR="${SOURCE_DIR}/coverage" COV_KEY="${CI_JOB_NAME_SLUG}" JUNIT_XML="${SOURCE_DIR}/test-results.xml" CFLAGS="-coverage -ftest-coverage -fprofile-arcs -Werror" MALLOC_CHECK_=3 MALLOC_PERTURB_=$((RANDOM % 255 + 1)) G_SLICE="debug-blocks" COVERAGE_FILE="${COV_DIR}/.coverage.${COV_KEY}" CCACHE_BASEDIR="$(pwd)" CCACHE_DIR="${CCACHE_BASEDIR}/_ccache" export CFLAGS MALLOC_CHECK_ MALLOC_PERTURB_ G_SLICE COVERAGE_FILE \ CCACHE_BASEDIR CCACHE_DIR # https://docs.python.org/3/using/cmdline.html#envvar-PYTHONDEVMODE export PYTHONDEVMODE=1 export MESONPY_EDITABLE_VERBOSE=1 mkdir -p "${CCACHE_DIR}" mkdir -p "${COV_DIR}" python -m venv /tmp/venv # shellcheck disable=SC1091 source /tmp/venv/bin/activate python -m pip install --upgrade pip python -m pip install meson meson-python pycairo pytest pytest-cov # BUILD & TEST python -m pip install --config-settings=setup-args="-Dtests=true" --no-build-isolation --editable . # TEST lcov --config-file .gitlab-ci/lcovrc --directory . --capture --initial --output-file \ "${COV_DIR}/${CI_JOB_NAME_SLUG}-baseline.lcov" xvfb-run -a python -m pytest -vs --cov --junit-xml="${JUNIT_XML}" python -m coverage lcov -o "${COV_DIR}/${COV_KEY}.py.lcov" # COLLECT GCOV COVERAGE lcov --config-file .gitlab-ci/lcovrc --directory . --capture --output-file \ "${COV_DIR}/${CI_JOB_NAME_SLUG}.lcov" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/test-flatpak.sh0000775000000000000000000000051715074673150017220 0ustar00rootroot#!/bin/bash set -e sed -i "/TEST_GTK_VERSION:/s/'.*'/'${TEST_GTK_VERSION:-3.0}'/" .gitlab-ci/org.gnome.PyGObject.Devel.yaml xvfb-run -a flatpak-builder --user --keep-build-dirs --verbose --disable-rofiles-fuse flatpak_ci .gitlab-ci/org.gnome.PyGObject.Devel.yaml mv .flatpak-builder/build/pygobject/coverage . chmod -R 777 coverage ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci/test-msys2.sh0000775000000000000000000000322215074673150016647 0ustar00rootroot#!/bin/bash set -e pacman --noconfirm -Suy pacman --noconfirm -S --needed \ "${MINGW_PACKAGE_PREFIX}"-ccache \ "${MINGW_PACKAGE_PREFIX}"-glib2 \ "${MINGW_PACKAGE_PREFIX}"-gobject-introspection \ "${MINGW_PACKAGE_PREFIX}"-gtk3 \ "${MINGW_PACKAGE_PREFIX}"-libffi \ "${MINGW_PACKAGE_PREFIX}"-meson \ "${MINGW_PACKAGE_PREFIX}"-ninja \ "${MINGW_PACKAGE_PREFIX}"-python \ "${MINGW_PACKAGE_PREFIX}"-python-cairo \ "${MINGW_PACKAGE_PREFIX}"-python-pip \ "${MINGW_PACKAGE_PREFIX}"-python-pytest \ "${MINGW_PACKAGE_PREFIX}"-python-pytest-cov \ "${MINGW_PACKAGE_PREFIX}"-toolchain \ git \ lcov # ccache setup export PATH="$MSYSTEM/lib/ccache/bin:$PATH" mkdir -p _ccache CCACHE_BASEDIR="$(pwd)" export CCACHE_BASEDIR CCACHE_DIR="${CCACHE_BASEDIR}/_ccache" export CCACHE_DIR # coverage setup COV_DIR="$(pwd)/coverage" COV_KEY="${CI_JOB_NAME_SLUG}" mkdir -p "${COV_DIR}" export COVERAGE_FILE="${COV_DIR}/.coverage.${COV_KEY}" # Test results JUNIT_XML="test-results.xml" # https://docs.python.org/3/using/cmdline.html#envvar-PYTHONDEVMODE export PYTHONDEVMODE=1 MSYSTEM='' CFLAGS="-coverage -ftest-coverage -fprofile-arcs -Werror" meson setup _build lcov \ --config-file .gitlab-ci/lcovrc \ --directory "$(pwd)" --capture --initial --output-file \ "${COV_DIR}/${COV_KEY}-baseline.lcov" MSYSTEM='' PYTEST_ADDOPTS="--cov -sv --junit-xml=${JUNIT_XML}" meson test --suite pygobject --timeout-multiplier 4 -C _build -v MSYSTEM='' python -m coverage lcov -o "${COV_DIR}/${COV_KEY}.py.lcov" lcov \ --config-file .gitlab-ci/lcovrc \ --directory "$(pwd)" --capture --output-file \ "${COV_DIR}/${COV_KEY}.lcov" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.gitlab-ci.yml0000664000000000000000000001155515074673150015011 0ustar00rootrootspec: inputs: python_versions: type: array default: - "python-3.9" - "python-3.10" - "python-3.11" - "python-3.12" - "python-3.13" - "python-3.14.0rc2" - "pypy-3.11" default_version: default: "python-3.13" build_images: options: ["never", "always"] default: "never" --- include: - component: gitlab.gnome.org/GNOME/citemplates/release-service@master inputs: dist-job-name: "sdist" tarball-artifact-path: "${TARBALL_ARTIFACT_PATH}" stages: - images - pre-commit - build - coverage - documentation - build-release - deploy variables: REGISTRY: registry.gitlab.gnome.org/gnome/pygobject CI_IMAGE: registry.gitlab.gnome.org/gnome/pygobject/ci TARBALL_ARTIFACT_PATH: "dist/${CI_PROJECT_NAME}-${CI_COMMIT_TAG}.tar.gz" # Normal build whenever Dockerfile has not changed default: interruptible: true cache: paths: - _ccache/ # Build images if Dockerfile has changed build-image: stage: images image: quay.io/buildah/stable:latest rules: - if: $CI_PROJECT_NAMESPACE == "GNOME" && $CI_COMMIT_BRANCH == "main" changes: - ".gitlab-ci.yml" - ".gitlab-ci/Dockerfile" when: always - when: $[[ inputs.build_images ]] variables: STORAGE_DRIVER: vfs BUILDAH_ISOLATION: chroot parallel: matrix: - IMAGE_TAG: $[[ inputs.python_versions ]] script: - echo "$CI_REGISTRY_PASSWORD" | buildah login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin - IMG="$CI_IMAGE:$IMAGE_TAG" - echo "Building image '$IMG'" - buildah build --build-arg BASE=${IMAGE_TAG/-/:} -t $IMG -f Dockerfile .gitlab-ci - buildah push $IMG cache: paths: pre-commit: stage: pre-commit image: $CI_IMAGE:$[[ inputs.default_version ]] variables: XDG_CACHE_HOME: "$CI_PROJECT_DIR/.cache" script: - git config --global --add safe.directory "$CI_PROJECT_DIR" - python -m pip install -q --no-warn-script-location pre-commit - python -m pre_commit run --verbose --all-files artifacts: when: on_failure paths: - .cache/pre-commit/pre-commit.log cache: paths: - .cache linux: stage: build image: $CI_IMAGE:$IMAGE_TAG parallel: matrix: - IMAGE_TAG: $[[ inputs.python_versions ]] TEST_GTK_VERSION: "3.0" - IMAGE_TAG: $[[ inputs.default_version ]] TEST_GTK_VERSION: "4.0" artifacts: when: always paths: - coverage/ - test-results.xml reports: junit: test-results.xml script: - bash -x ./.gitlab-ci/test-docker.sh windows: stage: build tags: - win32-ps parallel: matrix: - MSYSTEM: - "MINGW32" - "MINGW64" artifacts: when: always paths: - coverage/ - _build/meson-logs - test-results.xml reports: junit: test-results.xml script: - $env:CHERE_INVOKING = 'yes' - C:\msys64\usr\bin\pacman --noconfirm -Syyuu - C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/test-msys2.sh" gnome-master: stage: build image: quay.io/gnome_infrastructure/gnome-runtime-images:gnome-master tags: - flatpak parallel: matrix: - TEST_GTK_VERSION: - "3.0" - "4.0" artifacts: paths: - coverage/ script: - bash -x ./.gitlab-ci/test-flatpak.sh linux-pdm: stage: build image: $CI_IMAGE:$[[ inputs.default_version ]] variables: TEST_GTK_VERSION: "3.0" before_script: - python -m pip install "pdm!=2.17.3" - python -m pdm install -v script: - xvfb-run -a python -m pdm run pytest minimal-meson: allow_failure: true stage: build image: quay.io/fedora/fedora:40 before_script: - dnf install --assumeyes gcc meson git flex bison diffutils python3-devel python3-pytest gobject-introspection-devel script: - meson setup _build - meson compile -C _build - PYTEST_ADDOPTS="-sv -k 'not test_cairo'" meson test -C _build --suite pygobject --verbose coverage: stage: coverage image: $CI_IMAGE:$[[ inputs.default_version ]] artifacts: paths: - coverage/ script: - bash -x ./.gitlab-ci/coverage-docker.sh coverage: '/^\s+lines\.+:\s+([\d.]+\%)\s+/' pages: stage: documentation image: $CI_IMAGE:$[[ inputs.default_version ]] dependencies: - coverage before_script: - python -m pip install "pdm!=2.17.3" - python -m pdm install -v script: - python -m pdm run sphinx-build -T -E -W --keep-going -b html -d _build/doctrees -D language=en docs/ public - mv coverage/ public/ artifacts: paths: - public expire_in: 30 days rules: - if: $CI_COMMIT_BRANCH == "main" - if: $CI_COMMIT_TAG sdist: stage: build-release image: $CI_IMAGE:$[[ inputs.default_version ]] artifacts: paths: - dist/ script: - git config --global --add safe.directory "$CI_PROJECT_DIR" - bash -x ./.gitlab-ci/build-sdists.sh ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/.pre-commit-config.yaml0000664000000000000000000000127715074673150016636 0ustar00rootroot# This is a configuration file for the pre-commit tool. # Documentation is available at https://pre-commit.com/#plugins repos: - repo: https://github.com/shellcheck-py/shellcheck-py rev: v0.10.0.1 hooks: - id: shellcheck - repo: https://github.com/astral-sh/ruff-pre-commit rev: 'v0.12.4' hooks: - id: ruff args: [--fix, --preview] - id: ruff-format types_or: [python, spec] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: trailing-whitespace - id: check-toml - id: check-yaml args: [--allow-multiple-documents] - repo: https://github.com/pre-commit/mirrors-clang-format rev: v20.1.8 hooks: - id: clang-format ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/COPYING0000664000000000000000000006347515074673150013420 0ustar00rootroot GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/METADATA.in0000664000000000000000000000167615074673150014070 0ustar00rootrootMetadata-Version: 2.4 Name: PyGObject Version: @VERSION@ Summary: Python bindings for GObject Introspection Author-Email: James Henstridge Maintainer-Email: Christoph Reiter , Arjan Molenaar , Dan Yeaw , Ignacio Casal Quinteiro License-Expression: LGPL-2.1-or-later License-File: COPYING Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Operating System :: POSIX Classifier: Operating System :: Microsoft :: Windows Classifier: Programming Language :: C Classifier: Programming Language :: Python Classifier: Topic :: Software Development :: Libraries :: Python Modules Project-URL: Homepage, https://pygobject.gnome.org Project-URL: Repository, https://gitlab.gnome.org/GNOME/pygobject.git Project-URL: Changelog, https://gitlab.gnome.org/GNOME/pygobject/-/blob/main/NEWS Requires-Python: >=3.9 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/NEWS0000664000000000000000000055726415074673150013070 0ustar00rootroot3.54.5 - 2025-10-18 ------------------- * Backport: GLib 2.86/GioUnix compatibility :mr:`461` 3.54.3 - 2025-09-21 ------------------- * Do not skip symbols both in Gio and in platform specific :mr:`452` 3.54.2 - 2025-09-13 ------------------- * Prefix platform specific symbols with platform name :mr:`451` 3.54.1 - 2025-09-12 ------------------- * Excempt GioPlatform namespaces from required version check :mr:`450` 3.54.0 - 2025-09-06 ------------------- * Fix compatibility with Python 3.14 :mr:`433` * Add platform specific symbols back to Gio module :mr:`445` * Include docs from old GNOME wiki :mr:`441` * Add override for `GLib.MainContext.query()` :mr:`446` * Fix optional inout parameter marshalling :mr:`447` 3.53.0 - 2025-08-27 ------------------- * Drop Python upper limit :mr:`418` * Add `__enum|flags_values__` back to GEnum and GFlags :mr:`420` * Fix asyncio event loop selector with Python 3.13 :mr:`421` * Support `Gtk.Template` on sub-classed Python classes :mr:`199` * Use GI Repository singleton if GLib >= 2.85 :mr:`427` * Expose finish_func on function info to determine if a function can be used as awaitable :mr:`428` * Documentation updates :mr:`424` :mr:`426` :mr:`429` :mr:`430` * `ParamSpec` objects now return the expected enum type :mr:`432` * Fix `Gio.ActionMap` override for `Gio.Application` :mr:`435` * Fix regression for functions with multiple callbacks :mr:`436` :mr:`437` * Cleanup: callable argument cache :mr:`438` * Format Python and C code :mr:`386` * Fix compatibility with GLib 2.84 :mr:`443` * (chore) clean up array cache code :mr:`440` 3.52.3 - 2025-03-16 ------------------- * Remove invalid error check for gi_constant_info_get_value :mr:`417` 3.52.2 - 2025-03-12 ------------------- * Use legacy license definition in pyproject.toml :mr:`416` 3.52.1 - 2025-03-09 ------------------- Fixed release pipeline 3.52.0 - 2025-03-09 ------------------- From this version onwards girepository-2.0 is used for introspection. This means that you'll need GLib >= 2.80. * Fix invocation of async constructors :mr:`414` * Use keyword module to find out if function or parameter is a keyword :mr:`412` * Revert change that should prevent a memory leak in DBus invocation; this is now solved in GLib :mr:`404` * Make sure function/method signature parameters have unique names :mr:`410` * Support registering new enum and flags types from Python :mr:`400` * Only release a python-compatible tarball :mr:`401` :mr:`411` * GObject-based classes can now override the (`do`)`dispose` method :mr:`197` * Add mappings to Cairo foreign types `cairo_font_face_t` / `cairo_scaled_font_t` :mr:`236` :mr:`403` 3.51.0 - 2025-02-01 (pre-release) --------------------------------- From this version onwards girepository-2.0 is used for introspection. This means that you'll need GLib >= 2.80. Note: Only enumerations and flags that have a GType associated will have the GEnum extra properties, such as `value_nicks` and `value_names`. * Use `girepository` 2.0 for GIR mappings :mr:`320` * Use Python's vectorcall protocol internally :mr:`346` :mr:`356` * Improved API for asyncio :mr:`352` :mr:`353` * Deprecation: The pygtkcompat module now throws an exception when imported :mr:`261` * Method signatures are exposed from PyGObject now! :mr:`341` * Use [gobject-introspection-tests](https://gitlab.gnome.org/GNOME/gobject-introspection-tests) for testing :mr:`349` * Convenience API for Gdk.RGBA got GDK 4, similar to GDK 3 :mr:`351` * Added a [pre-commit](https://pre-commit.com/) configuration :mr:`383` * Use standard `enum` module for enums and flags in PyGObject :mr:`394` * Added an option to skip [automatic initialization of GTK and GDK](https://pygobject.gnome.org/guide/imports.html) :mr:`368` * PyGObject is no longer automatically tested on i386 architecture :mr:`362` * Fixed iterator protocol implementation for properties :mr:`392` * Various code and documentation improvements :mr:`346` :mr:`348` :mr:`358`, a.o. Note: the pygtkcompat module will be removed during the 3.53 development cycle. 3.50.0 - 2024-09-12 ------------------- * tests: Fix event test errors when GTK is not installed :mr:`347` 3.49.0 - 2024-09-06 (pre-release) --------------------------------- * Rename master branch to main * Drop support for Python 3.8 :mr:`300` * Add Override for Gio.DataInputStream :mr:`293` * Treat GParamSpec as any other fundamental type :mr:`268` * override connection.register_object to prevent an invocation object from leaking :mr:`219` * Various PyPy related fixes :mr:`299` * bind_property: Accept keyword arguments :mr:`309` * Various documentation improvements :mr:`342` :mr:`343` :mr:`338` :mr:`336` :mr:`335` :mr:`328` :mr:`329` :mr:`330` :mr:`325` :mr:`322` :mr:`312` * Python2 / GTK2 cleanups :mr:`338` :mr:`331` * Experimental: asyncio integration with support to await Gio async functions :mr:`189` * meson: move from .egg-info to .dist-info/METADATA :mr:`306` * build: fixes for building with gobject-introspection 1.81 :mr:`344` 3.48.2 - 2024-04-06 ------------------- * Fix support for fundamental (primitive) types, such as Gst.Bitmask :issue:`624` :mr:`304` 3.48.1 - 2024-03-10 ------------------- * Fix installation with pip failing in some environments with ModuleNotFoundError in g-ir-scanner :issue:`622` :mr:`302` 3.48.0 - 2024-03-09 ------------------- :Note: See 3.47.0 below for more details. * test: fix some tests on macOS :mr:`296` * docs: some dark mode fixes :mr:`291` 3.47.0 - 2024-02-12 (pre-release) --------------------------------- :Note: This is an unstable release. :Note: This is the first release using meson-python, and thus meson, instead of setuptools for PEP-517 installations i.e. when installing via pip or similar. Distro packagers can continue to use plain meson to build pygobject, but doing PEP-517 builds should also be possible with meson-python instead of setuptools. * Drop setuptools in favor of meson-python :mr:`248` :mr:`253` :mr:`254` :mr:`255` :mr:`276` * Fundamental type support :mr:`250` * Fundamental type support for GValues :mr:`264` * pygi-convert.sh: migrate FILE_CHOOSER_CONFIRMATION_* :mr:`266` * gimodule, cairo: Use multi-phase initialization as per PEP-489 :mr:`271` * Deprecate classes in gi.option module :mr:`272` * Deprecate pygtkcompat :mr:`278` * Add support for (optional) nullable GErrors :mr:`259` * Fix CssProvider not valid in GTK2 :mr:`284` * Fix double free if array item cannot be marshalled to Python :mr:`280` * Raise exception if a callback property is encountered :mr:`269` * build: Fix pycairo detection "script" for Windows :mr:`267` * Replace deprecated ``pkgutil.find_loader`` call :mr:`252` * Avoid segfault on property access for incompletely initialized objects :mr:`260` * pygenum: When getting a member instance, use correct key for the lookup :mr:`262` Project / Development / CI: * Remove pborelli from the maintainer list :mr:`251` * Add Arjan Molenaar to maintainers :mr:`256` * Remove runtests script :mr:`257` * test: build in a minimal environment without gtk :mr:`258` * CI: add a job for creating sdists :mr:`294` Documentation: * Build documentation on GitLab Pages :mr:`287` :mr:`289` * Update docs to use Furo theme :mr:`288` * Various docs improvements: :mr:`274` :mr:`281` :mr:`282` :mr:`285` :mr:`286` :mr:`292` 3.44.2 - 2023-09-29 ------------------- * Add support for Python 3.12 (minor test fixes) :mr:`247` * meson: define pycairo_dep in case pycairo=disabled :mr:`242` * Complete the PEP-451 implementation in gi.importer :mr:`229` * Replace usage of deprecated FFI closure API :mr:`241` * Fix invalid marshalling in some cases for boxed values, for example with Gtk.StyleContext.get_property() :mr:`213` * overrides: Allow Gdk.{Color,RGBA} instances to be compared with other objects :mr:`233` * docs: Fix build failure due to extlinks with Sphinx 6 :mr:`244` 3.46.0 - 2023-09-10 ------------------- * build: Drop Python 3.7 support :mr:`238` * build: Require glib 2.64 and gobject-introspection 1.64 :mr:`243` * Add support for Python 3.12 (minor test fixes) :mr:`247` * Drop GTK 2 support (after being effectively unsupported for 12 years) :mr:`182` * meson: Require meson 0.56.0 :mr:`220` * meson: Set PYTHONPATH in devenv :mr:`235` * meson: define pycairo_dep in case pycairo=disabled :mr:`242` * meson: Use pycairo from target python before pkg-config :mr:`223` * Complete the PEP-451 implementation in gi.importer :mr:`229` * Replace usage of deprecated FFI closure API :mr:`241` * Fix invalid marshalling in some cases for boxed values, for example with Gtk.StyleContext.get_property() :mr:`213` * Consistent setting of enum and flag property :mr:`192` * Fix docstring for methods that return an array and have a length (out) argument :mr:`249` * overrides: Fix incompatibility for CssProvider.load_from_data() (GTK 4.10) :mr:`231` * overrides: Allow Gdk.{Color,RGBA} instances to be compared with other objects :mr:`233` * overrides: Add overrides for Gdk.FileList in Gdk-4.0 :mr:`245` * docs: Fix underline too short warning :mr:`246` * docs: Fix build failure due to extlinks with Sphinx 6 :mr:`244` * docs: List additional projects using PyGObject :mr:`230` * docs: Update Development Environment Docs :mr:`232` * docs: Update docs and code examples to GTK 4 :mr:`215` 3.44.1 - 2023-03-24 ------------------- * Fix tests with glib 2.76 :mr:`240` 3.44.0 - 2023-03-19 ------------------- No changes compared to 3.43.1 3.43.1 - 2023-01-28 ------------------- * Note: PyGObject is in need of more maintainers, please read https://www.bassi.io/articles/2022/12/02/on-pygobject/ * Note: This is an unstable release. * Drop support for Python 3.6 :mr:`184` * meson: bump minimum version to 0.53.0 and update subprojects :mr:`227` * gimodule: fix floating state of python objects created with g_object_new :mr:`129` * Gtk.Template: Accept PathLike objects as a filename :mr:`195` * info: Show which type/object callables are bound to :mr:`194` * IntrospectionModule: handle two threads loading type at same time :mr:`149` * Port to Py_TRASHCAN_BEGIN :mr:`226` * Other cleanups/improvements: :mr:`181` :mr:`173` * This release also includes all changes from 3.42.1 and 3.42.2 3.42.2 - 2022-07-16 ------------------- * Error out instead of crashing when marshaling unsupported fundamental types in some cases :mr:`180` * Add a workaround for a PyPy 3.9+ bug when threads are used :mr:`200` * Fix crashes when marshaling zero terminated arrays for certain item types :mr:`191` * Fix a crash/refcounting error in case marshaling a hash table fails :mr:`191` * Make the test suite pass again with PyPy :mr:`191` * tests: support running tests with (MSVC) CPython 3.8+ on Windows :mr:`206` * interface: Fix leak when overriding GInterfaceInfo :mr:`204` * setup.py: look up pycairo headers without importing the module (helps with building on Windows and MSVC CPython 3.8+) :mr:`205` 3.42.1 - 2022-04-17 ------------------- * Do not error out for unknown scopes :mr:`179` * gtk overrides: restore Gtk.ListStore.insert_with_valuesv with newer gtk4 :issue:`467` * gtk overrides: Do not override Treeview.enable_model_drag_xx for GTK4 :mr:`175` * Implement DynamicImporter.find_spec() to silence a deprecation warning with Python 3.10 :issue:`473` * Some test/CI fixes 3.42.0 - 2021-09-19 ------------------- * meson: Bump minimum meson_version to 0.47.0 * Expose GObject.Object.run_dispose() :issue:`470` * docs: document Gtk.Template. :issue:`396` * dev: Add poetry support * meson: use main branch for glib subproject * Fix some small memory leaks :mr:`178` 3.40.1 - 2021-03-30 ------------------- * Fix tests with glib 2.68 :mr:`166` * Fix a regression with marshalling partial() objects :mr:`165` :issue:`464` 3.40.0 - 2021-03-19 ------------------- * GTK 4 compatibility fixes :mr:`148` :mr:`159` :mr:`144` :mr:`145` * Python 3.9 and 3.10 compatibility fixes :mr:`152` :mr:`156` * New minimal dependency requirements due to dropping support for Ubuntu 16.04 :mr:`151` * Python 3.6+ * glib 2.56+ * gobject-introspection 1.56+ * pycairo 1.16+ 3.38.0 - 2020-09-12 ------------------- * Python 2 is no longer supported. Note for distros/packagers: In case you want to keep Python 2 support you'll likely split any existing package into a Python 2 and 3 version. Since these aren't parallel installable here are some recommendations on how to make it work: * Build the devel package from the Python 3 source package * Drop the headers/.pc files from the Python 2 build/package * Make sure no Python 2 using package depends on the devel package (@Arch: gnumeric can be build without Python support for example) See :issue:`392` for details * meson: Make the `pycairo` option a feature :mr:`146` :mr:`147` * gdk overrides: Fix wrapping of scroll events :mr:`141` * Add overrides for Gtk.Button set/get_focus_on_click :mr:`132` 3.36.1 - 2020-05-06 ------------------- * tests: Fix failing tests with pytest 5.4.0+ * Gtk: Add override to make sure both TreeModelSort.new_with_model and TreeModel.sort_new_with_model exist independend of the gtk version * Gtk.Template: Fix initialisation order errors with Widgets getting created from C (potentially through other templates) :issue:`257` :issue:`386` :issue:`341` :mr:`140` (:user:`Jean Felder `) * Gtk.Template: Fix errors when calling init_template() multiple times :mr:`140` (:user:`Jean Felder `) 3.36.0 - 2020-03-08 ------------------- This will be the last release supporting Python 2. * pygobject-object: Avoid checking whether NULL is floating :mr:`135` (:user:`Alexandru BăluÈ› `) * Avoid various new glib deprecation warnings * Port to g_object_new_with_properties() * Drop Python 2 support on Windows * gtk overrides: Drop Menu, MenuItem for Gtk 4 (:user:`Marinus Schraal `) * Docs: * Update openSUSE instructions (:user:`sharkwouter`) * Add Gaphor to Who is Using PyGObject (:user:`Dan Yeaw `) * Remove reference to a fixed bug (:user:`Christian Stadelmann `) 3.34.0 - 2019-09-09 ------------------- * No changes since 3.33.1 3.33.1 - 2019-08-18 ------------------- * Make GLib.Variant.unpack a bit less costly :mr:`121` (:user:`Mathieu Bridon `) * pygobject: ignore GParameter deprecations :mr:`122` (:user:`Christian Hergert `) * pygobject-object: fix refcount of floating return values :mr:`120` (:user:`Mathieu Duponchelle `) * pygi-info: remove some dead code :issue:`303` 3.32.2 - 2019-06-23 ------------------- * Python 3.8b1 compatibility fixes * tests: fix a test error when run under wayland * setup.py: specify python_requires 3.30.5 - 2019-06-16 ------------------- * tests/gimarshallingtestsextra.c/h: relicense to LGPLv2.1+ :issue:`320` * Fix a crash when marshalling a GError to Python fails :mr:`115` * Fix leak of transfer-full/container C arrays :mr:`117` (:user:`Tomasz MiÄ…sko `) * Python 3.8b1 compatibility fixes 3.32.1 - 2019-04-20 ------------------- * tests/gimarshallingtestsextra.c/h: relicense to LGPLv2.1+ :issue:`320` * meson: add ``tests`` option for disabling tests :mr:`113` (:user:`Adam Duskett `) * meson: tests: pass ``--quiet`` to g-ir-scanner :mr:`114` (:user:`Tim-Philipp Müller `) * Fix a crash when marshalling a GError to Python fails :mr:`115` * Fix leak of transfer-full/container C arrays :mr:`117` (:user:`Tomasz MiÄ…sko `) 3.32.0 - 2019-03-10 ------------------- * No changes since 3.31.4 3.31.4 - 2019-03-07 ------------------- * docs: document GObject.Object.weak_ref() :issue:`245` * cairo: Add cairo pattern foreign struct support :mr:`111` (:user:`Renato Florentino Garcia `) * cairo: Add cairo_matrix_t converter to GValue :mr:`112` (:user:`Renato Florentino Garcia `) 3.31.3 - 2019-02-02 ------------------- * Speed up destruction of boxed types :mr:`106` and GObject.Value.set_value() calls. This makes appending to a Gtk.TreeModel nearly twice as fast for example :issue:`46`, :issue:`218` * Allow passing None for boolean parameters * meson: Install .egg-info directory to arch'd dir. :mr:`109` (:user:`Elliott Sales de Andrade `) * gtk overrides: raise in case Gtk.Window is instantiated after gtk_init failed :issue:`298` * gio overrides: Warn when creating various dbus types without a constructor :issue:`15` * tests: Fix tests with glib 2.59.x :issue:`287` * tests: fix test_atoms failing in some environments :issue:`300` 3.31.2 - 2018-12-15 ------------------- * Changes included in 3.30.4 * GLib.Variant.keys: correctly raise TypeError for non-dict types * GLib.Variant: implement __bool__ for maybe types * cairo: Fix GValue converters in case of NULL * setup.py: Print an install command hint when pkg-config is missing * pygi-info: wrap g_union_info_get_alignment() :mr:`105` (:user:`Tomasz MiÄ…sko `) 3.30.4 - 2018-11-30 ------------------- * gtk overrides: Fix rows getting inserted on the wrong level with TreeStore.insert_before/insert_after if parent=None. :issue:`281` (3.30 regression, thanks to :user:`Cian Wilson ` for the report) 3.30.3 - 2018-11-27 ------------------- * GValue: fall back to the custom C marshaller to support fundamental types. This makes GValue work with GstFraction. :issue:`280` * GValue: Work around wrong annotations for GVariant * Fix GObject attribute access during instance init which can lead to errors with __getattr__ implementations of subclasses. This lead to criticals when instantiating Gio.DBusProxy. :issue:`267` 3.31.1 - 2018-11-17 ------------------- * Changes included in 3.30.2 * overrides: add Pango.Layout.set_text() override. :issue:`259` :mr:`89` * docs: link updates :mr:`93` (:user:`tijder`) * overrides: Use functools.wraps instead of custom version. :issue:`271` :mr:`95` (:user:`Kai Willadsen `) * tests: Make tests run with current gtk4 master * Add (again) a pyproject.toml for specifying the pycairo build dep (requires pip >=18.0) * setup.py: Make it possible to build without cairo support through the PYGOBJECT_WITHOUT_PYCAIRO env var. :issue:`250` 3.30.2 - 2018-11-11 ------------------- * tests: Fix some test with newer glib. * overrides: Fix crash when using non-ascii text with. Gtk.Builder.add_from_string/add_objects_from_string. :issue:`255` * Various meson/distutils build fixes for MSVC. :mr:`91` (:user:`Chun-wei Fan `) * foreign-cairo: Fix cairo marshalling not using the foreign converters in some cases. :issue:`260` * build: setup.py reproducible build fixes. :mr:`94` (:user:`Bernhard M. Wiedemann `) 3.30.1 - 2018-09-14 ------------------- * Fix various crashes on big endian systems. :issue:`247` (:user:`Dan Horák `) * meson: Don't link against libpython on non-Windows systems. :issue:`253` :mr:`84` 3.30.0 - 2018-08-31 ------------------- * Various test suite fixes to get things to pass with Ubuntu 18.10. 3.29.3 - 2018-08-16 ------------------- * meson: Support building pycairo as a subproject. :mr:`76` * meson: Declare_dependency for use by potential superprojects (:user:`Mathieu Duponchelle `) * meson: Update glib wrap file. :mr:`80` (:user:`Carlos Soriano `) * meson: Fix the Python 2 build not not use the system pycairo extension when running tests. :issue:`242` * pygi-convert.sh: Various fixes and updates. :mr:`77` :mr:`78` (:user:`Sander Sweers `) * Gtk.Template: Fix instantiation error when using the new code with older PyGObject. :mr:`79` (:user:`Kai Willadsen `) * Gtk.Template: Don't error out when loading a resource that is only available in an overlay. :issue:`230` * Fix various crashes when running against a debug Python 3.7 build. :mr:`82` (:user:`Simon McVittie `) * overrides: Allow calling GObject.Binding.unbind() multiple times with GLib 2.58+. :issue:`240` * overrides: Gio.ListStore overrides use splice() when adding/removing many items with GLib 2.58+. :issue:`115` :mr:`83` * Work around pylint reporting bogus warnings regarding a missing self argument for normal functions. :issue:`217` * Add override for GdkPixbuf.Pixbuf.new_from_data() to wrap new_from_bytes() to work around a use after free. :issue:`225` :mr:`74` 3.28.3 - 2018-05-31 ------------------- * Fix Gio.Application leak in case no signal handler is set before. :issue:`219` * Squash critical warning when using array as hash value (:user:`Philip Withnall `) 3.29.2 - 2018-05-16 ------------------- * Add a meson build system. :issue:`165` (:user:`Mathieu Duponchelle`) * Gtk.Template: Allow marking children as "internal-child". :mr:`58` * Gio.ListModel: implement most of the mutable sequence protocol. :issue:`115` :mr:`59` * Gio.Settings: implement __iter__. * Gio.Settings: support range types in __setitem__. :issue:`134` * Add overrides for Gio.ListStore.sort and Gio.ListStore.insert_sorted. :issue:`130` * Make Gtk.Widget.freeze_child_notify a context manager. :issue:`45` * OptionParser.parse_args: return leftover arguments. :issue:`200` * Release the GIL when emitting a signal. :mr:`66` (John Bassett ) * Add ActionMap and ActionMap.add_action_entries() to overrides. :issue:`29` :mr:`65` (:user:`yangfl`) * importer: raise ImportError in load_module() and not find_module(). :issue:`213` * Don't wrap GValue in GValue when creating GValueArray. :mr:`66` (Stian Selnes ) * ossig: Don't leak the callbacks in case the event loops are not stopped through SIGINT. :issue:`219` :mr:`72` * Various fixes (Havard Graff ) * Destroy custom GLib.Source instances when they get freed. :issue:`193` * Revert "Add PEP518/pyproject.toml file", fixes installation with pip 10, see https://github.com/pypa/pip/issues/5244 * Various fixes/improvements for PyPy. * Don't crash on multiple calls to GObject.Value.__del__. :mr:`66` Documentation: * Added StackOverflow (with PyGObject tag) as an contact resource. (:user:`buhtz`) * Add introduction to handling GLib.Error. :mr:`68` (:user:`Kai Willadsen `) * Add pycairo requires for development setup. :mr:`70` (:user:`Kai Willadsen `) 3.29.1 - 2018-04-15 ------------------- * Support for `PyPy `__ and PyPy3. :issue:`180` * cairo: support :class:`cairo.Matrix` conversion. :issue:`16` * Speed up repeated closure creation by caching the closure cache in the argument cache :issue:`103` (:user:`Garrett Regier `\, :user:`Christoph Reiter `) * setup.py: make setuptools/pkg_resources optional. :issue:`186` * setup.py: print installation instructions in case a dependency is missing. :issue:`194` * Remove autotools build system. * overrides: Make :meth:`Gtk.ListStore.insert_before`, :meth:`Gtk.ListStore.insert_after`, :meth:`Gtk.TreeStore.insert_before` and :meth:`Gtk.TreeStore.insert_after` atomic. * Make :class:`GLib.Error` picklable. :issue:`145` * Add basic support for template based widgets through ``Gtk.Template``. :issue:`52` * Various documentation improvements. :mr:`29` (:user:`Dan Yeaw `) * Add PEP518/pyproject.toml file. :mr:`44` (:user:`James Tocknell `) * Avoid truncating value returned from g_value_info_get_value. :mr:`51` (:user:`Tomasz MiÄ…sko `) * Fix typo in BoundSignal disconnect. :mr:`55` (:user:`Vladislav Glinsky `) 3.28.2 - 2018-03-27 ------------------- * setup.py: Don't install the test C extension when it's built. :issue:`181` * setup.py: Always define PY_SSIZE_T_CLEAN. :issue:`185` * Fix __str__ return type of Gtk.TreePath with depth == 0. :issue:`143` * Fix a crash when setting a str property with a value containing surrogates. :issue:`169` * tests: Fix a potential crash during tests 3.28.1 - 2018-03-17 ------------------- * Fix a GValue leak (regression). :issue:`176` (:user:`Mathieu Duponchelle`) * setup.py: don't install the tests package * Various fixes for 64bit Windows. :mr:`34` (:user:`Mathieu Duponchelle`) * Fix tests with glib 2.56.0 * Various fixes for Python 3.7. :issue:`170` :mr:`28` 3.28.0 - 2018-03-12 ------------------- * GLib.Variant: Fix creation of guchar arrays from bytes (3.27.2 regression). :issue:`174` :mr:`30` 3.27.5 - 2018-03-01 ------------------- * Re-revert transfer-none boxed copy changes (:mr:`23`). Now with more fixes and tests. :mr:`24` (:user:`Mathieu Duponchelle `) * Add caching for boxed type lookup and try to avoid the import lock. :mr:`13` (:user:`Mikhail Fludkov `) 3.27.4 - 2018-02-14 ------------------- * tests: Fix tests under Wayland. :issue:`163` * tests: Make it possible to use pytest directly. * Reverted transfer-none boxed copy changes (:mr:`10`) due to regressions in gnome-music. :issue:`164` :mr:`23` 3.27.3 - 2018-02-10 ------------------- * Fix a 3.27.2 regression where functions return invalid boxed values. :mr:`16` (thanks to :user:`Mikhail Fludkov ` for providing a test) * tests: Make tests run without Gtk/Gdk installed. :mr:`17` (:user:`Mikhail Fludkov `) * tests: Remove dependency on ``localedef``. :commit:`64b02e301` * tests: Require/Use pytest. :mr:`20` :issue:`153` 3.27.2 - 2018-02-07 ------------------- * setup.py: Add a "quality" command which is equal to "make check.quality". * setup.py: Add a "test" command which is equal to "make check". :mr:`5` * setup.py: Install pkg-config and header files. * setup.py: Improve pycairo header lookup with pycairo >=1.16. :issue:`150` * autotools: "make check.quality" now requires flake8. * overrides: Fix ``Gtk.Adjustment.__init__()`` overrides not setting "value" sometimes. :issue:`151` :mr:`3` * overrides: ``GLib.Variant``: add support to create maybe types. :issue:`152` :mr:`4` (:user:`Alberto Ruiz `) * Make it possible to resolve ambiguous vmethod names. Ambiguities can be resolved by implementing methods named "do_$namespaced_base_class_name_$vfunc_name". :mr:`9` :issue:`105` (:user:`Mathieu Duponchelle `) * Fix setting a property installed in Python from C in some cases. :mr:`8` (:user:`Mathieu Duponchelle `) * pygobject-object: fix memory corruption around list of closures. :mr:`12` :issue:`158` (:user:`Mikhail Fludkov `) * Don't copy the boxed if we are the sole owner of the wrapper after a closure. :mr:`14` * Only copy transfer-none boxed values in closures once the closure exists. This allows modifying the passed boxed while allowing to keep the wrapper around after the closure is done. :mr:`10` (:user:`Mathieu Duponchelle `) 3.27.1 - 2017-12-11 ------------------- * Revert "setup.py: Also set setup_requires to require pycairo" (Christoph Reiter) * setup.py: Also set setup_requires to require pycairo (Christoph Reiter) * setup.py: Provide a os.path.samefile fallback for Python 2 under Windows (Christoph Reiter) * Add sphinx based documentation (Christoph Reiter) (:bzbug:`791448`) * PKG-INFO: Revert name back to PyGObject (Christoph Reiter) * setup.py: Rework pycairo discovery to not use pkg-config (Christoph Reiter) * setup.py: Fix the distcheck command on Windows (Christoph Reiter) * setup.py: Remove various classifiers and the download-url which aren't accepted by pypi (Christoph Reiter) * version bump (Christoph Reiter) 3.27.0 - 2017-12-08 ------------------- * demo: pep8 fixes (Christoph Reiter) * Fix ctypes.PyDLL construction under Windows (Christoph Reiter) (:bzbug:`622084`) * configure.ac: Error out in case autoconf-archive isn't installed (Christoph Reiter) (:bzbug:`784428`) * Move pygi-convert.sh into tools (Christoph Reiter) * README: Convert to reST (Christoph Reiter) * demo: Move demo into examples and dist it (Christoph Reiter) (:bzbug:`735918`) * demo: Add new Gtk.FlowBox example (Gian Mario Tagliaretti) (:bzbug:`735918`) * demo: Use HeaderBar for main app window (Simon Feltman) (:bzbug:`735918`) * demo: PyFlakes and PEP8 fixes (Simon Feltman) (:bzbug:`735918`) * demo: Rename gtk-demo.py to demo.py (Simon Feltman) (:bzbug:`735918`) * demo: Rename demos/gtk-demo to simply demo (Simon Feltman) (:bzbug:`735918`) * Remove AUTHORS file (Christoph Reiter) * Remove pre-commit.hook (Christoph Reiter) * setup.py: Port to distutils/setuptools (Christoph Reiter) (:bzbug:`789211`) * Install a default SIGINT handler for functions which start an event loop (Christoph Reiter) (:bzbug:`622084`) * Make Python OS signal handlers run when an event loop is idling (Christoph Reiter) (:bzbug:`622084`) * Drop Python 3.3 support (Christoph Reiter) (:bzbug:`790787`) * Drop set_value usage in Gtk.List/TreeStore.set override (Sander Sweers) (:bzbug:`790346`) * pygobject-object: Fix Python GC collecting a ref cycle too early (Christoph Reiter) (:bzbug:`731501`) * Fix potential uninitialized memory access during GC (Daniel Colascione) (:bzbug:`786872`) * test: revert parts of the previous test as it's broken on 32 bit builds (Christoph Reiter) (:bzbug:`786948`) * flags: Add testcase for bug 786948 (Christoph Reiter) (:bzbug:`786948`) * fix potential overflow when marshalling flags from py interface (Philippe Renon) (:bzbug:`786948`) * to_py_array: Properly handle enum array items (Christoph Reiter) (:bzbug:`788890`) * pygobject.doap: Add myself as maintainer (Christoph Reiter) * closure: Fix unaligned and out-of-bounds access (James Clarke) (:bzbug:`788894`) * build: Fix not installing .egg-info file (Christoph Reiter) (:bzbug:`777719`) * Drop pygobject-3.0-uninstalled.pc file (Christoph Reiter) * tests: Windows fix (Christoph Reiter) * tests: some more C locale fixes (Christoph Reiter) * tests: Make the test suite pass with the C locale (Christoph Reiter) * configure.ac: post-release version bump to 3.27.0 (Christoph Reiter) 3.26.1 - 2017-10-27 ------------------- * pygobject-object: Fix Python GC collecting a ref cycle too early (Christoph Reiter) (:bzbug:`731501`) * Fix potential uninitialized memory access during GC (Daniel Colascione) (:bzbug:`786872`) * test: revert parts of the previous test as it's broken on 32 bit builds (Christoph Reiter) (:bzbug:`786948`) * flags: Add testcase for bug 786948 (Christoph Reiter) (:bzbug:`786948`) * fix potential overflow when marshalling flags from py interface (Philippe Renon) (:bzbug:`786948`) * to_py_array: Properly handle enum array items (Christoph Reiter) (:bzbug:`788890`) * closure: Fix unaligned and out-of-bounds access (James Clarke) (:bzbug:`788894`) * build: Fix not installing .egg-info file (Christoph Reiter) (:bzbug:`777719`) * configure.ac: version bump to 3.26.1 (Christoph Reiter) 2.28.7 - 2017-10-13 ------------------- * Move property and signal creation into _class_init() (Martin Pitt) * gio-types.defs: change some enums to flags (Ryan Lortie) * Fix set_qdata warning on accessing NULL gobject property (Ivan Stankovic) * Disable introspection support by default (Dieter Verfaillie) * Don't install codegen for Python 3 (Arfrever Frehtes Taifersar Arahesis) * Ship tests/te_ST@nouppera in release tarballs for tests to succeed (Martin Pitt) * [gi] Port test_properties from static gio to GI Gio (Martin Pitt) * [python3] fix build. PYcairo_IMPORT doesn't exists anymore (Ignacio Casal Quinteiro) * [python3] Fix maketrans import (Martin Pitt) * [gi-overrides] fix MessageBox so it correctly handles the type constructor param (John (J5) Palmieri) * gdbus tests: Fix hang if test case fails (Martin Pitt) * Fix crash in Gtk.TextIter overrides (Martin Pitt) * correctly initialize the _gi_cairo_functions array to be zero filled (John (J5) Palmieri) * [gtk-override] print warning if user imports Gtk 2.0 (John (J5) Palmieri) * Add support for enums in gobject.property (Johan Dahlin) 3.26.0 - 2017-09-12 ------------------- * configure.ac: pre-release version bump to 3.26.0 (Christoph Reiter) * closure: silence a new compiler warning (Christoph Reiter) * tests: skip some failing test under Windows with Python 3.6 (Christoph Reiter) * tests: pyflakes/pep8 fixes (Christoph Reiter) * tests: Fix cairo test with pycairo >= 1.13 (Christoph Reiter) * Make sure version information passed to require_version is a string. (Benjamin Berg) (:bzbug:`781582`) * configure.ac: post-release version bump to 3.25.2 (Christoph Reiter) 3.25.1 - 2017-04-21 ------------------- * Bump pycairo requirement to 1.11.1 (Christoph Reiter) (:bzbug:`707196`) * configure.ac: Always disable -Werror (Christoph Reiter) * foreign-cairo: Enable cairo.Region support also on Python 2 if available (Christoph Reiter) * configure.ac: remove unused PLATFORM variable (Christoph Reiter) * configure.ac: Remove unused PySignal_SetWakeupFd check (Christoph Reiter) * tests: remove python 2.5/3.2 compat code (Christoph Reiter) * configure.ac: Require Python 3.3 (Christoph Reiter) * tests: Make test suite run with GTK+ 4 (Christoph Reiter) * tests: always call require_version; add TEST_GTK_VERSION env var (Christoph Reiter) * tests: Fix make check.valgrind (Christoph Reiter) * tests: Don't skip Regress tests when cairo is missing (Christoph Reiter) * tests: fix invalid regex escaping (Christoph Reiter) * tests: avoid mapping a GtkWindow (Christoph Reiter) (:bzbug:`780812`) * tests: silence some glib deprecation warnings (Christoph Reiter) (:bzbug:`780812`) * tests: avoid deprecation warnings for assertRegexpMatches/assertRaisesRegexp (Christoph Reiter) (:bzbug:`780812`) * pygi-source: clear exceptions in finalize handler (Christoph Reiter) (:bzbug:`780812`) * Fix pep8 errors (Christoph Reiter) * Remove gi._gi._gobject and gi._gobject modules (Christoph Reiter) (:bzbug:`735206`) * Remove gi._gi._glib module (Christoph Reiter) (:bzbug:`735206`) * GValue: add overflow checking for py -> gint; forward marshaling exceptions (Christoph Reiter) (:bzbug:`769789`) * pygobject_lookup_class: clear exceptions between calls and don't return with one set (Christoph Reiter) (:bzbug:`773394`) * Avoid some new deprecation warnings (Christoph Reiter) (:bzbug:`780768`) * Raise RuntimeError in case an uninitilialized GObject.Object is marshaled (Christoph Reiter) (:bzbug:`730908`) * closure: support unichar args (Christoph Reiter) (:bzbug:`759276`) * Add support for bytes and non-utf-8 file names. (Christoph Reiter) (:bzbug:`746564`) * test_gi: use correct min/max constants for gsize/gssize (Christoph Reiter) (:bzbug:`780591`) * Don't use long format string for formatting pointers (Christoph Reiter) (:bzbug:`780591`) * Fix conversion from pointers to hashfunc return values. (Christoph Reiter) (:bzbug:`780591`) * Fix PyLong <-> GPid conversion on 64bit Windows (Christoph Reiter) (:bzbug:`780591`) * property: support setting flags (Christoph Reiter) (:bzbug:`726484`) * overrides: warn on instantiation of Gio.VolumeMonitor (Christoph Reiter) (:bzbug:`744690`) * Remove gi.overrides.overridefunc (Christoph Reiter) (:bzbug:`686835`) * tests: Reduce usage of timeout_add() and sleep() (Christoph Reiter) (:bzbug:`698548`) * tests: Remove TestMainLoop.test_concurrency (Christoph Reiter) (:bzbug:`698548`) * Update .gitignore: add ``*.dll``, ``*.dylib``, ``.DS_STORE`` (Christoph Reiter) * tests: Make test suite run on Windows (Christoph Reiter) (:bzbug:`780396`) * tests: Make test suite run on macOS (Christoph Reiter) (:bzbug:`780396`) * Fix various compiler warnings for 32bit builds (Christoph Reiter) (:bzbug:`780409`) * pep8 fix (Christoph Reiter) * testhelper: only link against libpython on Windows (Christoph Reiter) (:bzbug:`773803`) * overrides: Fix Gtk.TextBuffer.insert_with_tags_by_name() with no tags (Garrett Regier) (:bzbug:`772896`) * Make use of instance-argument annotations (Christoph Reiter) (:bzbug:`735076`) * Remove pyglib_gil_state_ensure/pyglib_gil_state_release (Christoph Reiter) (:bzbug:`699440`) * Remove support for building without threads (Christoph Reiter) (:bzbug:`699440`) * pygtkcompat: Allow multiple calls to enable(), enable_gtk() as long as the version matches (Christoph Reiter) (:bzbug:`759009`) * tests: Update Makefile for building tests on OS X (Simon Feltman) (:bzbug:`762176`) * testhelper: propagate exception if _gobject could not be imported (Mikhail Fludkov) (:bzbug:`772949`) * pygi-info: initialize GIArgument before passing it to g_constant_info_get_value (Christoph Reiter) (:bzbug:`772949`) * tests: build libregress with disabled cairo (Mikhail Fludkov) (:bzbug:`772949`) * tests: use g-ir utils found by pkg-config (Mikhail Fludkov) (:bzbug:`772949`) * Add a foreign type for cairo_region_t. (Shyouzou Sugitani) (:bzbug:`667959`) * aclocal: make local file discover by reading AC_CONFIG_MACRO_DIR work (Christoph Reiter) (:bzbug:`777713`) * Port from gnome-common to autoconf-archive (Christoph Reiter) (:bzbug:`777713`) * Fix various potential compiler warnings (Christoph Reiter) (:bzbug:`777713`) * configure.ac: post-release version bump to 3.25.0 (Christoph Reiter) * Remove egg make target (Christoph Reiter) (:bzbug:`777719`) * Remove legacy docs (Christoph Reiter) (:bzbug:`777719`) 3.24.1 - 2017-04-10 ------------------- * pygi-info: initialize GIArgument before passing it to g_constant_info_get_value (Christoph Reiter) (:bzbug:`772949`) * configure.ac: post-release version bump to 3.24.1 (Christoph Reiter) 3.24.0 - 2017-03-20 ------------------- * configure.ac: pre-release version bump to 3.24.0 (Christoph Reiter) 3.23.92 - 2017-03-13 -------------------- * overrides: Update for Gdk-4.0 and Gtk+-4.0 (Fabian Orccon) (:bzbug:`777680`) * Disable -Werror=missing-prototypes (Christoph Reiter) (:bzbug:`777534`) * Fix new PEP8 errors (Christoph Reiter) (:bzbug:`776009`) * Move pep8/pyflakes tests from 'make check' to 'make check.quality' (Christoph Reiter) (:bzbug:`764087`) * overrides: Update for Gtk-4.0 (Christoph Reiter) (:bzbug:`773315`) * Handle exception unreffing Variant at exit (Dan Nicholson) (:bzbug:`776092`) * Handle multiple deinit of callable cache (Dan Nicholson) (:bzbug:`776092`) * configure.ac: post-release version bump to 3.23.0 (Christoph Reiter) 3.22.0 - 2016-09-19 ------------------- * configure.ac: pre-release version bump to 3.22.0 (Christoph Reiter) 3.21.92 - 2016-09-11 -------------------- * Handle nullable filename parameters (Christoph Reiter) (:bzbug:`770821`) * Fix list/hashtable enum <-> hash conversion on 64-bit big endian (Aurelien Jarno) (:bzbug:`770608`) * Allow passing sockets to io_add_watch on win32 (Lukas K) (:bzbug:`766396`) * tests: use dbus-run-session instead of dbus-launch to run tests (Michael Biebl) (:bzbug:`770798`) * configure.ac: post-release version bump to 3.21.92 (Christoph Reiter) 3.21.91 - 2016-08-25 -------------------- * Allow installing with pip (Mathieu Bridon) (:bzbug:`767988`) * Skip a test with older glib (Christoph Reiter) (:bzbug:`740301`) * Fix a test with Python 3.1/3.2 (Arfrever Frehtes Taifersar Arahesis, Christoph Reiter) (:bzbug:`740324`) * tests: Use places kwarg for assertAlmostEqual (Arfrever Frehtes Taifersar Arahesis, Christoph Reiter) (:bzbug:`740337`) * Print exception if marshalling a signal argument fails (Christoph Reiter) (:bzbug:`748198`) * overrides: allow treemodel sequence shorthands (Marinus Schraal) (:bzbug:`766580`) * Remove pygobject-external.h (Christoph Reiter) (:bzbug:`767084`) * Remove pygobject-private.h and rename pygobject.c to pygobject-object.c (Christoph Reiter) (:bzbug:`767084`) * Merge pyglib-private.h into pyglib.h (Christoph Reiter) (:bzbug:`767084`) * Remove pygi.h and pygi-private.h (Christoph Reiter) (:bzbug:`767084`) * configure.ac: post-release version bump to 3.21.1 (Simon Feltman) 3.21.0 - 2016-04-24 ------------------- * gi: Add require_versions() function (Dustin Falgout) (:bzbug:`761141`) * test_gerror_novalue: Don't assign the error to a variable (Iain Lane) (:bzbug:`764165`) * build: Do not enable code coverage based on lcov (Emmanuele Bassi) (:bzbug:`764075`) 3.20.1 - 2016-04-24 ------------------- * test_gerror_novalue: Don't assign the error to a variable (Iain Lane) (:bzbug:`764165`) 3.20.0 - 2016-03-21 ------------------- 3.19.92 - 2016-03-15 -------------------- 3.19.91 - 2016-03-01 -------------------- * Fix marshaling of GError stored in GValue (Simon Feltman) (Thibault Saunier) (:bzbug:`761592`) * Fix marshaling or GError from Python to C from function calls (Simon Feltman) (:bzbug:`685197`) * Error handling/reporting fixes (Christoph Reiter) (:bzbug:`751956`) * Fix crash due to GVariant implemented as PyGBoxed not PyGIStruct (Christoph Reiter) (:bzbug:`751956`) * Fix crash with GValueArray stored in GValue (Mikhail Fludkov) (:bzbug:`754359`) 3.19.90 - 2016-02-20 -------------------- * tests: Set the active style context state before retrieving values (Simon Feltman) * tests: Fix crash with empty drag source icon names (Simon Feltman) (:bzbug:`762392`) * Try to import GdkX11 in Gdk overrides (Christoph Reiter) (:bzbug:`673396`) * Fix import warnings pointing to the wrong code with CPython 3.3/3.5 (Christoph Reiter) (:bzbug:`757184`) 3.19.2 - 2015-10-31 ------------------- * tests: Fix failure due to new GTK+ warning regarding size_allocate() (Simon Feltman) * Fix build warnings regarding _POSIX_C_SOURCE redefinition (Simon Feltman) * Drop -std=c90 for now (Matthias Clasen) 3.19.1 - 2015-10-30 ------------------- * Use a named tuple for returning multiple values (Christoph Reiter) (:bzbug:`727374`) * enum/flags: use gir info for type names and __repr__ instead of the gtype name (Christoph Reiter) (:bzbug:`657915`) * Improve and unify __repr__ format for PyGObject, PyGBoxed and PyGIStruct (Christoph Reiter) (:bzbug:`657915`) * Don't leak internal RepositoryError on import. (Christoph Reiter) (:bzbug:`756033`) * Import dependencies when importing typelibs from gi.repository (Christoph Reiter) (:bzbug:`656314`) * Fix Gdk.rectangle_intersect/rectangle_union missing with GTK+ 3.18 (Christoph Reiter) (:bzbug:`756364`) * Don't import inspect at module level (Christoph Reiter) * invoke state: add a free memory cache for PyGIInvokeArgState (Christoph Reiter) (:bzbug:`750658`) * invoke/closure: reduce g_slice_alloc usage (Christoph Reiter) (:bzbug:`750658`) * pep8: ignore new errors reported by pep8 1.6 (Christoph Reiter) * Bump g-i dependency to latest stable (Garrett Regier) * Avoid calling g_slist_length() during invoke (Garrett Regier) * Simplify closure_convert_arguments() (Garrett Regier) * Remove a level of indentation in convert_ffi_arguments() (Garrett Regier) * Prevent passing the user data multiple times to callbacks (Garrett Regier) (:bzbug:`750347`) * Support throwing exceptions in closures (Garrett Regier) (:bzbug:`710671`) * Don't emit require_version warning if namespace was loaded previously using g_irepository_require (Christoph Reiter) (:bzbug:`754491`) * configure.ac: post release version bump to 3.19.1 (Garrett Regier) 3.18.2 - 2015-10-24 ------------------- * configure.ac: post release version bump to 3.18.2 (Christoph Reiter) 3.18.1 - 2015-10-23 ------------------- * Fix Gdk.rectangle_intersect/rectangle_union missing with GTK+ 3.18 (Christoph Reiter) (:bzbug:`756364`) * pep8: ignore new errors reported by pep8 1.6 (Christoph Reiter) * Don't emit require_version warning if namespace was loaded previously using g_irepository_require (Christoph Reiter) (:bzbug:`754491`) * configure.ac: post release version bump to 3.18.1 (Garrett Regier) 3.18.0 - 2015-09-22 ------------------- 3.17.90 - 2015-08-19 -------------------- * Allow passing unicode lists to GStrv properties on Python 2 (Christoph Reiter) (:bzbug:`744745`) * Avoid a silent long to int truncation (Rui Matos) (:bzbug:`749698`) * Handle gtype marshalling (Mathieu Bridon) (:bzbug:`749696`) * pygi-foreign-cairo.c: fix include for py3cairo.h (Daniel Hahler) (:bzbug:`746742`) * tests: Silence various error messages and warnings (Christoph Reiter) (:bzbug:`751156`) * Fix test regression when xdg-user-dirs is not installed (Christoph Reiter) (:bzbug:`751299`) * Explicitly check if an override exists instead of ImportError (Garrett Regier) (:bzbug:`749532`) 3.17.1 - 2015-06-15 ------------------- * Add gi.PyGIWarning used when import version is not specified (Christoph Reiter) (:bzbug:`727379`) * Remove Gdk.Rectangle alias with newer gobject-introspection and GTK+ (Christoph Reiter) (:bzbug:`749625`) * overrides: Provide _overrides_module attribute (Christoph Reiter) (:bzbug:`736678`) * overrides: Conditionalize touch override support in Gdk (Simon Feltman) (:bzbug:`747717`) * Field setters: Remove unneeded type/range checks and unused code (Christoph Reiter) (:bzbug:`746985`) * pygi-argument: Remove unused imports/includes (Christoph Reiter) (:bzbug:`746985`) * Improve test coverage for field setters/getters (Christoph Reiter) (:bzbug:`746985`) 3.16.2 - 2015-06-15 ------------------- * overrides: Provide _overrides_module attribute (Christoph Reiter) (:bzbug:`736678`) 3.16.1 - 2015-04-13 ------------------- * overrides: Conditionalize touch override support in Gdk (Simon Feltman) (:bzbug:`747717`) 3.16.0 - 2015-03-24 ------------------- 3.15.91 - 2015-03-05 -------------------- * tests: Don't use deprecated override attributes (Christoph Reiter) (:bzbug:`743514`) * Add GLib.MINFLOAT etc. and mark GObject.G_MINFLOAT etc. deprecated (Christoph Reiter) (:bzbug:`743514`) * Emit PyGIDeprecationWarning when accessing deprecated override attributes (Christoph Reiter) (:bzbug:`743514`) * Add namespace and container name to all warnings/error messages (Christoph Reiter) (:bzbug:`743468`) * tests: Add test for GIRepository.UnionInfo.get_size() (Garrett Regier) (:bzbug:`745362`) * Avoid duping filenames when marshalling from Python to C (Garrett Regier) (:bzbug:`744719`) 3.15.0 - 2015-02-20 ------------------- * Avoid copying bytearrays from Python to C when transfer nothing (Garrett Regier) (:bzbug:`743278`) * Allows passing arguments to opaque Boxed types (Garrett Regier) (:bzbug:`743214`) * Emit ImportWarning when gi.require_version() is not used (Christoph Reiter) (:bzbug:`727379`) * Refactor overrides import/modules (Christoph Reiter) (:bzbug:`736678`) * Replace statically bound GLib.Variant.new_tuple() with GI (Simon Feltman) (:bzbug:`735199`) * overrides: Add Gdk.EventTouch union discrimination (Simon Feltman) (:bzbug:`736380`) * PyGObjectFlags: Remove a trailing comma on the enum. (Murray Cumming) * Remove redefinitions of function and vfunc cache typedefs (Simon Feltman) (:bzbug:`737874`) 3.14.0 - 2014-09-22 ------------------- * configure.ac: pre release version bump to 3.14.0 (Simon Feltman) 3.13.92 - 2014-09-15 -------------------- * tests: Add test for Gio.Application.add_main_option() (Simon Feltman) * tests: Split up various test cases (Simon Feltman) (:bzbug:`735193`) * Fix invalid read error in argument cleanup code (Simon Feltman) * Fix memory management problems with struct arguments to signals (Simon Feltman) (:bzbug:`736175`) 3.13.91 - 2014-09-01 -------------------- * docs: Fix return types in auto-generated doc strings (Simon Feltman) * Special case signal output arguments which are structs as pass-by-reference (Simon Feltman) (:bzbug:`735486`) * Ignore closure callbacks when Python is not initialized (Simon Feltman) (:bzbug:`722562`) * Change boxed init with args to warn instead of raise (Christoph Reiter) (:bzbug:`727810`) * Fix crash in GList/GSList marshaling error handling path. (Christoph Reiter) (:bzbug:`735201`) * Fix reference counting problems with GLib.Variant.new_tuple() (Simon Feltman) (:bzbug:`735166`) * Skip marshalling NULL output arguments in Python closures (Simon Feltman) (:bzbug:`735090`) 3.13.90 - 2014-08-18 -------------------- * Support array lengths on struct fields (Simon Feltman) (:bzbug:`688792`) * Fast path Python property get access (Simon Feltman) (:bzbug:`723872`) * Unify accessing properties through props and get_property() (Simon Feltman) (:bzbug:`726999`) * Refactor boxed wrapper memory management strategy (Simon Feltman) (:bzbug:`726999`) * Replace GObject.signal_query with introspected version (Simon Feltman) (:bzbug:`688792`) * Fix memory leak with unboxed caller allocated structs (Simon Feltman) * tests: Add failing tests for GObject sub-class doc-strings (Piotr Iwaniuk) (:bzbug:`731452`) * Don't mask GObject sub-class doc strings in meta-class (Tobias Mueller) (:bzbug:`731452`) 3.13.4 - 2014-08-14 ------------------- * Marshaling cache refactor and cache usage in vfuncs (Garrett Regier) (:bzbug:`727004`) * Fix array argument out and inout marshaling from vfuncs (Garrett Regier) (:bzbug:`702508`) * Cleanup input args when marshaling in closures (Garrett Regier) (:bzbug:`727004`) * Add deprecation warning for connect_object() with non-GObject argument (Simon Feltman) (:bzbug:`688064`) * Add Python implementation of Object.connect_data() (Simon Feltman) (:bzbug:`701843`) * Add GClosure marshaling cleanup (Simon Feltman) (:bzbug:`695128`) * Fix GCallback Python wrapper leak (Simon Feltman) (:bzbug:`695130`) * tests: Add failing test for marshaling an array of GValues through signals (Martin Pitt) (:bzbug:`669496`) * Add protection against attempts at importing static bindings (Simon Feltman) (:bzbug:`709183`) * Update and deprecate gi.overrides.keysyms (Simon Feltman) (:bzbug:`721295`) * Generate .dll libraries on windows (Ignacio Casal Quinteiro) (:bzbug:`734288`) * Windows build fixes (Alexey Pavlov) (:bzbug:`734284`, :bzbug:`734289`, :bzbug:`734286`, :bzbug:`734287`) 3.13.3 - 2014-06-23 ------------------- * demos: Cleanup CSS accordion demo to use a loop for adding buttons (Simon Feltman) * refactor: Move builder connection utilities outside of Builder class (Simon Feltman) (:bzbug:`701843`) * tests: Move TestSignals from test_everything into test_signal (Simon Feltman) (:bzbug:`701843`) 3.13.2 - 2014-05-26 ------------------- * Python 3.4 make check fixes (Simon Feltman) (:bzbug:`730411`) * overrides: Add Gtk.Container.child_get/set overrides (Simon Feltman) (:bzbug:`685076`) * overrides: Make value argument to Widget.style_get_property optional (Simon Feltman) (:bzbug:`685076`) * overrides: Make value argument to Container.child_get_property optional (Simon Feltman) (:bzbug:`685076`) * Add GTypeClass methods as Python GObject class methods (Johan Dahlin) (:bzbug:`685218`) * Add marshalling coercion for Python classes and instances to GTypeClass (Simon Feltman) (:bzbug:`685218`) * Replace direct parent class call by super() (Andrew Grigorev) (:bzbug:`729970`) * Add cairo marshaling support for non-introspected signals (Simon Feltman) (:bzbug:`694604`) * [New API] Add gi.require_foreign (Simon Feltman) (:bzbug:`707735`) * Initialize the foreign API at PyGI load time (Simon Feltman) (:bzbug:`694604`) * Move pygi foreign API into pygi-foreign-api.h (Simon Feltman) (:bzbug:`694604`) * Unify GLib.GError and GLib.Error (Simon Feltman) (:bzbug:`712519`) * PEP8 fixes (Simon Feltman) 3.12.2 - 2014-05-26 ------------------- * PEP8 fixes (Simon Feltman) * Python 3.4 make check fixes (Simon Feltman) (:bzbug:`730411`) 3.13.1 - 2014-04-28 ------------------- * Raise TypeError if arguments are passed to Boxed.__init__ (Christoph Reiter) (:bzbug:`727810`) * Gdk.Event: Override __setattr__ to set fields based on the event type (Christoph Reiter) (:bzbug:`727810`) * Gdk.Event: Include GdkEventType in __repr__ (Christoph Reiter) (:bzbug:`727810`) * Fix crash with type checking for GObject arguments (Simon Feltman) (:bzbug:`727604`) * Do not leak info of destroy notify (Paolo Borelli) * Ignore GValueArray deprecations (Simon Feltman) * Raise ImportError when importing modules not found in repository (Simon Feltman) (:bzbug:`726877`) * tests: Rename test_overrides to test_import_machinery (Simon Feltman) (:bzbug:`726877`) 3.12.1 - 2014-04-14 ------------------- * Fix crash with type checking invalid GObject arguments (Simon Feltman) (:bzbug:`727604`) * Do not leak info of destroy notify (Paolo Borelli) 3.12.0 - 2014-03-24 ------------------- 3.11.92 - 2014-03-17 -------------------- * configure.ac: Remove option to build without libffi (Simon Feltman) * docs: Standardize Python doc strings (Simon Feltman) * Fix reference leaks with (transfer full) foreign struct returns (Owen W. Taylor) (:bzbug:`726206`) 3.11.91 - 2014-03-03 -------------------- * Use ffi_call directly instead of g_callable_info_invoke (Simon Feltman) (:bzbug:`723642`) * configure.ac: Use -std=c90 and error on declaration-after-statement (Simon Feltman) * Fix Build on Visual Studio (Chun-wei Fan) (:bzbug:`725122`) 3.11.90 - 2014-02-17 -------------------- * Use GObject type checking for instance arguments (Simon Feltman) (:bzbug:`724009`) * configure.ac: post release version bump to 3.11.90 (Simon Feltman) 3.11.5 - 2014-02-03 ------------------- * cache refactoring: Move all cache marshalers into files based on type (Simon Feltman) (:bzbug:`709700`) * tests: Add test for an owned boxed struct passed in a callback (Mike Gorse) (:bzbug:`722899`) * build: Add --without-common configure option for package maintainers (Patrick Welche) (:bzbug:`721646`) * demo: Add TreeModel interface implementation demonstration (Simon Feltman) * build: Set PLATFORM_VERSION again to 3.0 (Colin Walters) * tests: Run PyFlakes and PEP8 only on SUBDIRS (Simon Feltman) * Merge static PyGLib and PyGObject modules into PyGI (Simon Feltman) (:bzbug:`712197`) * Add test for callback user data arguments with following arguments (Martin Pitt) (:bzbug:`722104`) 3.11.4 - 2014-01-13 ------------------- * overrides: Fix __repr__ for various Gdk structs (Simon Feltman) * Add enum and flags member methods (Simon Feltman) (:bzbug:`693099`) * python.m4: g/c JD_PYTHON_CHECK_VERSION (Patrick Welche) (:bzbug:`721662`) * Support union creation with PyGIStruct (Simon Feltman) * docs: List constructors in object and struct doc strings (Simon Feltman) (:bzbug:`708060`) * docs: Fix array length argument skipping with preceding out arguments * docs: Add return values and skip implicit out arguments in functions (Simon Feltman) (:bzbug:`697356`) * docs: Skip implicit array length args when building function doc strings (Simon Feltman) (:bzbug:`697356`) * gtk-demo: Add CSS demos (Gian Mario Tagliaretti) (:bzbug:`719722`) * build: Avoid clash between gi/types.py and stdlib (Colin Watson) (:bzbug:`721025`) 3.11.3 - 2013-12-16 ------------------- * Replace usage of PyGIBoxed_Type with PyGIStruct_Type (Simon Feltman) (:bzbug:`581525`) 3.11.2 - 2013-11-17 ------------------- * gkt-demo: Change main info/source notebook into a GtkStack (Simon Feltman) * Add deprecation warnings and cleanup class initializer overrides (Simon Feltman) (:bzbug:`705810`) * Fix dir method for static GParamSpec in Python 3 (Simon Feltman) * Remove overzealous argument checking for callback userdata (Simon Feltman) (:bzbug:`711173`) 3.10.2 - 2013-11-11 ------------------- * Fix thread safety problems by always enabling the GIL (Simon Feltman) (:bzbug:`709223`, :bzbug:`710447`) 3.11.1 - 2013-10-28 ------------------- * Fix toggleref safety problems by always enabling the GIL (Simon Feltman) (:bzbug:`709223`) * Add consistent GLib.MainLoop SIGINT cleanup (Simon Feltman) (:bzbug:`710978`) * docs: Add a keyword value of None for allow-none annotations (Simon Feltman) (:bzbug:`640812`) * Remove overrides for supporting pre-3.10 GObject signal functions (Simon Feltman) * Add threads_init back as a requirement for non-Python threaded repos (Simon Feltman) (:bzbug:`710447`) * Add dir method to GObject props accessor (Simon Feltman) (:bzbug:`705754`) * Remove PyGObjectWeakRef now that g_binding_unbind exists (Simon Feltman) (:bzbug:`699571`) * Fix lots of memory leaks leaks (Simon Feltman) (:bzbug:`693402`, :bzbug:`709397`) * Add support for variable user data arguments (Simon Feltman) (:bzbug:`640812`) * Bump glib and g-i dependencies to latest stable. (Martin Pitt) * Fix TypeError when setting drag target_list to None (Nuno Araujo) (:bzbug:`709926`) * Use qdata for wrapper retrieval in toggle reference notifications (Simon Feltman) (:bzbug:`709223`) * Expose all GI enum and flags types (Simon Feltman) (:bzbug:`709008`) * Add support for default arguments annotated with allow-none (Simon Feltman) (:bzbug:`640812`) * Refactor argument cache handling (Simon Feltman) (:bzbug:`640812`) * Remove support for allowing PyObjects as void pointers (Simon Feltman) (:bzbug:`688081`) 3.10.1 - 2013-10-14 ------------------- * Fix TypeError when setting drag target_list to None (Nuno Araujo) (:bzbug:`709926`) * Use qdata for wrapper retrieval in toggle reference notifications (Simon Feltman) (:bzbug:`709223`) * Fix memory leak for caller allocated GValue out arguments (Simon Feltman) (:bzbug:`709397`) 3.10.0 - 2013-09-23 ------------------- * Fix test_gi.TestProjectVersion.test_version_str() (Martin Pitt) 3.9.92 - 2013-09-16 ------------------- * Fix union argument regression when marshaling from python (Simon Feltman) (:bzbug:`703873`) * Fix GLib.Source sub-classing with initializer args (Simon Feltman) (:bzbug:`707904`) * Copy __doc__ when wrapping function (Vratislav Podzimek) 3.9.91 - 2013-09-02 ------------------- * Fix GObject signal methods to work with new annotations (Simon Feltman) (:bzbug:`707280`) * Fix build on C89 Compilers (Chun-wei Fan) (:bzbug:`707264`) * Change boxed type checking in marshaling to use __gtype__ attribute (Simon Feltman) (:bzbug:`707140`) * Use G_IS_VALUE for checking return values in closure marshaling (Simon Feltman) (:bzbug:`707170`) * Fix PEP-8 errors in propertyhelper.py (Yanko Kaneti) (:bzbug:`706319`) 3.9.90 - 2013-08-19 ------------------- * Create GLib.Pid in the same way on python 2 and 3 (Benjamin Berg) (:bzbug:`705451`) * Use PyLong_Type.tp_new for GLib.Pid (Benjamin Berg) (:bzbug:`705451`) * Add accumulator and accu_data arguments to GObject.Signal decorator (Simon Feltman) (:bzbug:`705533`) * Pass return values through the GObject.Signal.emit wrapper (Simon Feltman) (:bzbug:`705530`) 3.9.5 - 2013-07-29 ------------------ * Ensure exceptions set in closure out argument marshaling are printed (Simon Feltman) (:bzbug:`705064`) * Always raise OverflowError for marshaling integers from Python (not ValueError or OverflowError) (Simon Feltman) (:bzbug:`705057`) * Cleanup invoke args and kwargs combiner code (Simon Feltman) (:bzbug:`640812`) * gtk-demo: Change demo to use Gtk.Application (Simon Feltman) (:bzbug:`698547`) * Add callable and descriptor protocols to PyGICallableInfo (Simon Feltman) (:bzbug:`704037`) * Unify basic type argument marshaling for methods, closures, and properties (Simon Feltman) (:bzbug:`693405`) * Override GValue.set/get_boxed with static C marshaler (Simon Feltman) (:bzbug:`688081`, :bzbug:`693405`) * Add deprecation warning for marshaling arbitrary objects as pointers (Simon Feltman) (:bzbug:`688081`) * Replace usage of __import__ with importlib.import_module (Simon Feltman) (:bzbug:`682320`) * Always unref the GiTypeInfo when generating an argument cache (Mike Gorse) (:bzbug:`703973`) * Unref interface info when fetching enums or flags (Mike Gorse) (:bzbug:`703960`) * Speed up MRO calculation (Daniel Drake) (:bzbug:`703829`) * Add GIL safety to pyobject_copy for copying boxed PyObjects (Simon Feltman) (:bzbug:`688081`) * Add marshaling of GI_TYPE_TAG_VOID held in a GValue to int (Simon Feltman) (:bzbug:`694233`) * GTK overrides: Make connect_signals handle tuple (Cole Robinson) (:bzbug:`693994`) * Re-add support for passing GValue's by reference (Simon Feltman) (:bzbug:`701058`) * Clear return value of closures to zero when an exception occurs (Simon Feltman) (:bzbug:`702552`) * Don't use doctest syntax in docstrings for examples (Martin Pitt) (:bzbug:`701009`) * Add support for properties of type GInterface (Garrett Regier) (:bzbug:`703456`) * pygtkcompat: Fix for missing methods on Windows (Martin Pitt) (:bzbug:`702787`) * gi/pygi-info.c: Avoid C99-style variable declaration (Chun-wei Fan) (:bzbug:`702786`) 3.8.3 - 2013-07-05 ------------------ * Add marshalling of GI_TYPE_TAG_VOID held in a GValue to int. While not particularly useful this allows some callbacks in WebKit to function without causing a segfault. (Simon Feltman) (:bzbug:`694233`) * pygtkcompat: Fix for missing methods on Windows (Martin Pitt) (:bzbug:`702787`) * gi/pygi-info.c: Avoid C99-style variable declaration (Chun-wei Fan) (:bzbug:`702786`) * Clear return value of closures to zero when an exception occures (Simon Feltman) (:bzbug:`702552`) * Re-add support for passing GValue's by reference (Simon Feltman) (:bzbug:`701058`) * Don't use doctest syntax in docstrings for examples, to fix test failures with pyflakes 0.7.x (Martin Pitt) (:bzbug:`701009`) * examples/option.py: Port to GI and Python 3 (Martin Pitt) 3.9.2 - 2013-05-28 ------------------ * examples/option.py: Port to GI and Python 3 (Martin Pitt) * Fix vfunc info search for classes with multiple inheritance (Simon Feltman) (:bzbug:`700092`) * Fix closure argument conversion for enum and flag in args (Simon Feltman) * Fix marshaling Python to FFI return value for enum and flags (Simon Feltman) * Remove half implemented GC in PyGIBaseInfo, PyGIStruct, and PyGIBoxed (Simon Feltman) (:bzbug:`677091`) * Replace usage of pyg_begin_allow_threads with Py_BEGIN_ALLOW_THREADS (Simon Feltman) (:bzbug:`699440`) * Remove and deprecate API for setting of thread blocking functions (Simon Feltman) (:bzbug:`699440`) 3.8.2 - 2013-05-13 ------------------ * Fix vfunc info search for classes with multiple inheritance (Simon Feltman) (:bzbug:`700092`) * Fix closure argument conversion for enum and flag in args (Simon Feltman) * Fix marshaling Python to FFI return value for enum and flags (Simon Feltman) * Use correct class for GtkEditable's get_selection_bounds() function (Mike Ruprecht) (:bzbug:`699096`) * Test results of g_base_info_get_name for NULL (Simon Feltman) (:bzbug:`698829`) * Change interpretation of NULL pointer field from None to 0 (Simon Feltman) (:bzbug:`698366`) * Remove Python keyword escapement in Repository.find_by_name (Simon Feltman) (:bzbug:`697363`) 3.9.1 - 2013-04-30 ------------------ * gtk-demo: Wrap description strings at 80 characters (Simon Feltman) (:bzbug:`698547`) * gtk-demo: Use textwrap to reformat description for Gtk.TextView (Simon Feltman) (:bzbug:`698547`) * gtk-demo: Use GtkSource.View for showing source code (Simon Feltman) (:bzbug:`698547`) * Use correct class for GtkEditable's get_selection_bounds() function (Mike Ruprecht) (:bzbug:`699096`) * Test results of g_base_info_get_name for NULL (Simon Feltman) (:bzbug:`698829`) * Add ObjectInfo.get_class_struct() (Johan Dahlin) (:bzbug:`685218`) * Change interpretation of NULL pointer field from None to 0 (Simon Feltman) (:bzbug:`698366`) * Do not build tests until needed (Sobhan Mohammadpour) (:bzbug:`698444`) * pygi-convert: Support toolbar styles (Kai Willadsen) (:bzbug:`698477`) * pygi-convert: Support new-style constructors for Gio.File (Kai Willadsen) (:bzbug:`698477`) * pygi-convert: Add some support for recent manager constructs (Kai Willadsen) (:bzbug:`698477`) * pygi-convert: Don't transform arbitrary keysym imports (Kai Willadsen) (:bzbug:`698477`) * Remove Python keyword escapement in Repository.find_by_name (Simon Feltman) (:bzbug:`697363`) * Optimize signal lookup in gi repository (Daniel Drake) (:bzbug:`696143`) * Optimize connection of Python-implemented signals (Daniel Drake) (:bzbug:`696143`) * Consolidate signal connection code (Daniel Drake) (:bzbug:`696143`) * Fix setting of struct property values (Daniel Drake) * Optimize property get/set when using GObject.props (Daniel Drake) (:bzbug:`696143`) * configure.ac: Fix PYTHON_SO with Python3.3 (Christoph Reiter) (:bzbug:`696646`) * Simplify registration of custom types (Daniel Drake) (:bzbug:`696143`) * pygi-convert.sh: Add GStreamer rules (Christoph Reiter) (:bzbug:`697951`) * pygi-convert: Add rule for TreeModelFlags (Jussi Kukkonen) * Unify GI marshalling code (Simon Feltman) (:bzbug:`693405`) * Use distutils.sysconfig to retrieve the python include path. (Christoph Reiter) (:bzbug:`696648`) * Support PEP 3149 (ABI version tagged .so files) (Christoph Reiter) (:bzbug:`696646`) * Fix stack corruption due to incorrect format for argument parser (Simon Feltman) (:bzbug:`696892`) * Deprecate GLib and GObject threads_init (Simon Feltman) (:bzbug:`686914`) * Drop support for Python 2.6 (Martin Pitt) * Remove static PollFD bindings (Martin Pitt) (:bzbug:`686795`) * Drop test skipping due to too old g-i (Martin Pitt) * Bump glib and g-i dependencies (Martin Pitt) 3.8.1 - 2013-04-15 ------------------ * pygi-convert.sh: Add GStreamer rules (Christoph Reiter) (:bzbug:`697951`) * pygi-convert: Add rule for TreeModelFlags (Jussi Kukkonen) * Fix enum and flags marshaling type assumptions (Simon Feltman) * Use g_strdup() consistently (Martin Pitt) (:bzbug:`696650`) * Fix stack corruption due to incorrect format for argument parser (Simon Feltman) (:bzbug:`696892`) 3.8.0 - 2013-03-25 ------------------ * tests: Fix incorrect assumption when testing pyglib version (Simon Feltman) 3.7.92 - 2013-03-18 ------------------- * Fix stack smasher when marshaling enums as a vfunc return value (Simon Feltman) (:bzbug:`637832`) * Change base class of PyGIDeprecationWarning based on minor version (Simon Feltman) (:bzbug:`696011`) * autogen.sh: Source gnome-autogen to fix out of source builddir (Alban Browaeys) (:bzbug:`694889`) * pygtkcompat: Make gdk.Window.get_geometry return tuple of 5 (Simon Feltman) * pygtkcompat: Initialize hint to zero in set_geometry_hints (Simon Feltman) * Remove incorrect bounds check with property helper flags (Simon Feltman) * Fix crash when setting property of type object to an incorrect type (Simon Feltman) (:bzbug:`695420`) * Give more informative error when setting property to incorrect type (Simon Feltman) (:bzbug:`695420`) 3.7.91.1 - 2013-03-05 --------------------- * Revert "Drop gi.overrides.overridefunc()" (Martin Pitt) (:bzbug:`695199`) 3.7.91 - 2013-03-04 ------------------- * Fix many memory leaks (:bzbug:`675726`, :bzbug:`693402`, :bzbug:`691501`, :bzbug:`510511`, :bzbug:`691501`, :bzbug:`672224`, and several more which are detected by our test suite) (Martin Pitt) * Dot not clobber original Gdk/Gtk functions with overrides (Martin Pitt) (:bzbug:`686835`) * Optimize GValue.get/set_value by setting GValue.g_type to a local (Simon Feltman) (:bzbug:`694857`) * Run tests with G_SLICE=debug_blocks (Martin Pitt) (:bzbug:`691501`) * Add override helper for stripping boolean returns (Martin Pitt) (:bzbug:`694431`) * Drop obsolete pygobject_register_sinkfunc() declaration (Martin Pitt) (:bzbug:`639849`) * Fix marshalling of C arrays with explicit length in signal arguments (Martin Pitt) (:bzbug:`662241`) * Fix signedness, overflow checking, and 32 bit overflow of GFlags (Martin Pitt) (:bzbug:`693121`) * gi/pygi-marshal-from-py.c: Fix build on Visual C++ (Chun-wei Fan) (:bzbug:`692856`) * Raise DeprecationWarning on deprecated callables (Martin Pitt) (:bzbug:`665084`) * pygtkcompat: Add Widget.window, scroll_to_mark, and window methods (Simon Feltman) (:bzbug:`694067`) * pygtkcompat: Add Gtk.Window.set_geometry_hints which accepts keyword arguments (Simon Feltman) (:bzbug:`694067`) * Ship pygobject.doap for autogen.sh (Martin Pitt) (:bzbug:`694591`) * Fix crashes in various GObject signal handler functions (Simon Feltman) (:bzbug:`633927`) * pygi-closure: Protect the GSList prepend with the GIL (Olivier Crête) (:bzbug:`684060`) * generictreemodel: Fix bad default return type for get_column_type (Simon Feltman) 3.7.90 - 2013-02-19 ------------------- * overrides: Fix inconsistencies with drag and drop target list API (Simon Feltman) (:bzbug:`680640`) * pygtkcompat: Add pygtk compatible GenericTreeModel implementation (Simon Feltman) (:bzbug:`682933`) * overrides: Add support for iterables besides tuples for TreePath creation (Simon Feltman) (:bzbug:`682933`) * Prefix __module__ attribute of function objects with gi.repository (Niklas Koep) (:bzbug:`693839`) * configure.ac: only enable code coverage when available, to fix autogen.sh with older gnome-commons (Jonathan Ballet) (:bzbug:`693328`) * Correctly set properties on object with statically defined properties (Jonathan Ballet) (:bzbug:`693618`) * autogen.sh: Use gnome-autogen.sh (Martin Pitt) (:bzbug:`693328`) * Fix reference leaks with transient floating objects (Simon Feltman) (:bzbug:`687522`) 3.7.5.1 - 2013-02-05 -------------------- * Fix ABI break with pygobject.h from 3.7.5 (Simon Feltman) (:bzbug:`675726`) 3.7.5 - 2013-02-04 ------------------ * Move various signal methods from static bindings to GI (Simon Feltman) (:bzbug:`692918`) * GLib overrides: Support unpacking 'maybe' variants (Paolo Borelli) (:bzbug:`693032`) * Fix ref count leak when creating pygobject wrappers for input args (Mike Gorse) (:bzbug:`675726`) * Prefix names of typeless enums and flags for GType registration (Simon Feltman) (:bzbug:`692515`) * Fix compilation with non-C99 compilers such as Visual C++ (Chun-wei Fan) (:bzbug:`692856`) * gi/overrides/Glib.py: Fix running on Windows/non-Unix (Chun-wei Fan) * Do not immediately initialize Gdk and Gtk on import (Martin Pitt) (:bzbug:`692300`) * Accept ±inf and NaN as float and double values (Martin Pitt) (:bzbug:`692381`) * Fix repr() of GLib.Variant (Martin Pitt) * Fix gtk-demo for Python 3 (Martin Pitt) * Define GObject.TYPE_VALUE gtype constant (Martin Pitt) * gobject: Go through introspection on property setting (Olivier Crête) (:bzbug:`684062`) * Clean up caller-allocated GValues and their memory (Mike Gorse) (:bzbug:`691820`) * Use GNOME_COMPILE_WARNINGS from gnome-common (Martin Pitt) 3.7.4 - 2013-01-14 ------------------ * Allow setting values through GtkTreeModelFilter (Simonas Kazlauskas) (:bzbug:`689624`) * Support GParamSpec signal arguments from Python (Martin Pitt) (:bzbug:`683099`) * pygobject_emit(): Fix cleanup on error (Martin Pitt) * Add signal emission methods to TreeModel which coerce the path argument (Simon Feltman) (:bzbug:`682933`) * Add override for GValue (Bastian Winkler) (:bzbug:`677473`) * Mark caller-allocated boxed structures as having a slice allocated (Mike Gorse) (:bzbug:`699501`) * pygi-property: Support boxed GSList/GList types (Olivier Crête) (:bzbug:`684059`) * tests: Add missing backwards compat methods for Python 2.6 (Martin Pitt) (:bzbug:`691646`) * Allow setting TreeModel values to None (Simon Feltman) (:bzbug:`684094`) * Set clean-up handler for marshalled arrays (Mike Gorse) (:bzbug:`691509`) * Support setting string fields in structs (Vadim Rutkovsky) (:bzbug:`678401`) * Permit plain integers for "gchar" values (Martin Pitt) * Allow single byte values for int8 types (Martin Pitt) (:bzbug:`691524`) * Fix invalid memory access handling errors when registering an enum type (Mike Gorse) * Fix (out) arguments in callbacks (Martin Pitt) * Fix C to Python marshalling of struct pointer arrays (Martin Pitt) * Don't let Property.setter() method names define property names (Martin Pitt) (:bzbug:`688971`) * Use g-i stack allocation API (Martin Pitt) (:bzbug:`615982`) * pyg_value_from_pyobject: support GArray (Ray Strode) (:bzbug:`690514`) * Fix obsolete automake macros (Marko Lindqvist) (:bzbug:`691101`) * Change dynamic enum and flag gtype creation to use namespaced naming (Simon Feltman) (:bzbug:`690455`) * Fix Gtk.UIManager.add_ui_from_string() override for non-ASCII chars (Jonathan Ballet) (:bzbug:`690329`) * Don't dup strings before passing them to type registration functions (Mike Gorse) (:bzbug:`690532`) * Fix marshalling of arrays of boxed struct values (Carlos Garnacho) (:bzbug:`656312`) 3.7.3 - 2012-12-17 ------------------ * Add support for caller-allocated GArray out arguments (Martin Pitt) (:bzbug:`690041`) * [API add] Re-support calling GLib.io_add_watch with an fd or Python file (Martin Pitt) * pygtkcompat: Work around IndexError on large flags (Martin Pitt) * Fix pyg_value_from_pyobject() range check for uint (Martin Pitt) * Fix tests to work with g-i 1.34.2 (Martin Pitt) * Fix wrong refcount for GVariant property defaults (Martin Pitt) (:bzbug:`689267`) * Fix array arguments on 32 bit architectures (Martin Pitt) * Add backwards compatible API for GLib.unix_signal_add_full() (Martin Pitt) * Drop MININT64/MAXUINT64 workaround, current g-i gets this right now (Martin Pitt) * Fix maximum and minimum ranges of TYPE_(U)INT64 properties (Simonas Kazlauskas) (:bzbug:`688949`) * Ship pygi-convert.sh in tarballs (Martin Pitt) (:bzbug:`688697`) 3.7.2 - 2012-11-19 ------------------ * [API change] Drop almost all static GLib bindings and replace them with proper introspection. This gets rid of several cases where the PyGObject API was not matching the real GLib API, makes the full GLib API available through introspection, and makes the code smaller, easier to maintain. For backwards compatibility, overrides are provided to emulate the old static binding API, but this will throw a PyGIDeprecationWarning for the cases that diverge from the official API (in particular, GLib.io_add_watch() and GLib.child_watch_add() being called without a priority argument). (Martin Pitt, Simon Feltman) * [API change] Deprecate calling GLib API through the GObject namespace. This has always been a misnomer with introspection, and will be removed in a later version; for now this throws a PyGIDeprecationWarning. * [API change] Do not bind gobject_get_data() and gobject_set_data(). These have been deprecated for a cycle, now dropped entirely. (Steve Frécinaux) (:bzbug:`641944`) * [API change] Deprecate void pointer fields as general PyObject storage. (Simon Feltman) (:bzbug:`683599`) * Add support for GVariant properties (Martin Pitt) * Add type checking to GVariant argument assignment (Martin Pitt) * Fix marshalling of arrays of struct pointers to Python (Carlos Garnacho) (:bzbug:`678620`) * Fix Gdk.Atom to have a proper str() and repr() (Martin Pitt) (:bzbug:`678620`) * Make sure g_value_set_boxed does not cause a buffer overrun with GStrvs (Simon Feltman) (:bzbug:`688232`) * Fix leaks with GValues holding boxed and object types (Simon Feltman) (:bzbug:`688137`) * Add doc strings showing method signatures for gi methods (Simon Feltman) (:bzbug:`681967`) * Set Property instance doc string and blurb to getter doc string (Simon Feltman) (:bzbug:`688025`) * Add GObject.G_MINSSIZE (Martin Pitt) * Fix marshalling of GByteArrays (Martin Pitt) * Fix marshalling of ssize_t to smaller ints (Martin Pitt) * Add support for lcov code coverage, and add a lot of missing GIMarshallingTests and g-i Regress tests. (Martin Pitt) * pygi-convert: remove deprecated GLib → GObject conversions (Jose Rostagno) * Add support for overriding GObject.Object (Simon Feltman) (:bzbug:`672727`) * Add --with-python configure option (Martin Pitt) * Do not prefer unversioned "python" when configuring, as some distros have "python" as Python 3. Use Python 3 by default if available. Add --with-python configure option as an alternative to setting $PYTHON, whic is more discoverable. (Martin Pitt) * Fix property lookup in class hierarchy (Daniel Drake) (:bzbug:`686942`) * Move property and signal creation into _class_init() (Martin Pitt) (:bzbug:`686149`) * Fix duplicate symbols error on OSX (John Ralls) * [API add] Add get_introspection_module for getting un-overridden modules (Simon Feltman) (:bzbug:`686828`) * Work around wrong 64 bit constants in GLib Gir (Martin Pitt) (:bzbug:`685022`) * Mark GLib.Source.get_current_time() as deprecated (Martin Pitt) * Fix OverflowError in source_remove() (Martin Pitt) (:bzbug:`684526`) 3.4.2 - 2012-11-12 ------------------ * Fix marshalling of GByteArrays (Martin Pitt) * Fix marshalling of ssize_t to smaller ints (Martin Pitt) * Fix crash with GLib.child_watch_add (Daniel Narvaez) (:bzbug:`688067`) * Fix various bugs in GLib.IOChannel (Martin Pitt) * Work around wrong 64 bit constants in GLib Gir (Martin Pitt) (:bzbug:`685022`) * Fix OverflowError in source_remove() (Martin Pitt) (:bzbug:`684526`) * Fix Signal decorator to not use base class gsignals dict (Simon Feltman) (:bzbug:`686496`) 3.7.1 - 2012-10-22 ------------------ * Bump version to 3.7.1; let's follow the real GNOME versioning from now on (Martin Pitt) * Change install_properties to not use getattr on classes (Simon Feltman) (:bzbug:`686559`) * Move property install function into propertyhelper.py (Simon Feltman) (:bzbug:`686559`) * Fix Signal decorator to not use base class gsignals dict (Simon Feltman) (:bzbug:`686496`) * tests: Consistently use GLib.MainLoop (Martin Pitt) * Install the .egg-info files into correct multilib directory (Kalev Lember) (:bzbug:`686315`) * Fix leaked vfunc return values (Simon Feltman) (:bzbug:`686140`) * Skip Regress tests with --disable-cairo (Martin Pitt) (:bzbug:`685094`) * Fix leak with python callables as closure argument. (Simon Feltman) (:bzbug:`685598`) * Gio overrides: Handle setting GSettings enum keys (Martin Pitt) (:bzbug:`685947`) * tests: Check reading GSettings enums in Gio overrides (Martin Pitt) * Fix unsigned values in GArray/GList/GSList/GHash (Martin Pitt) (:bzbug:`685860`) * _pygi_marshal_from_py_uint64(): Use correct data type in py2.7 check (Alban Browaeys) (:bzbug:`685000`) * Install an .egg-info file (Johan Dahlin) (:bzbug:`680138`) * PyGProps_getattro(): Fix GObjectClass leak (Johan Dahlin) (:bzbug:`685218`) * pygobject.c: Don't leak GObjectClass reference (Olivier Crête) (:bzbug:`684062`) * Fix memory leak in _pygi_argument_to_array() (Alban Browaeys) (:bzbug:`685082`) * Fix error messages for out of range numbers (Martin Pitt) (:bzbug:`684314`) * Kill dbus-daemon after running tests (Martin Pitt) (:bzbug:`685009`) * GVariant overrides: Support empty tuple arrays (Martin Pitt) (:bzbug:`684928`) * tests: Fix wrong return type in test_int64_callback() (Martin Pitt) (:bzbug:`684700`) * Fix GValue marshalling of long and unsigned long (Giovanni Campagna) (:bzbug:`684331`) * Clean up deprecation message for assigning gpointers to objects. (Simon Feltman) (:bzbug:`683599`) * pygi-property: Lookup property in base classes of non-introspected types (Olivier Crête) (:bzbug:`684058`) 3.4.1.1 - 2012-10-17 -------------------- * Bump g-i dependency to >= 1.34.1.1 (Paolo Borelli) * Fix leaked vfunc return values (Simon Feltman) (:bzbug:`686140`) * Install egg-info files in the right dir Kalev Lember) (:bzbug:`686315`) 3.4.1 - 2012-10-15 ------------------ * Skip Regress tests with --disable-cairo (Martin Pitt) (:bzbug:`685094`) * Fix leak with python callables as closure argument. (Simon Feltman) (:bzbug:`685598`) * Gio overrides: Handle setting GSettings enum keys (Martin Pitt) (:bzbug:`685947`) * Fix unsigned values in GArray/GList/GSList/GHash (Martin Pitt) (:bzbug:`685860`) * _pygi_marshal_from_py_uint64(): Use correct data type in py2.7 check (Alban Browaeys) (:bzbug:`685000`) * Install an .egg-info file (Johan Dahlin) (:bzbug:`680138`) * PyGProps_getattro(): Fix GObjectClass leak (Johan Dahlin) (:bzbug:`685218`) * pygobject.c: Don't leak GObjectClass reference (Olivier Crête) (:bzbug:`684062`) * Fix memory leak in _pygi_argument_to_array() (Alban Browaeys) (:bzbug:`685082`) * Fix error messages for out of range numbers (Martin Pitt) (:bzbug:`684314`) * Kill dbus-daemon after running tests (Martin Pitt) (:bzbug:`685009`) * GVariant overrides: Support empty tuple arrays (Martin Pitt) (:bzbug:`684928`) * tests: Fix wrong return type in test_int64_callback() (Martin Pitt) (:bzbug:`684700`) * Fix GValue marshalling of long and unsigned long (Giovanni Campagna) (:bzbug:`684331`) * Clean up deprecation message for assigning gpointers to objects. (Simon Feltman) (:bzbug:`683599`) * pygi-property: Lookup property in base classes of non-introspected types (Olivier Crête) (:bzbug:`684058`) 3.4.0 - 2012-09-24 ------------------ * Bump g-i dependency to 1.33.14 (Martin Pitt) 3.3.92 - 2012-09-17 ------------------- * [API add] Add ObjectInfo.get_abstract method (Simon Feltman) (:bzbug:`675581`) * Add deprecation warning when setting gpointers to anything other than int. (Simon Feltman) (:bzbug:`683599`) * argument: Fix 64bit integer convertion from GValue (Nicolas Dufresne) (:bzbug:`683596`) * Improve setting pointer fields/arguments to NULL using None (Simon Feltman) (:bzbug:`683150`) * Bump g-i dependency to 1.33.10 (Martin Pitt) * Fix -uninstalled.pc.in file (Thibault Saunier) (:bzbug:`683379`) * Various test suite additions and improvements (Martin Pitt) 3.3.91 - 2012-09-03 ------------------- * Fix exception test case for Python 2 (Martin Pitt) * Bump g-i dependency to >= 1.3.9 (Martin Pitt) * Show proper exception when trying to allocate a disguised struct (Martin Pitt) (:bzbug:`639972`) * Support marshalling GParamSpec signal arguments (Mark Nauwelaerts) (:bzbug:`683099`) * Add test for a signal that returns a GParamSpec (Martin Pitt) (:bzbug:`683265`) * [API add] Add Signal class for adding and connecting custom signals. (Simon Feltman) (:bzbug:`434924`) * Fix pygtkcompat's Gtk.TreeView.insert_column_with_attributes() (Martin Pitt) * Add override for Gtk.TreeView.insert_column_with_attributes() (Marta Maria Casetti) (:bzbug:`679415`) * .gitignore: Add missing built files (Martin Pitt) * Ship tests/gi in tarball (Martin Pitt) * Split test_overrides.py (Martin Pitt) (:bzbug:`683188`) * _pygi_argument_to_object(): Clean up array unmarshalling (Martin Pitt) * Fix memory leak in _pygi_argument_to_object() (Alban Browaeys) (:bzbug:`682979`) * Fix setting pointer fields/arguments to NULL using None. (Simon Feltman) (:bzbug:`683150`) * Fix for python 2.6, officially drop support for < 2.6 (Martin Pitt) (:bzbug:`682422`) * Allow overrides in other directories than gi itself (Thibault Saunier) (:bzbug:`680913`) * Clean up sys.path handling in tests (Simon Feltman) (:bzbug:`680913`) * Fix dynamic creation of enum and flag gi types for Python 3.3 (Simon Feltman) (:bzbug:`682323`) * [API add] Override g_menu_item_set_attribute (Paolo Borelli) (:bzbug:`682436`) 3.3.90 - 2012-08-20 ------------------- * Implement marshalling for GParamSpec (Mathieu Duponchelle) (:bzbug:`681565`) * Fix erronous import statements for Python 3.3 (Simon Feltman) (:bzbug:`682051`) * Do not fail tests if pyflakes or pep8 are not installed (Martin Pitt) * Fix PEP-8 whitespace checking and issues in the code (Martin Pitt) * Fix unmarshalling of gssize (David Malcolm) (:bzbug:`680693`) * Fix various endianess errors (David Malcolm) (:bzbug:`680692`) * Gtk overrides: Add TreeModelSort.__init__(self, model) (Simon Feltman) (:bzbug:`681477`) * Convert Gtk.CellRendererState in the pygi-convert script (Manuel Quiñones) (:bzbug:`681596`) 3.3.5 - 2012-08-06 ------------------ * Fix list marshalling on big-endian machines (Martin Pitt) (:bzbug:`680693`) * Beautify class/interface type mismatch error messages (Martin Pitt) * Skip instead of fail tests which need Pango, Atk, Gdk, Gtk (Martin Pitt) * [API add] pygtkcompat: Add more pixbuf creation functions (Simon Feltman) (:bzbug:`680814`) * Fix error messages on interface/class type mismatches (Martin Pitt) * Fix crash when returning (False, None) from Gtk.TreeModel.do_get_iter() (Simon Feltman) (:bzbug:`680812`) * Add test case for Gtk.TextIter.forward_search() (Martin Pitt) (:bzbug:`679415`) * pygi-info.c: Robustify pointer arithmetic (Martin Pitt) * Add set_attributes() override to Gtk.TreeViewColumn (Manuel Quiñones) * Gtk overrides: Add TreePath.__getitem__() (Simon Feltman) (:bzbug:`680353`) * Fix property type mapping from int to TYPE_INT for python3. (Simon Feltman) (:bzbug:`679939`) * Convert Gtk.DestDefaults constants in pygi-convert.sh script (Manuel Quiñones) (:bzbug:`680259`) * Convert all Gdk.WindowState constants in pygi-convert.sh (Manuel Quiñones) (:bzbug:`680257`) * [API add] Add API for checking pygobject's version (Joe R. Nassimian) (:bzbug:`680176`) * pygi-convert.sh: Add some missing Gdk.CursorTypes (Manuel Quiñones) (:bzbug:`680050`) * pygi-convert.sh: convert rsvg.Handle(data=...) (Manuel Kaufmann) (:bzbug:`680092`) 3.3.4 - 2012-07-16 ------------------ * pygi-convert.sh: Drop bogus filter_new() conversion (Martin Pitt) (:bzbug:`679999`) * Fix help() for GI modules (Martin Pitt) (:bzbug:`679804`) * Skip gi.CallbackInfo objects from a module's dir() (Martin Pitt) (:bzbug:`679804`) * Fix __path__ module attribute (Martin Pitt) * pygi-convert.sh: Fix some child → getChild() false positives (Joe R. Nassimian) (:bzbug:`680004`) * Fix array handling for interfaces, properties, and signals (Mikkel Kamstrup Erlandsen) (:bzbug:`667244`) * Add conversion of the Gdk.PropMode constants to pygi-convert.sh script (Manuel Quiñones) (:bzbug:`679775`) * Add the same rules for pack_start to convert pack_end (Manuel Quiñones) (:bzbug:`679760`) * Add error-checking for the case where _arg_cache_new() fails (Dave Malcolm) (:bzbug:`678914`) * Add conversion of the Gdk.NotifyType constants to pygi-convert.sh script (Manuel Quiñones) (:bzbug:`679754`) * Fix PyObject_Repr and PyObject_Str reference leaks (Simon Feltman) (:bzbug:`675857`) * [API add] Gtk overrides: Add TreePath.__len__() (Martin Pitt) (:bzbug:`679199`) * GLib.Variant: Fix repr(), add proper str() (Martin Pitt) (:bzbug:`679336`) * m4/python.m4: Update Python version list (Martin Pitt) * Remove "label" property from Gtk.MenuItem if it is not set (Micah Carrick) (:bzbug:`670575`) 3.3.3.1 - 2012-06-25 -------------------- * Do not escape enum and flag names that are Python keywords (Martin Pitt) 3.3.3 - 2012-06-25 ------------------ * Remove obsolete release-tag make target (Martin Pitt) * Do not do any python calls when GObjects are destroyed after the python interpreter has been finalized (Simon Schampijer) (:bzbug:`678046`) * Do not change constructor-only "type" Window property (Martin Pitt) (:bzbug:`678510`) * Escape identifiers which are Python keywords (Martin Pitt) (:bzbug:`676746`) * Fix code for PEP-8 violations detected by the latest pep8 checker. (Martin Pitt) * Fix crash in GLib.find_program_in_path() (Martin Pitt) (:bzbug:`678119`) * Revert "Do not bind gobject_get_data() and gobject_set_data()" (Martin Pitt) (:bzbug:`641944`) * GVariant: Raise proper TypeError on invalid tuple input (David Keijser) (:bzbug:`678317`) 3.3.2 - 2012-06-05 ------------------ * foreign: Register cairo.Path and cairo.FontOptions foreign structs (Bastian Winkler) (:bzbug:`677388`) * Check types in GBoxed assignments (Marien Zwart) (:bzbug:`676603`) * [API add] Gtk overrides: Add TreeModelRow.get_previous() (Bastian Winkler) (:bzbug:`677389`) * [API add] Add missing GObject.TYPE_VARIANT (Bastian Winkler) (:bzbug:`677387`) * Fix boxed type equality (Jasper St. Pierre) (:bzbug:`677249`) * Fix TestProperties.testBoxed test (Jose Rostagno) (:bzbug:`676644`) * Fix handling of by-reference structs as out parameters (Carlos Garnacho) (:bzbug:`653151`) * tests: Add more vfunc checks for GIMarshallingTestsObject (Martin Pitt) * Test caller-allocated GValue out parameter (Martin Pitt) (:bzbug:`653151`) * GObject.bind_property: Support transform functions (Bastian Winkler) (:bzbug:`676169`) * Fix lookup of vfuncs in parent classes (Carlos Garnacho) (:bzbug:`672864`) * tests/test_properties.py: Fix whitespace (Martin Pitt) * gi: Support zero-terminated arrays with length arguments (Jasper St. Pierre) (:bzbug:`677124`) * [API add] Add GObject.bind_property method (Simon Feltman) (:bzbug:`675582`) * pygtkcompat: Correctly set flags (Jose Rostagno) (:bzbug:`675911`) * Gtk overrides: Implement __delitem__ on TreeModel (Jose Rostagno) (:bzbug:`675892`) * Gdk Color override should support red/green/blue_float properties (Simon Feltman) (:bzbug:`675579`) * Support marshalling of GVariants for closures (Martin Pitt) (:bzbug:`656554`) * _pygi_argument_from_object(): Check for compatible data type (Martin Pitt) * pygtkcompat: Fix color conversion (Martin Pitt) * test_gi: Check setting properties in constructor (Martin Pitt) * Support getting and setting GStrv properties (Martin Pitt) * Support defining GStrv properties from Python (Martin Pitt) * Add GObject.TYPE_STRV constant (Martin Pitt) * Unref GVariants when destroying the wrapper (Martin Pitt) (:bzbug:`675472`) * Fix TestArrayGVariant test cases (Martin Pitt) * pygtkcompat: Add gdk.pixbuf_get_formats compat code (Jose Rostagno) (:bzbug:`675489`) * pygtkcompat: Add some more compat functions (Jose Rostagno) (:bzbug:`675489`) * Fix tests for Python 3 (Martin Pitt) * Fix building with --disable-cairo (Martin Pitt) * tests: Fix deprecated assertions (Martin Pitt) * Run tests with ``MALLOC_PERTURB_`` (Martin Pitt) 3.2.2 - 2012-05-14 ------------------ * pygtkcompat: Correctly set flags (Jose Rostagno) (:bzbug:`675911`) * Gtk overrides: Implement __delitem__ on TreeModel (Jose Rostagno) (:bzbug:`675892`) 3.2.1 - 2012-05-10 ------------------ * Reindent files in tests to use 4-space indentation (Sebastian Pölsterl * Add missing override for TreeModel.iter_previous() (Martin Pitt) * GSettings: allow extra keyword arguments (Giovanni Campagna) * pygtkcompat: Correct Userlist module use (Jose Rostagno) * test_gdbus: Call GetConnectionUnixProcessID() with correct signature (Martin Pitt) * GTK overrides: Add missing keyword arguments (Martin Pitt) * pygi-convert.py: Drop obsolete drag method conversions (Martin Pitt) * Fix len_arg_index for array arguments (Bastian Winkler) * Add missing GObject.TYPE_GTYPE (Martin Pitt) * Fix "distcheck" and tests with out-of-tree builds (Martin Pitt) * Add GtkComboBoxEntry compatibility (Paolo Borelli) 3.3.1 - 2012-04-30 ------------------ * GSettings: allow extra keyword arguments (Giovanni Campagna) (:bzbug:`675105`) * pygtkcompat: Correct Userlist module use (Jose Rostagno) (:bzbug:`675084`) * Add release-news make rule (Martin Pitt) * Add "make check.nemiver" target (Martin Pitt) * Test flags and enums in GHash values (Martin Pitt) (:bzbug:`637466`) * tests: Activate test_hash_in and apply workaround (Martin Pitt) (:bzbug:`666636`) * Add special case for Gdk.Atom array entries from Python (Martin Pitt) (:bzbug:`661709`) * test_gdbus: Call GetConnectionUnixProcessID() with correct signature (Martin Pitt) (:bzbug:`667954`) * Add test case for Gtk.ListStore custom sort (Martin Pitt) (:bzbug:`674475`) * GTK overrides: Add missing keyword arguments (Martin Pitt) (:bzbug:`660018`) * [API change] Add missing override for TreeModel.iter_previous() (Martin Pitt) (:bzbug:`660018`) * pygi-convert.py: Drop obsolete drag method conversions (Martin Pitt) (:bzbug:`652860`) * tests: Replace deprecated assertEquals() with assertEqual() (Martin Pitt) * Plug tiny leak in constant_info_get_value (Paolo Borelli) (:bzbug:`642754`) * Fix len_arg_index for array arguments (Bastian Winkler) (:bzbug:`674271`) * Support defining GType properties from Python (Martin Pitt) (:bzbug:`674351`) * Handle GType properties correctly (Bastian Winkler) (:bzbug:`674351`) * Add missing GObject.TYPE_GTYPE (Martin Pitt) * Fix test_mainloop.py for Python 3 (Martin Pitt) * Make callback exception propagation test stricter (Martin Pitt) (:bzbug:`616279`) * [API add] Add context management to freeze_notify() and handler_block(). (Simon Feltman) (:bzbug:`672324`) * Add support for GFlags properties (Martin Pitt) (:bzbug:`620943`) * [API add] Wrap GLib.Source.is_destroyed() method (Martin Pitt) (:bzbug:`524719`) * Fix error message when trying to override a non-GI class (Martin Pitt) (:bzbug:`646667`) * Fix segfault when accessing __grefcount__ before creating the GObject (Steve Frécinaux) (:bzbug:`640434`) * [API change] Do not bind gobject_get_data() and gobject_set_data() (Steve Frécinaux) (:bzbug:`641944`) * Add test case for multiple GLib.MainLoop instances (Martin Pitt) (:bzbug:`663068`) * Add a ccallback type which is used to invoke callbacks passed to a vfunc (John (J5) Palmieri) (:bzbug:`644926`) * Regression test: marshalling GValues in GHashTable (Alberto Mardegan) (:bzbug:`668903`) * Update .gitignore (Martin Pitt) * Fix "distcheck" and tests with out-of-tree builds (Martin Pitt) * Add a pep8 check to the makefile (Johan Dahlin) (:bzbug:`672627`) * PEP8 whitespace fixes (Johan Dahlin) (:bzbug:`672627`) * PEP8: Remove trailing ; (Johan Dahlin) (:bzbug:`672627`) * tests: Replace deprecated Python API (Martin Pitt) * Fail tests if they use or encounter deprecations (Martin Pitt) * Do not run tests in two phases any more (Martin Pitt) * test_overrides: Find local gsettings schema with current glib (Martin Pitt) * Add GtkComboBoxEntry compatibility (Paolo Borelli) (:bzbug:`672589`) * Correct review comments from Martin (Johan Dahlin) (:bzbug:`672578`) * Correct pyflakes warnings/errors (Johan Dahlin) (:bzbug:`672578`) * Make tests fail on CRITICAL logs, too, and apply to all tests (Martin Pitt) * Support marshalling GI_TYPE_TAG_INTERFACE (Alberto Mardegan) (:bzbug:`668903`) * Fix warnings on None values in added tree/list store rows (Martin Pitt) (:bzbug:`672463`) * pygtkcompat test: Properly clean up PixbufLoader (Martin Pitt) 3.2.0 - 2012-03-26 ------------------ * No changes since 3.1.93 except version number. 3.1.93 - 2012-03-22 ------------------- * Fix warnings on None values in added tree/list store rows. (:bzbug:`672463`, Martin Pitt) * Support marshalling GI_TYPE_TAG_INTERFACE (:bzbug:`668903`, Alberto Mardegan) * test_overrides: Find local gsettings schema with current glib (Martin Pitt) * pygtkcompat test: Properly clean up PixbufLoader (Martin Pitt) 3.1.92 - 2012-03-19 ------------------- * Correct Gtk.TreePath.__iter__ to work with Python 3 (Johan Dahlin) * Fix test_everything.TestSignals.test_object_param_signal test case (Martin Pitt) * Add a PyGTK compatibility layer (Johan Dahlin) * pygtkcompat: Remove first argument for get_origin() (Johan Dahlin) * Fix pygtkcompat.py to work with Python 3 (Martin Pitt) * GtkViewport: Add a default values for the adjustment constructor parameters (Johan Dahlin) * GtkIconSet: Add a default value for the pixbuf constructor parameter (Johan Dahlin) * PangoLayout: Add a default value for set_markup() (Johan Dahlin) * Gtk[HV]Scrollbar: Add a default value for the adjustment constructor parameter (Johan Dahlin) * GtkToolButton: Add a default value for the stock_id constructor parameter (Johan Dahlin) * GtkIconView: Add a default value for the model constructor parameter (Johan Dahlin) * Add a default value for column in Gtk.TreeView.get_cell_area() (Johan Dahlin) * Atomic inserts in Gtk.{List,Tree}Store overrides (Martin Pitt) * Fix Gtk.Button constructor to accept use_stock parameter (Martin Pitt) * Correct bad rebase, remove duplicate Window (Johan Dahlin) * Add bw-compatible arguments to Gtk.Adjustment (Johan Dahlin) * GtkTreePath: make it iterable (Johan Dahlin) * Add a default argument to TreeModelFilter.set_visible_func() (Johan Dahlin) * Add a default argument to Gtk.TreeView.set_cursor (Johan Dahlin) * Add a default argument to Pango.Context.get_metrics() (Johan Dahlin) * Fix double-freeing GValues in arrays (Martin Pitt) * Renamed "property" class to "Property" (Simon Feltman) * Fix Python to C marshalling of GValue arrays (Martin Pitt) * Correct the Gtk.Window hierarchy (Johan Dahlin) * Renamed getter/setter instance attributes to fget/fset respectively. (Simon Feltman) * Add Gtk.Arrow/Gtk.Window constructor override (Johan Dahlin) * Fix marshalling to/from Python to work on big endian machines. (Michel Dänzer) * Use gi_cclosure_marshal_generic instead of duplicating it. (Michel Dänzer) * Override Gtk.TreeView.get_visible_range to fix return (René Stadler) * Plug memory leak in _is_union_member (Paolo Borelli) * tests: Split TestInterfaces into separate tests (Sebastian Pölsterl) * README: Update current maintainers (Martin Pitt) 3.1.1 - 2012-02-20 ------------------ * Don't use C99 style (Sebastian Pölsterl) * Add test for GPtrArray with transfer full (Martin Pitt) * Drop obsolete g_thread_init() (Martin Pitt) * Fix deprecated g_source_get_current_time() (Martin Pitt) * Fix deprecated g_value_[gs]et_char() (Martin Pitt) * Make pygiconvert.sh correctly convert gtk.gdk.x11_* (Simon Schampijer) * Raise required glib version to 2.31 because of g_value_(get|set)_schar (Sebastian Pölsterl) * Fix cset_first typo (Dieter Verfaillie) * pygi-convert: Handle Clutter and Cogl (Bastian Winkler) * Provide access to gpointer struct values (Cédric Krier) * Add some GType tests (Paolo Borelli) * Split GStrv and array variant tests in their own classes (Paolo Borelli) * Add unit test for builder's connect_after (Paolo Borelli) * fix GtkBuilder signal connection 'after' logic (Ryan Lortie) * test(1) uses '=' to test if strings are identical (Patrick Welche) * pygspawn: improve error checking (Ryan Lortie) 3.0.4 - 2012-02-09 ------------------ * Revert "Convert all strings to utf-8 encoding when retrieving from TreeModel" (Martin Pitt) * Fixed bug where GObject.property did not respect minimum and maximum values (Sebastian Pölsterl) * Remove mention of removed option --enable-docs (Tomeu Vizoso) 3.1.0 - 2012-02-06 ------------------ * Updated DOAP file to only include people currently actively working on the project (Sebastian Pölsterl) * Revert "Convert all strings to utf-8 encoding when retrieving from TreeModel" (Sebastian Pölsterl) * tests: Fixed issues with python3 (Sebastian Pölsterl) * Properly distinguish between different integer types for properties (Sebastian Pölsterl) * Distinguish between GArray and GPtrArray when cleaning up (Sebastian Pölsterl) * Add null_gerror_callback unit test (Paolo Borelli) * pyglib_error_check: Re-add missing NULL check (Martin Pitt) * Add tests/runtests-windows.py to source tarball (Michael Culbertson) * Don't issue a depreciation warning for GtkDialog's NO_SEPARATOR flag, even when unused (Sebastian Pölsterl) * Fix bool() operations on GLib.Variant objects (Nirbheek Chauhan) * Fix hash() and __eq__() for GLib.Variant objects (Nirbheek Chauhan) * Fix method names of callback tests (Martin Pitt) * Cairo: add missing braces around array-of-struct definition (Will Thompson) * g_instance_init: cast to PyGObject * as needed (Will Thompson) * Fix a few set-but-not-used warnings. (Will Thompson) * pygmainloop: allow for extra arguments in 'quit' method (Stefano Facchini) * Fix bytearray test compatibility with python3 (Alexandre Rostovtsev) * Respect transfer-type when demarshalling GErrors (Alberto Mardegan) * Support GHashTable and GError as callback/closure arguments (Alberto Mardegan) * Don't leak when marshalling GErrors to C (Will Thompson) * Support functions which return GError (Will Thompson) * Fix indentation of _pygi_argument_to_object() (Alberto Mardegan) * Avoid C99 syntax. (Paolo Borelli) * Connect to first action of a radio group. (Paolo Borelli) * Use g_slist_free_full in pygi-closure. (Paolo Borelli) * Avoid O(n^2) behavior when marshalling lists (Paolo Borelli) * Handle NULL as a valid case of a char** array (Paolo Borelli) * Branching, bump version to 3.1.0 (Tomeu Vizoso) * Add notes about branching to HACKING (Tomeu Vizoso) * Fixed bug where GObject.property did not respect minimum and maximum values (Sebastian Pölsterl) * Remove mention of removed option --enable-docs (Tomeu Vizoso) * Fix sebp's name in NEWS (Tomeu Vizoso) 3.0.3 - 2011-12-12 ------------------ * Convert all modifier constants to Gdk.ModifierType (Manuel Quiñones) * Convert all strings to utf-8 encoding when retrieving from TreeModel (Sebastian Pölsterl) * add test for bytearray variants (John (J5) Palmieri) * handle NULL arrays correctly for each array type (John (J5) Palmieri) * Revert "Revert "Fix array termination and size calculation"" (John (J5) Palmieri) * pygmainloop: avoid lockups if multiple glib.MainLoop exist (Owen W. Taylor) * Properly chain up to the class that implements a given vfunc. (Tomeu Vizoso) * Revert "Fix array termination and size calculation" (Tomeu Vizoso) * Fix array termination and size calculation (Holger Berndt) * pygi-convert: fix for Pango.Alignment (Daniel Drake) * pygi-convert: fix for Gtk.Orientation (Daniel Drake) * Add tests for calling closures (Martin Pitt) * fix marshaling of arrays of GVariants (Mikkel Kamstrup Erlandsen) 3.0.2 - 2011-10-21 ------------------ * Add tests for boxed properties. (Ignacio Casal Quinteiro) * Allow GBoxed types as property (Timo Vanwynsberghe) * when converting an object with transfer none, make sure the wrapper owns a ref (John (J5) Palmieri) * unit test for checking ref count of object param in signals (John (J5) Palmieri) * Gdk overrides: Unbreak for Gdk-2.0 (Martin Pitt) * Do union member checks for unions that are parameters (John (J5) Palmieri) 3.0.1 - 2011-09-30 ------------------ * when checking instances union members are same type as parent * add a floating flag to pygobjects * Revert "Fix refcount bug by not creating python wrapper during gobject init stage" 3.0.0 - 2011-09-19 ------------------ * up version required of gobject-introspection to 1.29.0 (John (J5) Palmieri) * fix most warnings (John (J5) Palmieri) 2.90.4 - 2011-09-15 (3.0 pre-release) ------------------------------------- * do not pass in len(str) to the length argument of gtk_test_buffer_insert* apis (John (J5) Palmieri) * Switch tarball compression format to tar.xz only. (Dieter Verfaillie) * Remove pygtk_version attribute from internal gi._gobject module. (Dieter Verfaillie) * remove overridesdir from the .pc file and add it to the gi module (John (J5) Palmieri) * fix tests to correctly construct a dummy Gtk.TargetEntry (John (J5) Palmieri) * we now assume that C arrays of structs are flat so memcpy them when marshalling (John (J5) Palmieri) * only update the arg counts once if child arg comes before parent arg (John (J5) Palmieri) * Fix refcount bug by not creating python wrapper during gobject init stage (John (J5) Palmieri) * don't destroy just created wrapper when object is created via g_object_new (John (J5) Palmieri) * Remove deprecated API from pygobject.h (Steve Frécinaux) * Convert gtk.TRUE/FALSE to Python True/False. (Marcin Owsiany) * Drop legacy __gobject_init__ method of GObject.Object. (Steve Frécinaux) * AM_CHECK_PYTHON_LIBS does not work for lib64 (Dieter Verfaillie) * Remove common_ldflags from Makefile.am as it is no longer used. (Dieter Verfaillie) * check if object is actually a PyGFlag before trying to access g_type (John (J5) Palmieri) * fix regression - add instance type checks since Py3 no longer does this for us (John (J5) Palmieri) * refactor in/out marshalling to be to_py/from_py (John (J5) Palmieri) * Examples: fix cairo-demo.py imports (Dieter Verfaillie) * Fix paths and add missing overridesdir variable used in uninstalled pkgconfig file (Dieter Verfaillie) * Remove no longer used variables from pkgconfig files (Dieter Verfaillie) * docs/Makefile.am and m4/python.m4: Python3 portability fixes (Dieter Verfaillie) * Refactor and clean Makefile.am files (Dieter Verfaillie) * Remove all PLATFORM_VERSION = 2.0 traces (Dieter Verfaillie) * Remove gi/tests/ directory as all the tests now live in tests/ (Dieter Verfaillie) * autogen.sh: Use autoreconf instead of a custom script and honor ACLOCAL_FLAGS (Dieter Verfaillie) * use improved python.m4 macros to search for Python headers and libs (Dieter Verfaillie) * Make maintiner mode enabled by default (Javier Jardón) * Disable documentation for now since they are completely wrong for GI. (Dieter Verfaillie) * Fix documentation installation directory (Dieter Verfaillie) * Remove distutils based build system. (Dieter Verfaillie) * [gtk-demo] Fix syntax highlighter encoding issue (Dieter Verfaillie) * overrides: add constants for atoms (Ignacio Casal Quinteiro) * Drop pygobject_construct() from public API. (Steve Frécinaux) 2.90.3 - 2011-08-31(3.0 pre-release) ------------------------------------ * support skip annotation for return values (John (J5) Palmieri) * Test GPtrArray regression (Xavier Claessens) * Drop support for old constructor style. (Steve Frécinaux) * Drop support for sink functions. (Steve Frécinaux) * Reinstate copying of in-line structs in arrays (Mike Gorse) * fix inline struct array handling (John (J5) Palmieri) * fix on demos (Dieter Verfaillie) * Added support for __setitem__ to TreeModel and support for slices to TreeModelRow (Sebastian Pölsterl) * Convert ACCEL_* constants into Gtk.AccelFlags. (Olav Vitters) * Convert TREE_VIEW_DROP_* constants into Gtk.TreeViewDropPosition (Olav Vitters) 2.90.2 - 2011-08-18 (3.0 pre-release) ------------------------------------- * remove tests that were removed from gi (John (J5) Palmieri) * don't calculate item_size using is_pointer (John (J5) Palmieri) * Updated signal example to use GObject introspection (Timo Vanwynsberghe) * Updated properties example to use GObject introspection (Timo Vanwynsberghe) * Add override for GLib.Variant.split_signature() (Martin Pitt) * [pygi-convert.sh] Handle the import of pygtk and require Gtk 3.0 (Timo Vanwynsberghe) * Install pygobject.h again. (Ignacio Casal Quinteiro) * update the doap file (John (J5) Palmieri) 2.90.1 - 2011-08-14 (3.0 pre-release) ------------------------------------- * pass exta keywords to the Box constructor (John (J5) Palmieri) * add (Tree|List)Store set method override (John (J5) Palmieri) * add test for object arrays (John (J5) Palmieri) * only support C pointer arrays for structs and objects (John (J5) Palmieri) * revert Gtk.Window override because it causes issues with subclasses (John (J5) Palmieri) * take GIL in _pygi_invoke_closure_free (bug :bzbug:`647016`) (Jonathan Matthew) * Add a default parameter to GtkTreeModel.filter_new (Johan Dahlin) * Add vbox/action_area properties (Johan Dahlin) * Add a couple of constructors (Johan Dahlin) * Do not always pass in user_data to callbacks. (Johan Dahlin) * Add a default detail value for Widget.render_icon (Johan Dahlin) * Add an override for Gdk.color_parse() (Johan Dahlin) * Support function calling with keyword arguments in invoke. (Laszlo Pandy) * remove references to deprecated GI_INFO_TYPE_ERROR_DOMAIN (John (J5) Palmieri) * Fix gobject vs. gi.repository warning (Martin Pitt) * make GObject and GLib able to take overrides (John (J5) Palmieri) * avoid dependency issue by importing the internal gobject (John (J5) Palmieri) * fix tests to use the new GLib module (John (J5) Palmieri) * add DynamicGLibModule which works like DynamicGObjectModule (John (J5) Palmieri) * refactor, add objects and types to the correct internal module (John (J5) Palmieri) * rename the pyglib shared library so we don't load the old one (John (J5) Palmieri) * refactor tests to only use PyGObject 3 syntax (John (J5) Palmieri) * refactor the internal _glib module to import correct modules (John (J5) Palmieri) * refactor to use the new internal _glib and _gobject modules (John (J5) Palmieri) * refactor gi module to import and use internal _gobject module (John (J5) Palmieri) * move the static bits internal to gi and refactor build files (John (J5) Palmieri) * remove pygtk.py (John (J5) Palmieri) * introspection is no longer optional (John (J5) Palmieri) * up platform version to 3.0 (John (J5) Palmieri) * [gi] Handle GVariants from callback return values (Martin Pitt) * Handle GVariants for callback arguments (Martin Pitt) * [gi] Fix crash: check return value of _invoke_state_init_from_callable_cache() before continuing. (Laszlo Pandy) * [gi] Pass gtype as first parameter to vfuncs (instead of using kwargs). (Laszlo Pandy) * remove codegen (John (J5) Palmieri) * remove some left over ifdefs to complete merge of the invoke-rewrite branch (John (J5) Palmieri) * rename pygi-invoke-ng to pygi-invoke (John (J5) Palmieri) * make invoke-ng the only invoker (John (J5) Palmieri) * Merge branch 'master' into invoke-rewrite (John (J5) Palmieri) * Merge branch 'master' into invoke-rewrite (John (J5) Palmieri) * split the marshalling routines into two source files (John (J5) Palmieri) * Ship tests/te_ST@nouppera in release tarballs for tests to succeed (Martin Pitt) * [invoke] break out caller_allocates allocating into its own function (John (J5) Palmieri) * [invoke] missed a bit when removing constructor_class usage (John (J5) Palmieri) * [invoke] don't hold on to the constructor class, just add a TODO (John (J5) Palmieri) * [gi] Port test_properties from static gio to GI Gio (Martin Pitt) * [python3] Fix maketrans import (Martin Pitt) * [caching] remove all inline compiler flags (John (J5) Palmieri) * [caching] refactor function names to be less confusing (John (J5) Palmieri) * [overrides] deprecate the use of type keyword MessageDialog constructor (John (J5) Palmieri) * gdbus tests: Fix hang if test case fails (Martin Pitt) * use an enum instead of booleans to denote function type (John (J5) Palmieri) * rename aux arguments to child arguments to make their purpose clearer (John (J5) Palmieri) * Fixed the cairo example (Timo Vanwynsberghe) * Add override binding for Gtk.ListStore.prepend(). (Adam Dingle) * Fix crash in Gtk.TextIter overrides (Martin Pitt) * use gssize instead of int for arg indexes (John (J5) Palmieri) * [cache] remove refrence to default value as it is not implemented yet (John (J5) Palmieri) * Handle arguments that are flags correctly (Sebastian Pölsterl) * correctly initialize the _gi_cairo_functions array to be zero filled (John (J5) Palmieri) * correctly initialize the _gi_cairo_functions array to be zero filled (John (J5) Palmieri) * pass in the address of the gerror, not the gerror itself (John (J5) Palmieri) * [gi] handle marshalling gerrors arguments for signals (John (J5) Palmieri) * [gi-invoke-ng] fix NULL check to check before we access the cache struct (John (J5) Palmieri) * [gi-tests] add test for PyGObject->PyObject TreeModel storage (John (J5) Palmieri) * [gtk-overrides] special case TreeModel columns of PYGOBJECT types (John (J5) Palmieri) * [gi-invoke-ng] copy structs when transfer is full for array (John (J5) Palmieri) * [gtk-override] print warning if user imports Gtk 2.0 (John (J5) Palmieri) * [gtk-overrides] allow the message_type keyword to be used for MessageDialogs (John (J5) Palmieri) * Add support for enums in gobject.property (Johan Dahlin) * Add support for enums in gobject.property (Johan Dahlin) * [gi-invoke-ng] use g_slice for allocating GValues that are caller allocated (John (J5) Palmieri) * [gi-invoke-ng] Convert Overflow errors to ValueErrors when marshalling integers (John (J5) Palmieri) * [gi-invoke-ng] only cache caller allocates for interfaces as some API are broken (John (J5) Palmieri) * [gi-invoke-ng] handle in pointer array marshalling (John (J5) Palmieri) * Adding GPtrArray tests (Alex Eftimie) * [gi-invoke-ng] fix array element offset calculations (John (J5) Palmieri) * [gi] don't clean up arguments that weren't yet processed during in arg failure (John (J5) Palmieri) * [gi-overrides] use new instead of init when constructing a GLib.VariantBuilder (John (J5) Palmieri) * [gi-invoke-ng] actual code to import overrides (John (J5) Palmieri) * [gi-invoke-ng] import pytypes so we get overrides (John (J5) Palmieri) * [gi-invoke-ng] handle gvariants now that they are not foreign (John (J5) Palmieri) * [gi-invoke-ng] do not try to clean up NULL arguments (John (J5) Palmieri) * Merge branch 'master' into invoke-rewrite (John (J5) Palmieri) * Merge branch 'master' into invoke-rewrite (John (J5) Palmieri) * closure: avoid double free crash (Ignacio Casal Quinteiro) * Added __eq__ method for Gdk.Color and Gdk.RGBA (Jason Siefken) * closure: Check the out arg is not null. Fixes bug :bzbug:`651812` (Ignacio Casal Quinteiro) * Use constants instead of literals (Tomeu Vizoso) * GVariant has now a GType, take that into account (Tomeu Vizoso) * GVariantType is a boxed struct (Tomeu Vizoso) * Use _gi.Struct to wrap fundamentals (Tomeu Vizoso) * Merge gi/HACKING into /HACKING (Tomeu Vizoso) * Fix GC-related crash during PyGObject deallocation (Daniel Drake) * [gi-invoke-ng] enable invoke-ng by default (John (J5) Palmieri) * [gi-invoke-ng] add code to clean up when input values fail to marshal (John (J5) Palmieri) * [gi-invoke-ng] add hash cleanup routines (John (J5) Palmieri) * [gi-invoke-ng] handle arrays with transfers of GI_TRANSFER_CONTAINER (John (J5) Palmieri) * [gi-invoke-ng] add list cleanup routines (John (J5) Palmieri) * indentation fix (John (J5) Palmieri) * [gi-invoke-ng] add out array cleanup (John (J5) Palmieri) * [gi-invoke-ng] do not allocate null terminator for garray (John (J5) Palmieri) * [gi-invoke-ng] add array cleanup for in arrays (John (J5) Palmieri) * [gi-invoke-ng] remove remaining bits of the invoke stage state machine (John (J5) Palmieri) * [gi-invoke-ng] revamp cleanup framework to be orthogonal to cache setup (John (J5) Palmieri) * [gi-invoke-ng] stub out a cleaner way of cleaning up after ourselves (John (J5) Palmieri) * Doc Extractor: Correct the logic of the --no-since option. (José Alburquerque) * Doc Extractor: Add a --no-since option. (José Alburquerque) * [gi-invoke-ng] tweek cleanup routines (John (J5) Palmieri) * Fix symbol names to be locale independent (Martin Pitt) * [gi] pygi-convert.sh: Convert gtk.gdk.CROSSHAIR (Martin Pitt) * [gi-invoke-ng] handle filename cleanup with the utf8 cleanup function (John (J5) Palmieri) * [gi-invoke-ng] handle caller allocates cleanup (John (J5) Palmieri) * [gi-invoke-ng] refactor the cleanup code and add utf8 cleanup as initial test (John (J5) Palmieri) * use PyCapsule when importing pycairo/require pycairo 1.10.0 for python3 builds (John (J5) Palmieri) * [python3] fix build. PYcairo_IMPORT doesn't exists anymore (Ignacio Casal Quinteiro) * Updated DOAP file (Sebastian Pölsterl) * [gi] Don't create variant twice (Sebastian Pölsterl) * pygi-convert.sh: Make sure the uppercase GObject module is imported instead of the lowercase (Sebastian Pölsterl) * [gi] Removed hack to avoid using GLib.Variant.new_variant. (Sebastian Pölsterl) * [gi] Added additional test case for GVariant handling (Sebastian Pölsterl) * [gi] Added support for GVariant arguments (Sebastian Pölsterl) * fix static ABI for setting string gvalues from python objects (John (J5) Palmieri) * dsextras.py: ensure eol characters are preserved when writing template files (so \n does not become \r\n) (Dieter Verfaillie) * dsextras.py: remove \r as wel as \n character (Dieter Verfaillie) * use PyCapsule when importing pycairo/require pycairo 1.10.0 for python3 builds (John (J5) Palmieri) * [python3] fix build. PYcairo_IMPORT doesn't exists anymore (Ignacio Casal Quinteiro) * Updated DOAP file (Sebastian Pölsterl) * [gi] Don't create variant twice (Sebastian Pölsterl) * pygi-convert.sh: Make sure the uppercase GObject module is imported instead of the lowercase (Sebastian Pölsterl) * [gi] Removed hack to avoid using GLib.Variant.new_variant. (Sebastian Pölsterl) * [gi] Added additional test case for GVariant handling (Sebastian Pölsterl) * [gi-invoke-ng] fix prototype (John (J5) Palmieri) * [gi-invoke-ng] create new framework for cleaning up args (John (J5) Palmieri) * [gi] Added support for GVariant arguments (Sebastian Pölsterl) * [gi-invoke-ng] fix marshal header that is no longer part of pygi-arguments.h (John (J5) Palmieri) * [gi-invoke-ng] code style space fixes (John (J5) Palmieri) * [gi-invoke-ng] don't decref value taken from a dict as it is borrowed (John (J5) Palmieri) * [gi-invoke-ng] return None when appropriate so we don't crash (John (J5) Palmieri) * [gi-invoke-ng] fix aux value caching (John (J5) Palmieri) * [gi-invoke-ng] backport handling flags with no gtype (John (J5) Palmieri) * [gi-invoke-ng] backport raw gvalue handling (John (J5) Palmieri) * [gi-invoke-ng] marshal instances seperately since they differ slightly from other args (John (J5) Palmieri) * [gi-invoke-ng] refactor FunctionCache to be more generic CallableCache (John (J5) Palmieri) * [gi-invoke-rewrite] backport glib error handling (John (J5) Palmieri) * [gi-invoke-ng] backport closure passing from invoke (John (J5) Palmieri) * [gi-invoke-ng] handle vfuncs and fix cosntrutors (John (J5) Palmieri) * [gi-invoke-ng] handle foreign types correctly (John (J5) Palmieri) * [gi] remove the class parameter from the argument list of constructors (John (J5) Palmieri) * fix static ABI for setting string gvalues from python objects (John (J5) Palmieri) * dsextras.py: ensure eol characters are preserved when writing template files (so \n does not become \r\n) (Dieter Verfaillie) * dsextras.py: remove \r as wel as \n character (Dieter Verfaillie) * [gi] make new invoke-ng codepath compile correctly (John (J5) Palmieri) * [gi] conditionalize invoke code paths (John (J5) Palmieri) * [gi] revert back to the type.py from master (John (J5) Palmieri) * [gi] revert pygi-argument.h and move the invoke-ng code to pygi-marshal.h (John (J5) Palmieri) * Merge branch 'master' into invoke-rewrite (John (J5) Palmieri) * [gi] foreign types now take interface infos instead of type infos (John (J5) Palmieri) * Fix GSchema tests for separate build tree (Martin Pitt) * [gi] start of merge from master (John (J5) Palmieri) * [gi] marshal raw closures (John (J5) Palmieri) * pygi-convert.sh add GObject.xxx and webkit (John Stowers) * pygi-convert.sh remove gobject tests, GObject works now (John Stowers) * [gi-demos] add pickers demo (John (J5) Palmieri) * [gi-demos] add menu demo (John (J5) Palmieri) * [gi-overrides] fix exception block so it works in Python 2.5 (John (J5) Palmieri) * Revert "Deduce PYTHON_LIBS in addition to PYTHON_INCLUDES" (Martin Pitt) * setup.py: fix user_access_control option (Dieter Verfaillie) * [gi] Respect the MessageType for Gtk.MessageDialog (Martin Pitt) * [gi] Do not require signature for D-BUS methods without arguments (Martin Pitt) * [gi-overrides] TreeViewColumn.set_cell_data_func func_data can be None (John Stowers) * [gi-demos] dont try and run demos that represent directories (John Stowers) * [gi-demos] some python 3 compat fixes (John (J5) Palmieri) * [gi-demos] add liststore demo (John (J5) Palmieri) * [gi-demos] catch the correct error class (John (J5) Palmieri) * Do not leak python references when using the gobject.property() helper. (Steve Frécinaux) * handle uchar as bytes, not strings in python 3 (John (J5) Palmieri) * [gi-overrides] handle unichar gvalues when setting treemodels (John (J5) Palmieri) * [gi-overrides] special case python 2 keywords that crept in (John (J5) Palmieri) * check for the py3 _thread module in configure.ac if thread is not found (John (J5) Palmieri) * [gi-demos] add iconview demo (John (J5) Palmieri) * [gi] wrap the keyword argument in a dict so we don't break Python 2.5 (John (J5) Palmieri) * [gi-demos] add the combobox with string ids section to the demos (John (J5) Palmieri) * [gi-overrides] add an override for Gdk.RGBA (John (J5) Palmieri) * [gi-demos] fix up search-entry to reflect annotations fixed in Gtk+ master (John (J5) Palmieri) * [gi-demos] add search entry demo (John (J5) Palmieri) * [gi] wrap map in a list for Python 3 compat (John (J5) Palmieri) * [gi-demos] fix up the validation combobox (John (J5) Palmieri) * add overridesdir variable in the .pc file for 3rd party overrides (John (J5) Palmieri) * setup.py: Set bdist_wininst user-access-control property (Dieter Verfaillie) * Fix uninitialized variable in gi.require_version() (Martin Pitt) * Run tests with LC_MESSAGES="C" (Martin Pitt) * [gi-overrides] override Gtk.stock_lookup to not return success (John (J5) Palmieri) 2.28.6 - 2011-06-11 ------------------- * closure: avoid double free crash (Ignacio Casal Quinteiro) * [gi] backport of "GVariant has a GType" fe386a (John (J5) Palmieri) * [gi] fixes to backport commit 6b5a65 - in older glib GVariants are still structs (John (J5) Palmieri) * GVariantType is a boxed struct (Tomeu Vizoso) * Use _gi.Struct to wrap fundamentals (Tomeu Vizoso) * Added __eq__ method for Gdk.Color and Gdk.RGBA (Jason Siefken) * Remove useless import (Ignacio Casal Quinteiro) * Revert "[gi] Removed hack to avoid using GLib.Variant.new_variant." (Ignacio Casal Quinteiro) * closure: Check the out arg is not null. Fixes bug :bzbug:`651812` (Ignacio Casal Quinteiro) * Fix GC-related crash during PyGObject deallocation (Daniel Drake) * Fix symbol names to be locale independent (Martin Pitt) * Updated DOAP file (Sebastian Pölsterl) 2.28.4 - 2011-04-18 ------------------- * Version bump to 2.24.4 (Sebastian Pölsterl) * [gi] Don't create variant twice (Sebastian Pölsterl) * pygi-convert.sh: Make sure the uppercase GObject module is imported instead of the lowercase (Sebastian Pölsterl) * [gi] Removed hack to avoid using GLib.Variant.new_variant. (Sebastian Pölsterl) * [gi] Added additional test case for GVariant handling (Sebastian Pölsterl) * [gi] Added support for GVariant arguments (Sebastian Pölsterl) * Fix ABI break in old static bindings. (Steve Frécinaux) * fetch size from an enum type (Mike Gorse) * dsextras.py: ensure eol characters are preserved when writing template files (so \n does not become \r\n) (Dieter Verfaillie) 2.28.3 - 2011-03-23 ------------------- * fix a typo when converting objects to strings gvalues (John (J5) Palmieri) 2.28.2 - 2011-03-22 ------------------- * fix static ABI for setting string gvalues from python objects (John (J5) Palmieri) * Fix GSchema tests for separate build tree (Martin Pitt) * GIO tests: Fix remaining test case for separate build tree (Martin Pit * GIO tests: Fix for separate build tree (Martin Pitt) 2.28.1 - 2011-03-21 ------------------- * pygi-convert.sh remove gobject tests, GObject works now (John Stowers) * pygi-convert.sh add GObject.xxx and webkit (John Stowers) * [gi] marshal raw closures (John (J5) Palmieri) * Revert "Deduce PYTHON_LIBS in addition to PYTHON_INCLUDES" (Martin Pitt) * setup.py: fix user_access_control option (Dieter Verfaillie) * [gi-overrides] fix marshalling pygobjects in treemodels (John (J5) Palmieri) * [gi] Respect the MessageType for Gtk.MessageDialog (Martin Pitt) * [gi] Do not require signature for D-BUS methods without arguments (Martin Pitt) * [gi-demos] add pickers demo (John (J5) Palmieri) * [gi-demos] add menu demo (John (J5) Palmieri) * [gi-overrides] TreeViewColumn.set_cell_data_func func_data can be None * [gi-demos] dont try and run demos that represent directories (John Stowers) * [gi-overrides] fix exception block so it works in Python 2.5 (John (J5) Palmieri) 2.28.0 - 2011-03-08 ------------------- * [gi-demos] some python 3 compat fixes (John (J5) Palmieri) * [gi-demos] catch the correct error class (John (J5) Palmieri) * Try not to sink objects returned by C functions. (Steve Frécinaux) * Do not leak python references when using the gobject.property() helper. (Steve Frécinaux) * [gi] fix try except blocks so they work in Python 2.5 (John (J5) Palmieri) * handle uchar as bytes, not strings in python 3 (John (J5) Palmieri) * [gi-overrides] handle unichar gvalues when setting treemodels (John (J5) Palmieri) * [gi-overrides] special case python 2 keywords that crept in (John (J5) Palmieri) * check for the py3 _thread module in configure.ac if thread is not found (John (J5) Palmieri) * [gi-demos] add iconview demo (John (J5) Palmieri) * [gi] wrap the keyword argument in a dict so we don't break Python 2.5 (John (J5) Palmieri) * [gi-demos] add the combobox with string ids section to the demos (John (J5) Palmieri) * [gi-overrides] add an override for Gdk.RGBA (John (J5) Palmieri) * [gi-demos] fix up search-entry to reflect annotations fixed in Gtk+ master (John (J5) Palmieri) * [gi-demos] add search entry demo (John (J5) Palmieri) * [gi] wrap map in a list for Python 3 compat (John (J5) Palmieri) * [gi-demos] fix up the validation combobox (John (J5) Palmieri) * add overridesdir variable in the .pc file for 3rd party overrides (John (J5) Palmieri) * [gi] remove unref for closures since they are floating objects that get sunk (John (J5) Palmieri) * setup.py: Set bdist_wininst user-access-control property (Dieter Verfaillie) * Fix uninitialized variable in gi.require_version() (Martin Pitt) * Run tests with LC_MESSAGES="C" (Martin Pitt) * [gi-overrides] override Gtk.stock_lookup to not return success (John (J5) Palmieri) 2.27.91 - 2011-02-28 (2.28 pre-release) --------------------------------------- * [gi-tests] use Gdk.test_simulate_button instead of emitting event ourselves (John (J5) Palmieri) * [gi-tests] tests for EventButton override. (Laszlo Pandy) * Skip interfaces when checking for conflicts in the MRO (Tomeu Vizoso) * [gi-overrides] Add event methods to all event union members (John (J5) Palmieri) * [gi] check to see if object is a member of a union when validating paramaters (John (J5) Palmieri) * [gi] Remove DyanmicModule.load() to _load() to prevent overriding GI attrs. (Laszlo Pandy) * Test case with John's fix for crash with C arrays and a GError is set. (Laszlo Pandy) * [gi-overrides] fix setting rows in treeview to accept None as a value (John (J5) Palmieri) * [gi] Add value_name for enum and flags from introspection "c:identifier" (if attr is available). (Laszlo Pandy) * Don't force loading of DynamicModule until set in sys.modules (Laszlo Pandy) * Fix flags with multiple names for the same value. (Laszlo Pandy) * [gi-demos] add liststore demo (John (J5) Palmieri) * [gi-demos] run through the demos and remove the FIXMEs that have been fixed (John (J5) Palmieri) * Load typelibs at import time, add gi.require_version() (Tomeu Vizoso) * use GValue support to marshal GtkTreeModel values correctly (John (J5) Palmieri) * [gi] pass raw GValues instead of trying to marshal them (John (J5) Palmieri) * [gi-demos] add icon view edit and drag-and-drop demo (John (J5) Palmieri) * [gi] Register GType for non-GType enums and flags at runtime. (Laszlo Pandy) * [gi-demos] add info bars demo (John (J5) Palmieri) * tests/runtests.py: Add missing "import sys" (Martin Pitt) * [gi] Add Pythonic gdbus method invocation (Martin Pitt) * Skip GError out parameters in Python closure. (Laszlo Pandy) * [gi-demos] added rotate text demo (John (J5) Palmieri) * [gi-demos] add images demo (John (J5) Palmieri) * [gi-demos] add pixbuf demo (John (J5) Palmieri) * [gi-demos] remove fixmes from print demo, fixed in pango (John (J5) Palmieri) * [gi-demos] add printing demo (John (J5) Palmieri) * [gi-overrides] add cursor overrides (John (J5) Palmieri) * [gi-demos] add the links demo (John (J5) Palmieri) * [gi-demos] add expander demo (John (J5) Palmieri) * [gi-overrides] use pop instead of del and add extra tests for Gtk.Table kwargs (John (J5) Palmieri) * [tests] Separate processes for GI and static binding tests. (Laszlo Pandy) * [GI] Remove implicit loading of gi module preserve the code path for static bindings. (Laszlo Pandy) * [gi-demos] add dialogs demo (John (J5) Palmieri) * [gi-overrides] fix typo in GtkTable constructor (John (J5) Palmieri) * [gi-demos] keep popup menu from destroying itself by holding a ref in app class (John (J5) Palmieri) * [gi-overrides] add a Gtk.Menu override for the popup method (John (J5) Palmieri) * [gi-demos] fix the about dialog in appwindow demo (John (J5) Palmieri) * [gi-demos] fix clipboard demo so DnD works (John (J5) Palmieri) * [gi-demos] fix clipboard demo to reflect new API (John (J5) Palmieri) * [gi-demo] Fix color dialog demo to run with new draw, style and color apis (John (J5) Palmieri) * [gi-demos] fix most of the combobox app (John (J5) Palmieri) * Use PyGI type conversion (to fix foreign types) for signal callbacks. (Laszlo Pandy) * [gi-demos] fix drawingarea app to use the new draw api (John (J5) Palmieri) * [gi-overrides] for Gtk 3 alias Gdk.Rectangle to cairo.RectangleInt (John (J5) Palmieri) * [gi-overrides] let user set the proper property names in Gtk.Table (John (J5) Palmieri) * [gi-demos] get appwindow demo working again (John (J5) Palmieri) * [gi-demos] fixed use of tree_iter_get (John (J5) Palmieri) 2.27.90 - 2011-02-11 (2.28 pre-release) --------------------------------------- * fix build to correctly use python-config (John (J5) Palmieri) * Run gio tests separately when enabled (Martin Pitt) * Revert "Remove gio static bindings" (Martin Pitt) * Decrease the refcount for GInitiallyUnowned constructors. (Steve Frécinaux) * Ensure the sink functions are only ran once. (Steve Frécinaux) * Revert "Fix wrong refcount when calling introspected widget constructors" (Steve Frécinaux) * Revert "Fix reference leaks for GInitiallyUnowned objects" (Steve Frécinaux) * Run test suite under dbus-launch (Martin Pitt) * Fix test_gdbus.py to be Python3 friendly (Martin Pitt) * [gi] Provide comfortable GSettings API (Martin Pitt) * Fix vfunc search bug when using GInterfaces and a do_* method. (Laszlo Pandy) * [GI] Add tests for Gtk.Widget.drag_* methods. (Laszlo Pandy) * [python 3] use the right syntaxis to raise exceptions (Ignacio Casal Quinteiro) * [gi] return PYGLIB_MODULE_ERROR_RETURN on error and use pygobject_init (Ignacio Casal Quinteiro) * [gi] return PYGLIB_MODULE_ERROR_RETURN on error (Ignacio Casal Quinteiro) * Fix wrong refcount when calling introspected widget constructors (Steve Frécinaux) * Gdk.Window: Map the standard constructor to the *new* constructor (Simon Schampijer) * Ship tests/org.gnome.test.gschema.xml in dist tarballs (Martin Pitt) * [gi] Add GSettings tests (Martin Pitt) * [gi] Provide GtkTextBuffer.insert_with_tags_by_name() (Martin Pitt) * [gi] Support tag names in GtkTextBuffer.insert_with_tags() (Martin Pitt) * Add MAINTAINERCLEANFILES (Ignacio Casal Quinteiro) * Remove .gitignore files and use git.mk (Ignacio Casal Quinteiro) * pygi-convert.sh: Convert Pango.TabAlign.* (Martin Pitt) * pygi-convert.sh: Drop window -> get_window() conversion (Martin Pitt) * pygi-convert.sh: Don't convert self.window assignments (Martin Pitt) * Fix leaked python reference in python-defined subclasses (Steve Frécinaux) * Add some tests for the number of python refs held at creation time (Steve Frécinaux) * Factor out parameter marshalling from construction functions. (Steve Frécinaux) * [gi] in python 3 an array of uint8 can be bytes but not string (John (J5) Palmieri) * [gi] fix Gio.FileEnumerator to reflect the Python 3 iter protocol (John (J5) Palmieri) * [gi] python 3 fixes (John (J5) Palmieri) * [gi] fix try/except blocks using depricated raise format (John (J5) Palmieri) * [gi] Add docstring to GLib.Variant constructor (Martin Pitt) * [gi] update gdbus test cases for previous GVariant change (Martin Pitt) * [gi] Accept only a single object in GLib.Variant constructor (Martin Pitt) * Speed up _setup_native_vfuncs() (Laszlo Pandy) * Speed up class creation: rewrite _setup_vfuncs() to be much more efficient. (Laszlo Pandy) * pygi-convert.sh: Convert gtk.UI_MANAGER_* (Sebastian Pölsterl) * pygi-convert.sh: Convert gdk.GRAB_* (Sebastian Pölsterl) * [gi] set the gtype GValue correctly (Ignacio Casal Quinteiro) * [gi] use the right argument type for callback (Ignacio Casal Quinteiro) * [gi] Add test cases for GDBus client operations (Martin Pitt) * [gi] Add Variant construction/unpack support for boxed Variants (Martin Pitt) * Merge branch 'windows-setup-fixes' (Dieter Verfaillie) * pygi-convert.sh: GdkPixbuf methods (Thomas Hindoe Paaboel Andersen) * pygi-convert.sh: Gdk.COLORSPACE_RGB (Thomas Hindoe Paaboel Andersen) * [gi] Support nested objects and empty sequences in GLib.Variant building (Martin Pitt) * Uncomment test_gi.TestInterfaceClash (Tomeu Vizoso) * Fix reference leaks for GInitiallyUnowned objects (Steve Frécinaux) * Add tests for refcount of a GObject owned by a library (Steve Frécinaux) * Add a test to check for regular object reference count (Steve Frécinaux) * [gi] Update TreeView.enable_model_drag_{source,dest} to current GTK (Martin Pitt) * Fix a typo in a private symbol name. (Steve Frécinaux) * pygi-convert.sh: Convert glib.source_remove() (Martin Pitt) * Fix typo in previous commit to actually convert glib.GError (Martin Pitt) * pygi-convert.sh: Move some glib bits which are better handled by gobject (Martin Pitt) * Modify override for Gtk.Adjustment to allow position or keyword arguments in __init__(). (Laszlo Pandy) * [gi] Fix small typo in previous commit (Martin Pitt) * [gi] Add pythonic iterator and indexing for string GVariants (Martin Pitt) * Construct structs using default API constructor (Tomeu Vizoso) * pygi-convert.sh: Migrate Gdk.Cursor constructor, and some cursor names (Martin Pitt) * pygi-convert.sh: Handle .window attributes (Martin Pitt) * Also deal with foreign boxed structs (Tomeu Vizoso) * [gi] Convert GErrors to GObject.GError exceptions, and throw them upon returning from calling the C function. (Laszlo Pandy) * pygi-convert.sh: Don't convert glib -> GLib for now (Martin Pitt) * Link libregress.so to GIO_LIBS again (Tomeu Vizoso) * Fix attributes 2BUTTON_PRESS and 3BUTTON_PRESS of Gdk.EventType. (Laszlo Pandy) * [gi] Fixed typo in exception (Sebastian Pölsterl) * [gi] Enable handling of Gdk.EventType.2BUTTON_PRESS and 3BUTTON_PRESS (Sebastian Pölsterl) * Revert "Fix Pango FontDescription override" (Martin Pitt) * Python iterator interface support for GFileEnumerator. (Tony Young) * Remove gio static bindings (Tomeu Vizoso) * [gi] set length when marshalling guint8 erases (Ignacio Casal Quinteiro) * Convert Gdk.Pixbuf to GdkPixbuf.Pixbuf (Sebastian Pölsterl) * Disable calls to PyGILState_* when threads are disabled (Arnaud Charlet) * pygi-convert.sh: Do not comment out set_cell_data_func() calls; these should be ported properly (Martin Pitt) * pygi-convert.sh: Fix match for adding missing imports (Martin Pitt) * pygi-convert.sh: Fix Gtk.Label handling to be idempotent (Martin Pitt) * Remove trailing whitespace from gi/overrides/Gtk.py (Laszlo Pandy) * Fix Pango FontDescription override (Martin Pitt) * tests: Respect existing $GI_TYPELIB_PATH (Martin Pitt) * Merge branch 'value' (Sebastian Pölsterl) * GTK overrides: Do type conversion to column types of ListStore and TreeStore in set_value (Sebastian Pölsterl) * Always register a new GType when a GObject class is subclassed (Steve Frécinaux) * Raise required versions of GLib and GObject-Introspection (Simon van der Linden) * pygi-convert.sh: Handle keysyms (Martin Pitt) * GLib overrides: Add test case for array variant building (Martin Pitt) * Remove cairo.RectangleInt from the foreign module (Tomeu Vizoso) * Dont try to guess the transfer if its a boxed (Tomeu Vizoso) * The tags can be Empty not None. (Ignacio Casal Quinteiro) * Add Pythonic iterators and indexing to GVariant (Martin Pitt) * Add GLib.Variant.unpack() (Martin Pitt) * Add override for gtk_text_buffer_insert_with_tags (Ignacio Casal Quinteiro) * Deduce PYTHON_LIBS in addition to PYTHON_INCLUDES (Simon van der Linden) * Kill JD_CHECK_PYTHON_HEADERS (Simon van der Linden) * Revert "Override Gtk.Box.pack_start and pack_end to set default values to be compliant with pygtk" (Sebastian Pölsterl) * Revert "Override Gtk.CellLayout.pack_start and pack_end to add default values to be compliant with pygtk" (Sebastian Pölsterl) * Revert "Override Gtk.TreeViewColumn.pack_start, pack_end and set_cell_data_func to add default values to be compliant with pygtk" (Sebastian Pölsterl) * pygi-convert.sh: Handle gtk.combo_box_new_text() (Martin Pitt) * Override TreeSortable.set_sort_func and set_default_sort_func to add default values to be pygtk compliant (Sebastian Pölsterl) * Override Gtk.TreeViewColumn.pack_start, pack_end and set_cell_data_func to add default values to be compliant with pygtk (Sebastian Pölsterl) * Override Gtk.CellLayout.pack_start and pack_end to add default values to be compliant with pygtk (Sebastian Pölsterl) * Override Gtk.Paned pack1 and pack2 to add default values to be compliant with pygtk (Sebastian Pölsterl) * Override Gtk.Box.pack_start and pack_end to set default values to be compliant with pygtk (Sebastian Pölsterl) * Handle GObject subclasses in the property helper. (Steve Frécinaux) * Fix handling of unicode for GtkTreeModels (Martin Pitt) * In IntrospectionModule and DynamicModule classes, make all instance attributes start with an underscore. (Laszlo Pandy) * Amend previous enum wrapping commit to remove redundant setting of __info__ attribute. (Laszlo Pandy) * pygi-convert.sh: Handle GdkPixbuf.InterpType (Martin Pitt) * Fix wrapping of enums: Create new Python type for each non-gtype enum. (Laszlo Pandy) * Use g_vfunc_info_invoke for chaining up in vfuncs (Tomeu Vizoso) * Move pyglib_{main_context, option_context, option_group}_new into _PyGLib_API (Simon van der Linden) * pygi-convert.sh: Handle Gdk.DragAction (Martin Pitt) * pygi-convert.sh: Generalize Gtk.Settings migration (Martin Pitt) * pygi-convert.sh: Don't change the name of "glib" submodules (Martin Pitt) * Plug another memory leak (Paolo Borelli) * Plug a small memory leak. (Paolo Borelli) * Override Table.attach() to behave like pygtk (Paolo Borelli) * pygi-convert.sh: Convert Pango.WrapMode (Martin Pitt) * pygi-convert.sh: Don't change the name of "gtk" submodules (Martin Pitt) * Fix the __dir__() methods on DynamicModule and IntrospectionModule (Laszlo Pandy) * pygi-convert.sh: handle ReliefStyle (Paolo Borelli) * setup.py: fix the provides keyword argument (Dieter Verfaillie) * setup.py: use the same spaces-less format for all setup() parameters (Dieter Verfaillie) * Add a __repr__() method to DynamicModule. (Laszlo Pandy) * Go back to using getattr() in DynamicModule.__getattr__ (Tomeu Vizoso) * Change __dir__() to report all the attributes that __getattr__ supports (Laszlo Pandy) * Bump the minimum gio dependency (Emilio Pozuelo Monfort) * Add test for incorrect attributes in Gdk.Event (Tomeu Vizoso) * Don't call getattr again in gi.overrides.Gdk.Event.__getattr__ (Simon van der Linden) * Release allocated array of arguments when handling closures (Mike Gorse) * Release GIValueInfo when checking an enum argument (Mike Gorse) * Respect different type lengths when assigning out-argument pointers. (Eitan Isaacson) * Fix stupid name clash (Tomeu Vizoso) * Add /usr/share to XDG_DATA_DIRS when running the tests (Tomeu Vizoso) * Comment out tests that require SRV lookups (Tomeu Vizoso) * Use suppresion file when running valgrind (Tomeu Vizoso) * Fix warnings. (Ignacio Casal Quinteiro) * Allow comparing Gtk.TreePath to None (Jesse van den Kieboom) * handle unicode objects in properties (John (J5) Palmieri) * dsextras.py: check if gcc is there when platform is win32 and compiler is mingw32 (Dieter Verfaillie) * dsextras.py: be consistent in how distutils imports are done (Dieter Verfaillie) * dsextras.py: add have_gcc() function (Dieter Verfaillie) * dsextras.py: use distutils.spawn.find_executable for have_pkgconfig() (Dieter Verfaillie) * setup.py: fix another case of use True/False instead of 1/0 (Dieter Verfaillie) * pygi-convert.sh: improve GtkSourceView conversion (Paolo Borelli) * pygi-convert.sh: Gtk.DialogFlags conversion (Paolo Borelli) * Doc Extractor: Print the gtk-doc blocks sorted by function name. (José Alburquerque) * pygi-convert.sh: add more Gtk conversions and sort (Paolo Borelli) * pygi-convert.sh: convert Atk (Paolo Borelli) * pygi-convert.sh: convert a few more Gio types (Paolo Borelli) * pygi-convert.sh: more GLib conversion (Paolo Borelli) * pygi-convert.sh: remove two cases handled by overrides (Paolo Borelli) * Override Gtk.ScrolledWindow constructor (Paolo Borelli) * pygi-convert.sh: Fix 'find' syntax (Paolo Borelli) * pygi-convert.sh: start handling Gio and GLib (Paolo Borelli) * pygi-convert.sh: convert Gdk.ScrollDirection. (Paolo Borelli) * Override Pango.Layout constructor. (Paolo Borelli) * Remove Pango.FontDescription() conversion. (Paolo Borelli) * Override GtkAction and GtkRadioAction constructors. (Paolo Borelli) * Override Adjustment constructor to behave like pygtk (Dmitrijs Ledkovs) * add secondary_text apis to MessageDialog (John (J5) Palmieri) * [gi] get rid of some debug prints and fix error messages (John (J5) Palmieri) * Fix demo for override changes. (Paolo Borelli) * Override Pango.FontDescription. (Paolo Borelli) * Stop checking that all vfuncs are implemented (Tomeu Vizoso) * Fix usage of TreeIter api that is now an override. (Paolo Borelli) * Fix Gtk.Label(label="Foo") (Paolo Borelli) * Fix typo when raising an exception (Paolo Borelli) * pygi-convert.sh: Added more conversions (Sebastian Pölsterl) * Override LinkButton constructor to make 'uri' mandatory (Paolo Borelli) * Container should be iterable. (Dmitry Morozov) * No need to import Gdk (Paolo Borelli) * Remove semicolumns (Paolo Borelli) * [gi] make sure Gtk.Button override passes all keywords to parent constructor (John (J5) Palmieri) * Fix cut&paste error in the Label override (Paolo Borelli) * pygi-convert.sh: handle TextWindowType (Paolo Borelli) * Override Label constructor to behave like pygtk (Paolo Borelli) * Override GtkTable constructor to behave like pygtk (Paolo Borelli) * pygi-convert.sh: convert MovementStep (Paolo Borelli) * Update Gdk overrides to work with latest Gtk+ 3 (Paolo Borelli) * Gtk: add an override for Gtk.main_quit (Johan Dahlin) * [gi] handle subtypes when inserting into tree models (John (J5) Palmieri) * Override TreeSelection.select_path and TreeView.scroll_to_cell (Paolo Borelli) * Override TreePath.__new__ (Paolo Borelli) * Override Container to behave like a sequence (Paolo Borelli) * refactor Jonathan Matthew recurse vfunc patch so it applys and clean up a bit (John (J5) Palmieri) * Recurse up through base classes when setting up vfuncs (Jonathan Matthew) * add a profiling torture test for when we fix up invoke (John (J5) Palmieri) * moved dynamic and base modules outside of gtk-2.0 directory (John (J5) Palmieri) * add test for inout argument count (John (J5) Palmieri) * [gi] add check for UNICHAR (John (J5) Palmieri) * Support gunichar (Paolo Borelli) * pygi-convert.sh: gtk.accel_map -> Gtk.AccelMap._ (Paolo Borelli) * pygi-convert.sh: handle "from gtk import gdk" (Paolo Borelli) * pygi-convert.sh: add some Pango special cases (Paolo Borelli) * Override TextIter (begins|ends|toggles)_tag() (Paolo Borelli) * Override TextBuffer.set_text() to make length optional (Paolo Borelli) * Override TextBuffer.create_mark() (Paolo Borelli) * Fix TextBuffer.get_selection_bounds() override (Paolo Borelli) * [gi] fix ActionGroup constructor to allow other keyword properties to be set (John (J5) Palmieri) * [gi] require the name parameter when creatin a Gtk.ActionGroup (John (J5) Palmieri) * Override UIManager.insert_action_group (Paolo Borelli) * Override TreeModel.get() to return a tuple (Paolo Borelli) * Make TreeSelection.get_selected_rows compatible with PyGtk (Paolo Borelli) * [gi] switch to using sequences/tuples when marshalling cairo_rectangle_int_t (John (J5) Palmieri) * [gi] overrides for treeview Drag and Drop (John (J5) Palmieri) * [gi] when encountering guint8 arrays treat them as byte arrays (John (J5) Palmieri) * pygi-convert.sh: Add pynotify -> Notify (Martin Pitt) * pygi-convert.sh: Remove sugar specifics, and allow command line file list (Martin Pitt) * pygi-convert.sh: Cover Message and Buttons types (Martin Pitt) * [gi] fix actiongroup test since actions are hashed (John (J5) Palmieri) * [gi] when converting to UTF-8 accept Python Unicode objects as input (Python 2) (John (J5) Palmieri) * Correct a bug in the freeing of memory in pygi-invoke.c. (Damien Caliste) * update news for release (John (J5) Palmieri) * Implement richcompare for GIBaseInfo (Jonathan Matthew) * [gi] add the rectangle_int_t forign cairo type (John (J5) Palmieri) * add a foreign type for cairo_rectangle_int_t and allow it to be caller-allocated (John (J5) Palmieri) * [gi] add overrides to Gtk.Editable (John (J5) Palmieri) * [gi] handle virtual invokers (John (J5) Palmieri) * add overrides for the insert* apis of list_store and tree_store (John (J5) Palmieri) * fix dialogs overrides which were relying on broken inheritance behavior (John (J5) Palmieri) * Add a overrides registry so we can refrence overrides inside the module (John (J5) Palmieri) * Merge remote branch 'dieterv/setup-fixes-for-merge' (John Stowers) * setup.py: ease maintenance burden for tests installation (Dieter Verfaillie) * fix inheritence issues in overrides (John (J5) Palmieri) * tests: add runtests-windows.py script (Dieter Verfaillie) * pygobject_postinstall.py: remove pygobject-2.0.pc treatment from postinstall as pkg-config on windows figures out the correct prefix at runtime (Dieter Verfaillie) * pygobject_postinstall.py: remove shortcut creation (Dieter Verfaillie) * setup.py: formatting cleanup, makes things readable (Dieter Verfaillie) * setup.py: build and install tests (Dieter Verfaillie) * setup.py: install documentation when available on build system (Dieter Verfaillie) * setup.py: install pygobject-codegen script (Dieter Verfaillie) * setup.py: install fixxref.py script (Dieter Verfaillie) * setup.py: rearrange constants (Dieter Verfaillie) * setup.py: check python version and pkgconig availability before anything else (Dieter Verfaillie) * setup.py: simplify sys.platform != 'win32' detection and error reporting (Dieter Verfaillie) * setup.py: rearrange imports (Dieter Verfaillie) * README.win32: update build instructions (Dieter Verfaillie) * dsextras.py: formatting cleanup, makes things readable (Dieter Verfaillie) * dsextras.py: add ggc4 to MSVC compatible struct packing comment (Dieter Verfaillie) * dsextras.py: use the ``pkgc_`` functions instead of repeating pgk-config incantations all over the place (Dieter Verfaillie) * dsextras.py: add pkgc_get_version and pkgc_get_defs_dir functions (Dieter Verfaillie) * dsextras.py: PEP8: Comparisons to singletons like None should always be done with 'is' or 'is not', never the equality operators. (Dieter Verfaillie) * dsextras.py: use True/False instead of 1/0 (Dieter Verfaillie) * dsextras.py: rearrange imports (Dieter Verfaillie) * Add distutils generated build/dist directories and eclipse configuration files to .gitignore (Dieter Verfaillie) * [gi] add tests for calling dir on a dynamic module (John (J5) Palmieri) * [gi] dir() now works for modules (Deepankar Sharma) * Don't check the inner type when comparing gpointers (Simón Pena) * Release GIL when calling into C functions (John (J5) Palmieri) * _gi.Repository : Implement missing info bindings. (José Aliste) * include Python.h so that PY_VERSION_HEX gets defined (John (J5) Palmieri) * [gi] make overrides work for python 3.x protocols and alias for python 2.x (John (J5) Palmieri) * Override Gtk.Widget.translate_coordinates to not return success value (Sebastian Pölsterl) * Override Gtk.TreeViewColumn.cell_get_position to not return success value (Sebastian Pölsterl) * Override get_path_at_pos and get_dest_row_at_pos of Gtk.TreeView to not return success value (Sebastian Pölsterl) * Override Gtk.TreeSortable.get_sort_column_id to not return success value (Sebastian Pölsterl) * Override forward_search and backward_search of Gtk.TextIter to not return success value (Sebastian Pölsterl) * Override Gtk.TextBuffer.get_selection_bounds to not return success value (Sebastian Pölsterl) * Override Gtk.RecentInfo.get_application_info to not return success value (Sebastian Pölsterl) * Override Gtk.IMContext.get_surrounding to not return success value (Sebastian Pölsterl) * Override get_item_at_pos, get_visible_range, get_dest_item_at_pos of Gtk.IconView to not return success value (Sebastian Pölsterl) * Override Gtk.Container.get_focus_chain to not return success value (Sebastian Pölsterl) * Override Gtk.ComboBox.get_active_iter to not return success value (Sebastian Pölsterl) * [gi] make parameter check less strict when dealing with GValue params (John (J5) Palmieri) * Shortcut removal is not needed on post-uninstall (John Stowers) * Disable shortcut creation in windows installer (John Stowers) * overrides for all subclasses of dialog (John (J5) Palmieri) * Make TreeModel behave like in GTK-2.x (Sebastian Pölsterl) * Correctly build GIO on windows (John Stowers) * Require Python >= 2.6.0 for Windows build (John Stowers) * Fix depreciation warning in dsextras.py (John Stowers) * Fix build on windows (John Stowers) * Support for GCC4 in Windows distutils build - bug 626548 (Michael Culbertson) * Remove obsolete comments in dsextras.py (John Stowers) * Broken dsextras.py pkg-config check error message (John Stowers) * add compat functions for the deprecated PyCObject api (John (J5) Palmieri) * Add __path__ attributes. (Damien Caliste) * Override Gtk.TreeSelection.get_selected to not return success value. (Sebastian Pölsterl) * Make row optional in Gtk.TreeStore/ListStore.append override (Vincent Untz) * Revert "add compat functions for the deprecated PyCObject api" (John (J5) Palmieri) * return NULL instead of -1 which fixes crash when introspection is turned off (John (J5) Palmieri) * add compat functions for the deprecated PyCObject api (John (J5) Palmieri) * fix commit 7fe83108 which didn't use the compat functions for string handling (John (J5) Palmieri) * Python 3 fixes for dsextras and the python.m4 distribution files (John (J5) Palmieri) 2.27.0 - 2010-11-10 ------------------- * Implement richcompare for GIBaseInfo (Jonathan Matthew) * [gi] add the rectangle_int_t forign cairo type (John (J5) Palmieri) * add a foreign type for cairo_rectangle_int_t and allow it to be caller-allocated (John (J5) Palmieri) * [gi] add overrides to Gtk.Editable (John (J5) Palmieri) * [gi] handle virtual invokers (John (J5) Palmieri) * add overrides for the insert* apis of list_store and tree_store (John (J5) Palmieri) * fix dialogs overrides which were relying on broken inheritance behavior (John (J5) Palmieri) * Add a overrides registry so we can refrence overrides inside the module (John (J5) Palmieri) * Merge remote branch 'dieterv/setup-fixes-for-merge' (John Stowers) * setup.py: ease maintenance burden for tests installation (Dieter Verfaillie) * fix inheritence issues in overrides (John (J5) Palmieri) * tests: add runtests-windows.py script (Dieter Verfaillie) * pygobject_postinstall.py: remove pygobject-2.0.pc treatment from postinstall as pkg-config on windows figures out the correct prefix at runtime (Dieter Verfaillie) * pygobject_postinstall.py: remove shortcut creation (Dieter Verfaillie) * setup.py: formatting cleanup, makes things readable (Dieter Verfaillie) * setup.py: build and install tests (Dieter Verfaillie) * setup.py: install documentation when available on build system (Dieter Verfaillie) * setup.py: install pygobject-codegen script (Dieter Verfaillie) * setup.py: install fixxref.py script (Dieter Verfaillie) * setup.py: rearrange constants (Dieter Verfaillie) * setup.py: check python version and pkgconig availability before anything else (Dieter Verfaillie) * setup.py: simplify sys.platform != 'win32' detection and error reporting (Dieter Verfaillie) * setup.py: rearrange imports (Dieter Verfaillie) * README.win32: update build instructions (Dieter Verfaillie) * dsextras.py: formatting cleanup, makes things readable (Dieter Verfaillie) * dsextras.py: add ggc4 to MSVC compatible struct packing comment (Dieter Verfaillie) * dsextras.py: use the ``pkgc_`` functions instead of repeating pgk-config incantations all over the place (Dieter Verfaillie) * dsextras.py: add pkgc_get_version and pkgc_get_defs_dir functions (Dieter Verfaillie) * dsextras.py: PEP8: Comparisons to singletons like None should always be done with 'is' or 'is not', never the equality operators. (Dieter Verfaillie) * dsextras.py: use True/False instead of 1/0 (Dieter Verfaillie) * dsextras.py: rearrange imports (Dieter Verfaillie) * Add distutils generated build/dist directories and eclipse configuration files to .gitignore (Dieter Verfaillie) * [gi] add tests for calling dir on a dynamic module (John (J5) Palmieri) * [gi] dir() now works for modules (Deepankar Sharma) * Don't check the inner type when comparing gpointers (Simón Pena) * Release GIL when calling into C functions (John (J5) Palmieri) * _gi.Repository : Implement missing info bindings. (José Aliste) * include Python.h so that PY_VERSION_HEX gets defined (John (J5) Palmieri) * [gi] make overrides work for python 3.x protocols and alias for python 2.x (John (J5) Palmieri) * Override Gtk.Widget.translate_coordinates to not return success value (Sebastian Pölsterl) * Override Gtk.TreeViewColumn.cell_get_position to not return success value (Sebastian Pölsterl) * Override get_path_at_pos and get_dest_row_at_pos of Gtk.TreeView to not return success value (Sebastian Pölsterl) * Override Gtk.TreeSortable.get_sort_column_id to not return success value (Sebastian Pölsterl) * Override forward_search and backward_search of Gtk.TextIter to not return success value (Sebastian Pölsterl) * Override Gtk.TextBuffer.get_selection_bounds to not return success value (Sebastian Pölsterl) * Override Gtk.RecentInfo.get_application_info to not return success value (Sebastian Pölsterl) * Override Gtk.IMContext.get_surrounding to not return success value (Sebastian Pölsterl) * Override get_item_at_pos, get_visible_range, get_dest_item_at_pos of Gtk.IconView to not return success value (Sebastian Pölsterl) * Override Gtk.Container.get_focus_chain to not return success value (Sebastian Pölsterl) * Override Gtk.ComboBox.get_active_iter to not return success value (Sebastian Pölsterl) * [gi] make parameter check less strict when dealing with GValue params (John (J5) Palmieri) * Shortcut removal is not needed on post-uninstall (John Stowers) * Disable shortcut creation in windows installer (John Stowers) * overrides for all subclasses of dialog (John (J5) Palmieri) * Make TreeModel behave like in GTK-2.x (Sebastian Pölsterl) * Correctly build GIO on windows (John Stowers) * Require Python >= 2.6.0 for Windows build (John Stowers) * Fix depreciation warning in dsextras.py (John Stowers) * Fix build on windows (John Stowers) * Support for GCC4 in Windows distutils build - bug 626548 (Michael Culbertson) * Remove obsolete comments in dsextras.py (John Stowers) * Broken dsextras.py pkg-config check error message (John Stowers) * add compat functions for the deprecated PyCObject api (John (J5) Palmieri) * Add __path__ attributes. (Damien Caliste) * Override Gtk.TreeSelection.get_selected to not return success value. (Sebastian Pölsterl) * Make row optional in Gtk.TreeStore/ListStore.append override (Vincent Untz) * Revert "add compat functions for the deprecated PyCObject api" (John (J5) Palmieri) * return NULL instead of -1 which fixes crash when introspection is turned off (John (J5) Palmieri) * add compat functions for the deprecated PyCObject api (John (J5) Palmieri) * fix commit 7fe83108 which didn't use the compat functions for string handling (John (J5) Palmieri) * Python 3 fixes for dsextras and the python.m4 distribution files (John (J5) Palmieri) 2.26.0 - 2010-09-24 ------------------- * Wrap g_get_system_{config,data}_dirs () (John Strowers) * fixed make check and make dist (John (J5) Palmieri) * Disable GI tests when introspection disabled (John Stowers) * Wrap g_uri_list_extract_uris. Fixes bug :bzbug:`584431` (Tomeu Vizoso) * Fix a few uses of TRUE and FALSE in the docs (Paul Bolle) * pygi: always free the invocation_state struct (Damien Caliste) * Start implementing something equivalent to g_variant_new (Tomeu Vizoso) * fixed typo - missing comma in glib.option module (John (J5) Palmieri) * add checks so we can compile under python 3 by setting PYTHON=python3 (John (J5) Palmieri) * Rename static methods as functions (Tomeu Vizoso) * fix a couple of compiler warnings (John (J5) Palmieri) * remove unused code (John (J5) Palmieri) * Check the type of the instance object (John (J5) Palmieri) * include the correct pycairo version (John (J5) Palmieri) * Use PyMapping_Keys to determine if an object is a dict (py3k fix) (John (J5) Palmieri) * fix handling of UINT64 and INT64 arguments in py3k (John (J5) Palmieri) * properly handle ulongs properties in py3k (John (J5) Palmieri) * Specify encoding of tests/test_gi.py (Tomeu Vizoso) * use actual unicode in the tests on py3k, not the byte representation (John (J5) Palmieri) * s/METH_KEYWORDS/METH_VARARGS|METH_KEYWORDS/ when defining object methods (John (J5) Palmieri) * fix subclassing PyLong by calling __new__ correctly (John (J5) Palmieri) * minor py3k fixups for python modules (John (J5) Palmieri) * minor fixes in tests for py3k compat (John (J5) Palmieri) * compilation: Fix syntax error (Colin Walters) * Add missing file (Tomeu Vizoso) * Add override for GLib.Variant.new_tuple (Tomeu Vizoso) * fix for changes in the gi test libraries (John (J5) Palmieri) * Gtk.DialogFlags.NO_SEPARATOR has been removed in Gtk 3.0 (John (J5) Palmieri) * no need to offset arg positions when is_method is true (John (J5) Palmieri) * gi: Add support for more property types (Tomeu Vizoso) * use PyObject_SetAttrString, not PyDict_SetItemString when setting __gtype__ (John (J5) Palmieri) * Rename GArgument to GIArgument (Tomeu Vizoso) * fix up tests so they run in py3k (John (J5) Palmieri) * tests: Port to new introspection tests (Colin Walters) * we need to specify tp_hash since we overide tp_richcompare (John (J5) Palmieri) * working enum/flags/pid subclasses of long (John Ehresman) * make vfuncs work in py3k (John (J5) Palmieri) * make cairo module compile in py3k (John (J5) Palmieri) * fix exceptions so they work in python 3.x (John (J5) Palmieri) * make the gi module compile under 3.x (John (J5) Palmieri) * fix up testshelper module so it compiles in python 3.x (John (J5) Palmieri) * convert to using PYGLIB_DEFINE_TYPE for module objects (John (J5) Palmieri) * some more p3k PyString and PyInt eradication in GI (John (J5) Palmieri) * pyglib: Fix typo (Leo Singer) (Tomeu Vizoso) * Add defines for size_t and ssize_t conversion functions (Gustavo Noronha Silva) * pyglib: Fix a compiler warning (Colin Walters) * Don't force gtk 2.0 (Tomeu Vizoso) * Fix some ref leaks in hook_up_vfunc_implementation() (Steve Frécinaux) * handle strings correctly in gio (John (J5) Palmieri) * make giomodule compile under py3k (John (J5) Palmieri) * for py3k we need to do some more processing to get bytes from a unicode string (John (J5) Palmieri) * use Bytes instead of Unicode when reading io (John (J5) Palmieri) * prefix compat macros with PYGLIB (John (J5) Palmieri) * Gtk.Button unit tests (John (J5) Palmieri) * [Gtk] Add overrides for Button (Johan Dahlin) * Make Cairo an optional dependency (Simon van der Linden) * Don't import again PyGObject (John Ralls) (Tomeu Vizoso) * move to using richcompare slot instead of compare (John (J5) Palmieri) * Replace autogen.sh by a newer version (Simon van der Linden) * Fix some warnings (Simon van der Linden) * Fix caller-allocates emergency free. (Simon van der Linden) * Remove useless checks. (Simon van der Linden) * Call valgrind with G_SLICE=always-malloc G_DEBUG=gc-friendly (Tomeu Vizoso) * Fix some warnings. (Ignacio Casal Quinteiro) * Add myself as a maintainer (Simon van der Linden) * Properly allocate boxed structs that are (caller-allocates) (Tomeu Vizoso) * override gdk.Event to return attribute from the proper event object (Toms Baugis) * check if z# needs an int or Py_ssize_t (John (J5) Palmieri) * make sure we parse parameters to python object vars not glib vars (John (J5) Palmieri) * Make an example and a demo work out of the box (Paul Bolle) * make sure caller allocated structs are freed when they go out of scope (John (J5) Palmieri) * Revert "override gdk.Event to return attribute from the proper event object." (Tomeu Vizoso) * PyGI: properly quit cairo-demo (Paul Bolle) * override gdk.Event to return attribute from the proper event object. (Toms Baugis) * Clean and improve the test infrastructure (Simon van der Linden) * Add some more transformations to pygi-convert.sh (Tomeu Vizoso) * Adapt to API changes: g_irepository_enumerate_versions (Tomeu Vizoso) * Add GValue<->GArgument marshalling for some more types (Tomeu Vizoso) * Chain up with the non-introspection implementation for properties if needed (Tomeu Vizoso) * Improve error reporting for missing attributes in introspection modules (Tomeu Vizoso) * Implement getting and setting properties using introspection information. (Tomeu Vizoso) * Readd Gdk.Rectangle override for Gtk-2.0 (Tomeu Vizoso) * Allow specifying a version when loading a typelib (Tomeu Vizoso) * treat GFreeFunc as equivalent to GDestroyNotify when scanning callbacks (Jonathan Matthew) * Don't use == to compare doubles, use <= and =>. (Simon van der Linden) * Allow passing ints as enum args (Tomeu Vizoso) * Make error message less ambiguous (Tomeu Vizoso) * fix passing in type names as a GType and add gtype unit tests (John (J5) Palmieri) * Increase a bit verbosity of tests so people know which test failed (Tomeu Vizoso) * Actually add the files for GVariant foreign structs (Tomeu Vizoso) * Add foreign struct support for GVariant (Tomeu Vizoso) 2.21.5 - 2010-07-12 ------------------- * Shut up some compiler warnings (Florian Müllner) * Adjust to API break in GObject-Introspection (Florian Müllner) * pass in the demo app so demos can use utility methods like requesting file paths (John (J5) Palmieri) * demo fixes to keep up with Gtk+ (John (J5) Palmieri) * override test fixes for new GTK+ annotations (John (J5) Palmieri) * Fix warning. (Ignacio Casal Quinteiro) * fix up treeiter usage due to caller-allocates annotations in gtk+ (John (J5) Palmieri) * add entry completion demo (John (J5) Palmieri) * string changes (John (J5) Palmieri) * add the Entry demo directory and the entry_buffer demo (John (J5) Palmieri) * fix loading of demo modules to support sub modules (John (J5) Palmieri) * add the ability to have demos in sub catagories (John (J5) Palmieri) * Add __name__ to DynamicModule class. (Jose Aliste) * Do not override GdkRectangle. (Ignacio Casal Quinteiro) * Add override for TreeModel implementing __len__() (Philip Withnall) 2.21.4 - 2010-06-29 ------------------- * Build the cairo shim as a python module so the _gi module stops linking to it (Tomeu Vizoso) * add drawing area demo (John (J5) Palmieri) * sort the demo list (John (J5) Palmieri) * rename iter to treeiter so we aren't using a python reserved word (John (J5) Palmieri) * Fixup for change in buffer API (John (J5) Palmieri) * add ListStore, TreeStore and TreeViewColumn APIs (John (J5) Palmieri) * Add unit test for add_actions user data. (Ignacio Casal Quinteiro) * Pass user_data param when adding actions (Paolo Borelli) * add an exception type to the try/except block (John (J5) Palmieri) * return PyList instead of PyTuple for array, return empty list for NULL arrays (John (J5) Palmieri) * Fix 'make distcheck' (Tomeu Vizoso) * Allow building pygobject without introspection support by providing --disable-introspection to configure. (Tomeu Vizoso) * Make sure that sys.argv is a list and not a sequence. (Tomeu Vizoso) * Force loading the GObject typelib so we have available the wrappers for base classes such as GInitiallyUnowned. (Tomeu Vizoso) * we shouldn't g_array_free NULL pointers (John (J5) Palmieri) * remove unneeded TextIter creation in the tests (John (J5) Palmieri) * add override for TextBuffer (John (J5) Palmieri) * fix up some build issues (John (J5) Palmieri) * make the overrides file git friendly by appending to __all__ after each override (John (J5) Palmieri) * Override Dialog constructor and add_buttons method (Paolo Borelli) * Merge PyGI (Johan Dahlin) 2.21.3 - 2010-06-21 ------------------- * Proper handling of null-ok in virtual methods (Ludovic L'Hours) * Fall back to use the floating references API in glib if there isn't a sinkfunc defined. (Tomeu Vizoso) * Revert "Drop sinkfuncs." (Tomeu Vizoso) * [giounix] Make it possible to compile on glib 2.20 (Johan Dahlin) * Release the lock when potentially invoking Python code. (Sjoerd Simons) 2.21.2 - 2010-06-10 ------------------- * Drop sinkfuncs. (Tomeu Vizoso) * Clear error if we failed the import (Colin Walters) * Added missing , to keyword list of gio.GFile.set_attribute (John Ehresman) * Fix arg conversion in gio.GFile.set_attribute (John Ehresman) * Set constants under python 2.5 or before (John Ehresman) * Doc Extractor: Use replacements that make sense for &...; expressions. (José Alburquerque) * Add build docs for windows (John Stowers) * Setup.py cosmetic tidy (John Stowers) * Fix crash when importing gio (John Stowers) * Bug 589671 - Dont use generate-constants (John Stowers) * Bug 589671 - Fix setup.py for windows build (John Stowers) * Include pygsource.h (John Stowers) * codegen/docextract_to_xml.py: One more &...; replacement ( ). (José Alburquerque) * codegen/docextract_to_xml.py: Replace some &..; that cause errors. (José Alburquerque) * codegen/docextract_to_xml.py: Handle C++ multi-line comments. (José Alburquerque) * codegen/docextract.py: Stop final section processing on first match. (José Alburquerque) * Update doc extraction tool to handle GObjectIntrospection annotations. (José Alburquerque) * Docs: replace gio.IO_ERROR_* with gio.ERROR_* (Paul Bolle) * Bug 613341 - pygobject tests seem to require pygtk causing a circular (Gian Mario) * Don't raise an error in _pygi_import if pygi support is disabled (Simon van der Linden) * Initialize PyGPollFD_Type.fd_obj to NULL (Tomeu Vizoso) * Bug 605937 - pygobject: Makefile.am sets $TMPDIR, disrupting distcc (Gian Mario) * Wrap gio.Cancellable.make_pollfd() and add a test (Gian Mario) * Make cancellable an optional parameter in many methods (Gian Mario) 2.21.1 - 2010-01-02 ------------------- * Wrap gio.Volume.eject_with_operation (Gian Mario) * Wrap gio.Mount.eject_with_operation (Gian Mario) * Wrap gio.Mount.unmount_mountable_with_operation (Gian Mario) * Wrap File.unmount_mountable_with_operation (Gian Mario) * Wrap gio.File.stop_mountable (Gian Mario) * Wrap gio.File.start_mountable (Gian Mario) * Wrap gio.File.replace_readwrite_async (Gian Mario) * Wrap gio.File.poll_mountable (Gian Mario) * Wrap gio.File.open_readwrite_async (Gian Mario) * Wrap gio.File.eject_mountable_with_operation (Gian Mario) * Wrap gio.File.create_readwrite_async (Gian Mario) * Wrap gio.Drive.stop (Gian Mario) * Wrap gio.Drive.start (Gian Mario) * Wrap gio.SocketListener.accept_socket_async|finish (Gian Mario) * Wrap gio.SocketListener.accept_finish (Gian Mario) * Wrap gio.SocketListener.accept_async (Gian Mario) * Wrap gio.SocketListener.accept_socket (Gian Mario) * Wrap gio.SocketListener.accept (Gian Mario) * Make cancellable optional in gio.SocketClient.connect_to_host (Gian Mario) * Wrap gio.SocketListener.add_address (Gian Mario) * Wrap gio.SocketClient.connect_to_service_async (Gian Mario) * Wrap gio.SocketClient.connect_to_host_async (Gian Mario) * Wrap gio.SocketClient.connect_async (Gian Mario) * Wrap gio.SocketAddressEnumerator.next_async (Gian Mario) * Add a missing object gio.InetSocketAddress new in GIO 2.22 (Gian Mario) * Make cancellable optional for gio.SocketAddressEnumerator.next (Gian Mario) * Wrap gio.Socket.condition_wait (Gian Mario) * Wrap gio.Socket.condition_check (Gian Mario) * Wrap gio.Resolver.lookup_service_finish (Gian Mario) * Wrap gio.Resolver.lookup_service_async (Gian Mario) * Wrap gio.Resolver.lookup_service (Gian Mario) * Wrap gio.Resolver.lookup_by_address_async (Gian Mario) * Wrap gio.Resolver.lookup_by_name_finish (Gian Mario) * Wrap gio.Drive.eject_with_data (Gian Mario) * Deprecate old gio.Drive methods (Gian Mario) * Wrap gio.Resolver.lookup_by_name (Gian Mario) * Make cancellable optional in gio.Resolver.lookup_by_address (Gian Mario) * Strip ``g_`` prefix for many other functions (Gian Mario) * Strip ``g_`` prefix from InetAddress functions (Gian Mario) * Fix function name gio.resolver_get_default (Gian Mario) * Wrap gio.FileIOStream.query_info_async (Gian Mario) * Register enums and flags in PyGI if needed (Tomeu Vizoso, :bzbug:`603534`) * Wrap gio.IOStream.close_async (Gian Mario) * Make cancellable optional in GFile.create_readwrite (Gian Mario) * Remove a duplicate entry in gio.defs (Gian Mario) * Wrap gio.FileInfo.set_modification_time (Gian Mario) * Wrap gio.EmblemedIcon.get_emblems (Gian Mario) * Update Enums and Flags with new API (Gian Mario) * Fix handling of uchar in pyg_value_from_pyobject (Bastian Winkler) 2.21.0 - 2009-12-18 ------------------- * pygmainloop: fix use of PySignal_WakeUpFD API for nested loops (Philippe Normad, :bzbug:`481569`) * Add capabilities to import wrappers from pygi (Simon van der Linden) * Move threads_init() function from 'gobject' to 'glib' (Paul) * Fix wrong minimum checking in float properties (Paul, :bzbug:`587637`) * Wrap new API added in GIO 2.22 (Gian Mario) * Fix bad name when rebuilding the unix source module (Gian Mario) * Add the missing limit constants from glibconfig.h (Tomeu Vizoso, :bzbug:`603244`) * Suppress warnings about format conversion (Simon van der Linden, :bzbug:`603355`) * Properly define Connectable as interface type and not object type (Gian Mario) * Wrap new API added in GIO-UNIX 2.22 (Gian Mario) * Wrap g_find_program_in_path (Gian Mario, :bzbug:`598435`) * Add pygi-external.h into Makefile SOURCES (Gian Mario) 2.20.0 - 2009-09-23 ------------------- * Allow to use automake 1.11 (Paolo Borelli) * Specify programming language in .devhelp file (Frédéric Péters) * Plug reference leak of GSource in pyg_main_loop_init (Paul) * Updated uninstalled.pc file (Brian Cameron) 2.19.0 - 2009-08-10 ------------------- * Add macros to help with Python list to/from GList/GSList conversions. (John Finlay) * GIO docs practically completed (Gian) * GFileInfo.list_attributes should accept None/NULL (Gian) * Strip out Windows DLL API macros (John Finlay) * Document that many functions got moved gobject -> glib (Paul) * Allow h2def.py to work when there are tabs or multiple spaces after the struct keyword. (Murray Cumming) * Fix build when builddir is not the same as srcdir (Theppitak Karoonboonyanan) * Make gio.Emblem constructor new-style (Paul) * Cleanup GIO overrides to use Python function/method names (Paul) * Make codegen report errors using Python function/method names (Paul) * Fix object type in gio.BufferedInputStream_fill_async (Gian) * Wrap gio.BufferedInputStream.fill_async (Gian) * Add gio.BufferedOutputStream which was forgotten in the types (Gian) * Split overrides for gio.MemoryOutputStream (Gian) * Wrap gio.memory_input_stream_new_from_data (Gian) * Introduces the girepository module from the former PyBank (Simon van der Linden) * Add API appeared in 2.20 but not marked as such in gio docs (Gian) * Wrap gio.FileOutputStream.query_info_async (Gian) * Wrap gio.FileInputStream.query_async (Gian) * Install executable codegen parts with executing permissions (Paul) * Wrap gio.DataInputStream.read_line_async and read_until_async (Paul) * Fix gio.OutputStream.splice_async (Paul) * Add GIO 2.20 API and update docs (Gian) 2.18.0 - 2009-05-24 ------------------- * Improve gio docs with some more classes (Gian) * Wrap gio.OutputStream.splice_async() (Gian) * Add Python ver into installed libpyglib name (Emilio Pozuelo Monfort) * Wrap gio.OutputStream.flush_async() (Gian) * Use 'Requires.private' for libffi in '.pc' files (Josselin Mouette) * Add wrapper for gio.FileAttributeMatcher (Gian) * Mark relevant glib.IOChannel methods as METH_NOARGS (Paul) * Retire hand-written ChangeLog; autocreate from Git history (Paul) * Wrap gio.InputStream.skip_async() (Gian) * Add in codegen -n --namespace option and the code to remove dll API in headers, added documentation (Siavash Safi) * Properly mark glib.get_user_special_dir() as a keywords method (Paul) 2.17.0 - 2009-04-30 ------------------- * Write a good part of the docs for gio (Gian) * Wrap g_mount_guess_content_type g_mount_guess_content_type_finish g_mount_guess_content_type_sync (Gian, :bzbug:`580802`) * Swap first two arguments of gio.File.query_info_async (Paul, :bzbug:`580490`) * Fix a crash in pyg_type_add_interfaces (Paul, :bzbug:`566571`) * Remove an empty structure, use sizeof(PyObject) instead (Paul, :bzbug:`560591`) * Wrap four g_get_user_*_dir() functions (Paul, :bzbug:`575999`) * Remove 'ltihooks.py' as using deprecated Python module (Paul) * Code maintenance: add .gitignore files (Paul) * CellRendererPixbuf stock-size property has wrong type (Paul, :bzbug:`568499`) * Add a doap file after git migration (Johan Dahlin) * missing dep on libffi in pygobject-2.0.pc (Götz Waschk, :bzbug:`550231`) * g_volume_monitor_tp_new new function, return the singleton object. (Paul, :bzbug:`555613`) * Remove a DeprecationWarning under python 2.6 (James Westby, :bzbug:`573753`) * several scripts from codegen directory are not distributed (Krzesimir Nowak) * g_file_copy_async change argument order to keep it consistent with the other methods (Gian) * memory leak in gio.File.copy_async (Paul Pogonyshev, :bzbug:`578870`) * g_file_monitor should accept None for cancellable and set the default flag to G_FILE_MONITOR_NONE (Gian) * pyg_notify_free needs to ensure it has GIL before calling Py_XDECREF (Jonathan Matthew) * Wrap g_file_set_display_name_async (Gian) * Add a semi-private method to return the option context C object from an option context wrapper (Tristan Hill) * Converting a negative long Python value to a GUINT64 GValue doesn't error out as it should (Gustavo J. A. M. Carneiro, :bzbug:`577999`) * Wrap g_file_set_attributes_async and g_file_set_attributes_finish (Gian) * g_file_query_filesystem_info_async fix a typo (Gian) * Wrap g_file_query_filesystem_info_async (Gian) * Add missing g_file_query_filesystem_info_async and g_file_query_filesystem_info_finish (Gian) * Wrap g_file_eject_mountable (Gian) * g_file_copy callback cannot be optional (Gian) * Swap various kwargs names to reflect the code (Gian) * Update the address of the FSF (Tobias Mueller, :bzbug:`577134`) * Add g_volume_should_automount (Gian) * Wrap g_drive_enumerate_identifiers and g_volume_enumerate_identifiers (Gian) * Add a couple of convinence functions to convert from/to a python list and an array of strings (Gian) * Allow setting pytype wrapper class (Mark Lee, John Ehresman, :bzbug:`559001`) * Wrap g_file_enumerator_close_async (Gian Mario Tagliaretti) 2.16.1 - 2009-02-22 ------------------- * Apply the patch provided by Cygwin Ports maintainer (Paul Pogonyshev, :bzbug:`564018`) * Bad -I ordering can break build, patch from [dmacks netspace org] (Gian Mario Tagliaretti, :bzbug:`566737`) * Fix keyword list to be in sync with positional arguments (Paul, :bzbug:`566744`) * Add a comment explaining why the two for loops for registering interfaces (Gustavo Carneiro) * Huge cleanup of GIO overrides (Paul, :bzbug:`566706`) * gtk.Buildable interface method override is not recognized (Paul, :bzbug:`566571`) * Do not escape the ampersand "&" in entity references. Replace some unusual entity references in the output with their literal values. (Daniel Elstner, :bzbug:`568485`) * gio.InputStream.read_async can cause memory corruption. (Paul, :bzbug:`567792`) * Inconsistent use of tabs and spaces in pygtk.py (Paul, :bzbug:`569350`) * Huge fix of memory leaks in GIO (Paul, Paolo Borelli, Gian, :bzbug:`568427`) * non-async functions don't release python locks before calling blocking C functions (Gian, Gustavo, :bzbug:`556250`) * Change comment to avoid false positives when grep'ing for deprecated gtk functions (Andre Klapper) * ltihooks.py updating license header from GPL to LGPL (James Henstridge) 2.16.0 - 2009-01-04 ------------------- * gobject.timeout_add_seconds() not found in docs (Paul Pogonyshev, :bzbug:`547119`) * _wrap_g_output_stream_write_async not adding a reference to the buffer passed (Paul, :bzbug:`564102`) * gio.VolumeMonitor segfaults (Gian Mario Tagliaretti, :bzbug:`555613`) * Test if `domain` is not-null before using it to avoids segfaults (Paul, :bzbug:`561826`) * g_output_stream_write_all use gsize instead of gssize (Gian) * add __repr__ to gio.Drive, gio.Mount and gio.Volume (Paul, :bzbug:`530935`) * Missing AC_CONFIG_MACRO_DIR([m4]) (Loïc Minier, :bzbug:`551227`) * Make codegen not import when corresponding argument types are not registered (Paul, :bzbug:`551056`) * Fix typos breaking compilation (Frederic Peters :bzbug:`551212`) * GFile load_contents methods chop data at first \0 (Jonathan Matthew, :bzbug:`551059`) 2.15.4 - 2008-09-03 ------------------- * Fix typo in GPointer type registration (Loïc Minier,:bzbug:`550463`) * support G_TYPE_CLOSURE in codegen (Gian) 2.15.3 - 2008-08-31 ------------------- * Beginning of porting to 3.0. glib & gobject module ported. * Wrap g_app_info_* functions (Gian) * Wrap gio.FileAttributeInfo (Gian) * Wrap g_vfs_get_supported_uri_schemes (Johan, :bzbug:`545846`) * Wrap g_file_info_get_modification_time (Johan, :bzbug:`545861`) * Wrap gio.Volume.mount/eject (Johan) * Wrap gio.File.move (Johan) * Wrap gio.query_writable_namespaces (Gian, :bzbug:`545920`) * Separate glib & gobject documentation * Wrap GFile.append_to_async (Gian, :bzbug:`545959`) * Wrap GFile.create_async (Gian, :bzbug:`546020`) * Change return value from 'gboolean' to 'int' and changed semantics to Pythonic (Paul, :bzbug:`544946`) * Wrap GFile.replace_async and query_info_async (Gian, :bzbug:`546046`) * GIcon and implementations improvements (Paul, :bzbug:`546135`) * Improve __repr__ and richcompare for gio classes (Paul) * Missing Py_INCREFs for some file async methods (Jonathan Matthew, :bzbug:`546734`) * File.copy progress_callback does not work (Paul, :bzbug:`546591`) * add File.replace_contents, replace_contents_async, replace_contents_finish. (Jonathan Matthew, :bzbug:`547067`) * Add GFile.query_default_handler (Gian) * fix docstring line length (Jonathan Matthew, :bzbug:`547134`) * improve runtime type wrapper creation (Paul, :bzbug:`547104`) * make gio.File more Pythonic (Paul, :bzbug:`546120`) * No TypeError raised when type is None (Paul, :bzbug:`540376`) * wrap a few memory stream methods (Paul, :bzbug:`547354`) * wrap gio.DataInputStream.read_line and ...read_until (Paul, :bzbug:`547484`) * wrap four important asynchronous methods in gio.Drive and gio.Mount (Paul, :bzbug:`547495`) * gio.InputStream.read() looks broken (Paul, :bzbug:`547494`) * wrap g_content_types_get_registered() (Paul, :bzbug:`547088`) * cannot create new threads when pygtk is used (Paul, :bzbug:`547633`) * an unitialized variable in PyGLib (Paul, :bzbug:`549351`) * Constructor of gtk.TreeView raises TypeError when model is None (Paul, :bzbug:`549191`) * Fix memory problems reported by valgrind due to invalid tp_basicsize in PyGPropsDescr_Type. (Gustavo, :bzbug:`549945`) 2.15.2 - 2008-07-26 ------------------- * New module: glib, which contains the parts of the old gobject bindings which are in the glib library. MainLoop/MainContext/Sources/GOption and a few others has now moved. * Add a new installed library libpyglib-2.0, which contains the extension API for third-part modules instead of relying on macros which accesses struct fields. * Add bindings for gio.File.enumerate_children_async, gio.FileEnumerator.next_files_async, gio.Mount.mount, gio.File.mount_mountable, gio.File.mount_enclosing_volume, gio.File.unmount_mountable, gio.File.copy. * Add a new api for mapping a GError domain to an exception and register an exception for GIOError. * Remove leading IO_* prefix for the gio flags and register a quark for the domain. * Use GSlice in the glib module and bump required version to 2.14. 2.15.1 - 2008-07-15 ------------------- * Rename pygtk-codegen-2.0 to pygobject-codegen-2.0 to avoid conflicting with PyGTK (Paul Pogonyshev) 2.15.0 - 2008-07-15 ------------------- * Add GIO bindings (Johan, Mario Tagliaretti, Thomas Leonard) * Move codegen from PyGTK (Johan, Paul Pogonyshev, :bzbug:`542821`) * Add more variables to the .pc files (Damien Carbery, Paul, Dan Winship, :bzbug:`486876`) * Add pyg_option_group_new to the public API (Johan) * Add g_get_application_anme and g_get_progname (Sebastian Rittau) * Avoid making wakeups when using Python 2.6 (Johan, Gustavo, Adam Olsen, Josselin Mouette, Philippe Normand, Guido Van Rossum) * Only link against libffi when found (Ed Catmur, :bzbug:`496006`) * Improve gobject.property (Tomeu Vizoso, :bzbug:`523352`) * Improve enum comparision and warnings (Paul, Phil Dumont, :bzbug:`428732`) * Many gobject.Source improvements (Bryan Silverthorn) * Apply some fixes to make pylint happier (Johan, Simon Schampijer, :bzbug:`523821`) * Fix error message in pyg_io_add_watch (Juha Sahkangas) * Improve h2def.py (Oliver Crete, Murray Cumming, Lauro Moura) 2.14.2 - 2008-05-23 ------------------- * Allow gobject.property work with subclasses. (:bzbug:`523352`, Tomeu Vizoso) * Unbreak Source.prepare (:bzbug:`523075`, Bryan Silverthorn) * Never override customly set 'tp_new' and 'tp_alloc' (Paul Pogonyshev) * Don't link against libffi if we cannot find libffi on the system. (:bzbug:`496006`, Ed Catmur) * Dist .m4 files. (:bzbug:`496011`, Ed Catmur) * Don't return NULL after warning of enum comparsion (:bzbug:`519631`, Paul Pogonyshev) 2.14.1 - 2008-01-03 ------------------- * Avoid wakeups when using Python trunk (Johan Dahlin, :bzbug:`481569`) * Add an uninstalled.pc (Damien Carbery, :bzbug:`486876`) 2.14.0 - 2007-09-16 ------------------- * Fix a Python 2.6 deprecation warning (Johannes Hölzl, :bzbug:`342948`) * Wrap g_timeout_add_seconds, when compiling with glib 2.14 (Gustavo) * Always fully initialize the PyGObject (Ed Catmur, :bzbug:`466082`) * Fix compilation in Solaris, again (:bzbug:`339924`, Gustavo) * Fix check for default value in boolean type (Marco Giusti, :bzbug:`470230`) * Fix new style properties with subclasses (Johan Dahlin, :bzbug:`470718`) * Docs generation fixes (John Finlay) 2.13.2 - 2007-07-07 ------------------- * Fix build on opensolaris (Damien Carbery, :bzbug:`339924`) * Proxy GOption exceptions from Python to C (Johannes Hölzl, :bzbug:`342948`) * Support G_TYPE_VALUE boxed args/signals (Ed Catmur, Carlos Martin, :bzbug:`351072`) * pyg_error_exception_check bug fix (Sebastian Granjoux, :bzbug:`449879`) * Toggle references bug fix (:bzbug:`447271`, Gustavo Carneiro) * use python-config to get python includes (:bzbug:`448173`, Sebastien Bacher) * Support GObject properties in new properties API (Gustavo) * generate-constants fixes (Muntyan) * Allow running autogen.sh from outside $srcdir (Muntyan) 2.13.1 - 2007-05-02 ------------------- * Generic CClosure marshaller using libffi (Johan, :bzbug:`353816`) * Uninstalled .pc file (Damien Carbery, :bzbug:`385129`) * Fix leak in GFlags handling (Daniel Berrange, :bzbug:`428726`) * Use dirname in autogen (Loïc Minier, :bzbug:`409234`) * Treat None in a GValueArray as pointer/NULL (Ed Catmur, :bzbug:`352209`) * Toggle reference bug fix in tp_setattro (Gustavo, :bzbug:`434659`) * Add a simplified helper for creating properties (Johan, Gustavo, :bzbug:`338089`) * Avoid throwing an exception in GValue converter (James Livingstone, Ed Catmur, :bzbug:`374653`) * Build fix in .pc file (Luca Ferretti, :bzbug:`435132`) 2.13.0 - 2007-04-23 ------------------- * Release the GIL in g_object_set_property (Edward Hervey, :bzbug:`395048`) * Break PyGObject<->GObject reference cycle (Gustavo Carneiro, :bzbug:`320428`) * use static inline functions for init_pygobject (Gustavo, :bzbug:`419379`) * Wrap g_set_application_name, g_set_prgname (Havoc Pennington, :bzbug:`415853`) * New pyg_gerror_exception_check API (Gustavo, :bzbug:`425242`) * New API to get/set multiple properties (Gian Mario Tagliaretti, :bzbug:`403212`) * Misc. bug fixes. 2.12.3 - 2006-11-18 ------------------- * distutils build fixes (Cedric) * documentation updates (John) * gobject.handler_block_by_func and friends now accept methods (Johan, Dima, :bzbug:`375589`) * avoid truncating of gparamspec (Yevgen Muntyan, :bzbug:`353943`) * set __module__ on gobject derived types (Johan, Osmo Salomaa, :bzbug:`376099`) * Ensure exceptions are raised on errors in gobject.OptionGroup (Johan, Laszlo Pandy, :bzbug:`364576` 2.12.2 - 2006-10-03 ------------------- * Make PyGObject 64-bit safe for Python 2.5 (Gustavo) * All headers are now LGPL and not GPL (Johan) * Remove a couple of GCC warnings (Gustavo) * Revive distutils support (Cedric Gustin) * Emission hook reference count bugfix (Gustavo) * MSVC/ANSI C compilation fix (John Ehresman) * Bump Ctrl-C timeout handler from 100ms to 1000 (Johan) 2.12.1 - 2006-09-04 ------------------- * Corrected version check (Sebastian Dröge, :bzbug:`354364`) 2.12.0 - 2006-09-04 ------------------- * Install the html files even when using --disable-docs (:bzbug:`353159`, Johan, Matthias Clasen) 2.11.4 - 2006-08-27 ------------------- * Include pre-generated html docs in the tarball (Johan) * Fix bug in do_set_property called from constructor (Gustavo, :bzbug:`353039`) * Fix type registration involving interfaces with signals and/or properties (Gustavo) 2.11.3 - 2006-08-21 ------------------- * Documentation updates (John) * Documentation build fixes (Johan, John, Gian Mario Tagliaretti) * PyGObject can now be compiled using a C++ compiler (Murray Cumming) * Type registration bug fix (Gustavo) 2.11.2 - 2006-08-08 ------------------- * Add fixxref.py from PyGTK (Johan) * Fix parallel build (:bzbug:`350225`, Ed Catmur) 2.11.1 - 2006-08-04 ------------------- * Add John Finlay's reference manual (Johan, John) * Fix GOption mem leak (Gustavo) * Infrastructure for lazy type registration (Johan) * Enum/Flags fixes (Gustavo, John) * Eliminate some GCC warnings (Johan) 2.11.0 - 2006-07-12 ------------------- * Add GOption support (:bzbug:`163645`, Johannes Hölzl) * GObject metaclass converted to Python code (Gustavo) * Register GType constants from Python-land (Johan) * Distutils updates (John Ehresman, Cedric Gustin) * Add support for signal emission hooks (:bzbug:`154845`, Johan) * g_spawn_close_pid support (Gustavo) * Add new APIs do add or disable log redirections (Muntyan, :bzbug:`323786`) * "sub-sub-type" bug fixed (Gustavo) * Coverity report code fixes (Johan) * Support retrieving signal and property info from interfaces (Finlay) * Support parameters of type G_TYPE_GSTRING in signals (Gustavo) * Wrap a few g_filename_* APIs (Gustavo) 2.10.1 - 2006-04-11 ------------------- * uint64 property bug fix (Andy Wingo) * Hard code path to 2.0 (Gustavo) * Allow only tuples and lists in strv to value (Gustavo) * Include dsextras.py in the dist (Johan) 2.10.0 - 2006-03-13 ------------------- * enum/leak fix (Michael Smith) 2.9.1 - 2006-01-16 ------------------ 2.9.0 - 2006-01-16 ------------------ * Signal accumulator support (Gustavo) * GObject doc string generation improvements (Gustavo) * Discover GInterfaces in runtime (Gustavo) * Warn if return value in iowatch callback is not bool (Gustavo) * Convert string arrays properly (Christopher Aillon) 2.8.0 - 2006-01-09 ------------------ * Initial release, split of from PyGTK. * Updates for Python 2.5's richcompare (Manish Yosh) * PyFlags bug fixes (Gustavo) * Fix leak in pygobject_new_with_interfaces (Johan) * Undeprecate gobject.type_register (Johan) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/README.rst0000664000000000000000000000322215074673150014034 0ustar00rootroot.. image:: https://gitlab.gnome.org/GNOME/pygobject/-/raw/main/docs/images/pygobject.svg?ref_type=heads :align: center :width: 400px :height: 98px | **PyGObject** is a Python package which provides bindings for `GObject `__ based libraries such as `GTK `__, `GStreamer `__, `WebKitGTK `__, `GLib `__, `GIO `__ and many more. It supports Linux, Windows, and macOS and works with **Python 3.9+** and **PyPy3**. PyGObject, including this documentation, is licensed under the **LGPLv2.1+**. Homepage -------- https://pygobject.gnome.org Installation ------------ The latest version from PyGObject can be installed from `PyPI `__: pip install PyGObject PyGObject is only distributed as source distribution, so you need a C compiler installed on your host. Please have a look at our `Getting Started `__ documentation for OS specific installation instructions. Development ~~~~~~~~~~~ Our website contains instructions on how to `set up a development environment `__. Default branch renamed to ``main`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The default development branch of PyGObject has been renamed to ``main``. To update your local checkout, use:: git checkout master git branch -m master main git fetch git branch --unset-upstream git branch -u origin/main git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/Makefile0000664000000000000000000000062015074673150014734 0ustar00rootrootDIAS = $(wildcard images/*.dia) DIA_SVGS = $(patsubst %.dia,%.svg,$(DIAS)) all: _build images/%.svg: images/%.dia dia $< --export=$@ --filter=dia-svg _build: Makefile *.rst devguide/*.rst guide/*/*.rst guide/*.rst conf.py images/*.png images/*.svg $(DIA_SVGS) ../README.rst ../NEWS python3 -m sphinx -b html . _build linkcheck: python3 -m sphinx -b linkcheck -n . _build clean: rm -R _build ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/bugs_repo.rst0000664000000000000000000000147415074673150016023 0ustar00rootroot========================== Bug Tracker / Git / Source ========================== .. include:: icons.rst |bug-logo| Bug Tracker ---------------------- We use the GNOME GitLab issue tracker: * List of existing issues: https://gitlab.gnome.org/GNOME/pygobject/-/issues * Create a new issue: https://gitlab.gnome.org/GNOME/pygobject/-/issues/new |git-logo| Git Repo ------------------- PyGObject uses `Git `_ for source control and the git repo is hosted on the `GNOME Gitlab instance `__: * https://gitlab.gnome.org/GNOME/pygobject * ``git clone https://gitlab.gnome.org/GNOME/pygobject.git`` |source-logo| Source Tarballs ----------------------------- Release tarballs of all releases can be found on the GNOME server: https://ftp.gnome.org/pub/GNOME/sources/pygobject ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/changelog.rst0000664000000000000000000000047415074673150015764 0ustar00rootrootChangelog ========= Versions with an odd minor version are unstable releases (e.g. 3.27.x) while versions with even minor version are stable releases (e.g. 3.28.x). This list is sorted by release date. For more details see the Git log: https://gitlab.gnome.org/GNOME/pygobject/-/commits/main .. include:: ../NEWS ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/conf.py0000664000000000000000000000275515074673150014606 0ustar00rootrootextensions = [ "sphinx.ext.todo", "sphinx.ext.intersphinx", "sphinx.ext.extlinks", "sphinx_copybutton", ] intersphinx_mapping = { "python": ("https://docs.python.org/3", None), "cairo": ("https://pycairo.readthedocs.io/en/latest", None), "apidocs": ( "https://api.pygobject.gnome.org/", None, ), } source_suffix = {".rst": "restructuredtext"} master_doc = "index" exclude_patterns = ["_build", "README.rst"] pygments_style = "tango" html_theme = "pydata_sphinx_theme" html_show_copyright = False html_favicon = "images/favicon.ico" project = "PyGObject" html_title = project html_context = { "extra_css_files": [ "_static/extra.css", ], "display_gitlab": True, "gitlab_user": "GNOME", "gitlab_repo": "pygobject", "gitlab_version": "main", "conf_py_path": "/docs/", "gitlab_host": "gitlab.gnome.org", } html_static_path = [ "extra.css", "images/pygobject-small.svg", "images/arch.svg", "images/arch-dark.svg", ] extlinks = { "bzbug": ("https://bugzilla.gnome.org/show_bug.cgi?id=%s", "bz#%s"), "issue": ("https://gitlab.gnome.org/GNOME/pygobject/-/issues/%s", "#%s"), "commit": ("https://gitlab.gnome.org/GNOME/pygobject/commit/%s", "%s"), "mr": ("https://gitlab.gnome.org/GNOME/pygobject/-/merge_requests/%s", "!%s"), "user": ("https://gitlab.gnome.org/%s", "%s"), "devdocs": ("https://developer.gnome.org/documentation/%s.html", None), } suppress_warnings = ["image.nonlocal_uri"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/contact.rst0000664000000000000000000000176115074673150015470 0ustar00rootroot======= Contact ======= Issue Tracker If you want to file a bug report please file an issue on `GitLab `__. Chat For chatting with the community we are on the GNOME [matrix] instance in the `GNOME Python channel `__. Historical logs for this channel and for the legacy IRC channel are available at https://quodlibet.duckdns.org/irc/pygobject. Forum If you are running in to an issue or want to give feedback, start a discussion with the Python GNOME community by using the `Python` tag at the GNOME Discourse at https://discourse.gnome.org/tag/python. StackOverflow / StackExchange If you have technical questions about PyGObject you can find answers on `Stack Overflow `__. When asking there please use the tag `PyGObject`. If you are unsure which communication channel to use, **please start with discourse**. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/analysis/classes_without_constructor.rst0000664000000000000000000002116215074673150025336 0ustar00rootroot======================================== Analysis of Classes without Constructors ======================================== There are a number of classes in the GNOME APIs that are not intended for direct creation. The issue is there is not an accurate way to generically determine this. GI bindings are general and expose everything they can, this makes a number of classes available which crash when an attempt is made to instantiate them. However, we can look at classes which do not explicitly implement constructors as a hint. The following script and table attempts some analysis as to what classes do not have constructors and why. Script Used to Generate Initial Table ====================================== This script iterates a number of Python GI imported namespaces and looks for GObject.Object based classes which do not provide a public constructor. .. code-block:: python import inspect import gi from gi.repository import GObject, Gtk, Gdk, GdkPixbuf, Gio repo = gi.gi.Repository.get_default() modules = dict(GObject=GObject, Gtk=Gtk, Gdk=Gdk, GdkPixbuf=GdkPixbuf, Gio=Gio) print("||'''Name'''||'''Bug'''||'''Alternative'''||'''Reason'''||") for modname, mod in sorted(modules.items()): for name in dir(mod): obj = getattr(mod, name) if not inspect.isclass(obj) or not issubclass(obj, GObject.Object): continue info = repo.find_by_name(modname, name) if isinstance(info, (gi.types.ObjectInfo, )) and not info.get_abstract(): if not any(meth.is_constructor() for meth in info.get_methods()): print('||`%s.%s` || || || ||' % (modname, name)) Classes without Constructors ============================= ==================================== ================================ =============================================== ============================================================================================================ **Name** **Bug** **Alternative** **Reason** ==================================== ================================ =============================================== ============================================================================================================ ``GObject.Binding`` `675581`_ GObject.Object.bind_property(...) Non-generic semantics, requires construct only arguments. ``GObject.InitiallyUnowned`` [1] ``Gdk.Display`` Gdk.Display.get_default() Singleton ``Gdk.DisplayManager`` Gdk.Display.get_default() or Gdk.Display.get() Singleton ``Gdk.DragContext`` Gdk.drag_begin() [1] ``Gdk.Keymap`` Gdk.Keymap.get_default() Singleton ``Gdk.Screen`` `687792`_ Screen.get_default() Singleton ``Gdk.Visual`` [1] ``GdkPixbuf.PixbufAnimationIter`` [1] ``GdkPixbuf.PixbufSimpleAnimIter`` [1] ``Gio.ApplicationCommandLine`` [1] (Usually created by GApplication) ``Gio.DBusActionGroup`` Gio.DBusActionGroup.get() [1] ``Gio.DBusMenuModel`` Gio.DBusMenuModel.get() [1] ``Gio.DBusMethodInvocation`` [1] Received as argument to the handle_method_call() function ``Gio.FileEnumerator`` Gio.File.enumerate_children() [1] ``Gio.FileIOStream`` unknown ``Gio.FileInputStream`` unknown ``Gio.FileOutputStream`` unknown ``Gio.MemoryOutputStream`` unknown ``Gio.ProxyAddressEnumerator`` Gio.SocketConnectable.enumerate() [1] ``Gio.Resolver`` Gio.Resolver [1] ``Gio.SocketConnection`` unknown ``Gio.TcpConnection`` unknown ``Gio.TlsInteraction`` unknown ``Gio.UnixConnection`` unknown ``Gio.Vfs`` Gio.Vfs.get_default() or Gio.Vfs.get_local() Singleton ``Gio.VolumeMonitor`` `647731`_ Gio.VolumeMonitor.get() Singleton ``Gtk.AccelMap`` Gtk.AccelMap.get() [1] ``Gtk.Accessible`` unknown ``Gtk.CellAreaContext`` Gtk.CellAreaClass.create_context() [1] ``Gtk.Clipboard`` Gtk.Clipboard.get() [1] ``Gtk.FileChooserDialog`` Generic creation works and is necessary. Constructor skipped do to variadic arguments. ``Gtk.MessageDialog`` Generic creation works and is necessary. Constructor skipped do to variadic arguments. ``Gtk.NumerableIcon`` Works. gtk_numerable_icon_new marked as function not constructor do to annotation problem? ``Gtk.PrintContext`` [1] Gtk.PrintContext objects gets passed to the ::begin-print, ::end-print, ::request-page-setup and ::draw-page signals on the Gtk.PrintOperation. ``Gtk.RecentChooserDialog`` Generic creation works and is necessary. Constructor skipped do to variadic arguments. ``Gtk.Settings`` Gtk.Settings.get_default() [1] ``Gtk.ThemingEngine`` [1] ``Gtk.Tooltip`` [1] Instance passed to "query-tooltip" signal handler ``Gtk.TreeModelFilter`` Gtk.TreeModel.filter_new() [1] ``Xkl.Engine`` `680202`_ Xkl.Engine.get_instance(display) ==================================== ================================ =============================================== ============================================================================================================ .. _675581: http://bugzilla.gnome.org/show_bug.cgi?id=675581 .. _687792: http://bugzilla.gnome.org/show_bug.cgi?id=687792 .. _647731: http://bugzilla.gnome.org/show_bug.cgi?id=647731 .. _680202: http://bugzilla.gnome.org/show_bug.cgi?id=680202 [1] - Generic creation works but the class might not be necessary in Python. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/analysis/index.rst0000664000000000000000000000047115074673150020560 0ustar00rootroot======== Analysis ======== Here you can find some analysis reports of (old) bugs. Those are kept around mostly for historical reasons. .. toctree:: :titlesonly: :maxdepth: 1 classes_without_constructor object_ref_counting_for_vfuncs_and_closures property_object_transfer signal_transfer././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/analysis/object_ref_counting_for_vfuncs_and_closures.rst0000664000000000000000000010430415074673150030454 0ustar00rootrootObject Reference Counting for VFuncs and Closures ================================================== Abstract -------- The following document attempts to analyse marshaling strategies for GObjects passed as in or out arguments to Python implemented vfuncs and signal closures. There are currently a number of bugs which have cropped up throughout the years regarding this topic. Fixing these bugs sometimes ends up causing problems in other areas of the bindings, or resulting in different leaks or invalid unrefs to occur. Given this, analysis is needed which attempts to take all possibilities into account. This can then be used as a basis for testing and implementation. Related Bugs ~~~~~~~~~~~~ ======= ============================================================================ Bug Description ======= ============================================================================ 638267_ gc.collect deletes __dict__ of an object in a GTK-object, Python-object cycle 675726_ props accessor leaks references for properties of type G_TYPE_OBJECT 687522_ Setting tool item type fails 657202_ Floating refs and transfer-ownership 546802_ Pygtk destroys cycle too early 640868_ Wrong gobject refcount when calling introspected constructors for widgets 661359_ Something is wrong with editing-started signal 92955_ gc.collect() destroys __dict__? 685598_ Callback closures and user_data with "call" scope type are leaked ======= ============================================================================ .. _638267: http://bugzilla.gnome.org/show_bug.cgi?id=638267 .. _675726: http://bugzilla.gnome.org/show_bug.cgi?id=675726 .. _687522: http://bugzilla.gnome.org/show_bug.cgi?id=687522 .. _657202: http://bugzilla.gnome.org/show_bug.cgi?id=657202 .. _546802: http://bugzilla.gnome.org/show_bug.cgi?id=546802 .. _640868: http://bugzilla.gnome.org/show_bug.cgi?id=640868 .. _661359: http://bugzilla.gnome.org/show_bug.cgi?id=661359 .. _92955: http://bugzilla.gnome.org/show_bug.cgi?id=92955 .. _685598: http://bugzilla.gnome.org/show_bug.cgi?id=685598 Assumptions ----------- Possibilities that probably don't make sense: * Inout arguments for a GObject should be considered invalid. Because GObject arguments are references to a managed object, an inout argument is ambiguous and should be a gi scanner error. * Transfer container seems ambiguous in regards to GObject arguments and should probably be a gi scanner error. Input Arguments --------------- Input Argument with Transfer Everything ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In this case we simply need to avoid adding an additional ref to the GObject argument and let the bindings wrappers like PyObject steal an existing ref from it. However, if an input argument is marked as transfer everything and the incoming object is floating, we should probably sink the floating ref. Input Argument with Transfer Nothing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is mostly a case of adding a new ref to the GObject which is removed upon the PyObject wrapper being destructed. However, there are cases where incoming GObjects are floating which makes things more complex. For example (from bug: 687522_) .. code-block:: python class Window(Gtk.Window): def __init__(self): Gtk.Window.__init__(self) renderer = Gtk.CellRendererText() renderer.connect('editing-started', self.on_view_label_cell_editing_started) def on_view_label_cell_editing_started(self, renderer, editable, path): print path In the above example "editable" is a floating reference which the bindings will currently sink and add a reference to which ends up leaking. This could be addressed by maintaining the GObject as floating and simply adding a new reference upon (in) argument marshaling as proposed in bug 675726_. However, in addition to this proposed fix, there is also a situation where we might consider sinking the GObject within cleanup code after the Python vfunc is finished: .. code-block:: python class Window(Gtk.Window): def on_view_label_cell_editing_started(self, renderer, editable, path): self.editable = editable In this situation, Python is keeping a strong reference to what was just a temporary floating object coming in. We could detect this case by looking at the PyObject ref count and if it is greater than one, we sink the GObject because Python is basically maintaining a strong reference. Output and Return Arguments --------------------------- Output and return arguments should essentially be considered the same and behave the same in regards to reference counting between callers and callees. The only difference is the code paths will be different in the binding layer due to different APIs in gi-repository for working with them. VFunc Return with Transfer Everything ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is perhaps the easiest case to deal with because bindings can simply increment the reference count of the GObject being returned and return it (a "new value reference" in Python C API terminology). Binding wrapper objects will decrement their existing reference to the GObject when their own reference count reaches zero. This will always work regardless of if the object is only temporarily created in Python and returned right back to C, or if the vfunc is returning a strong reference to an object being held elsewhere. VFunc Return with Transfer Nothing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is one of the more problematic situations due to there not being a clear indication that callers of the vfunc expect a floating reference or a borrowed reference. In Gtk for example, we might have something like this: .. code-block:: python class ToolMenuAction(Gtk.Action): def do_create_tool_item(self): return Gtk.MenuToolButton() The problem here is the creation MenuToolButton from Python will sink the initial floating reference. However, what the caller of create_tool_item really wants you to return is a floating reference. Currently the Python bindings are returning an invalid object do to the lifetime being created and destroyed all within the scope of the Python method (bug 687522_). If the bindings were to always ref return values (just like with transfer everything), it would most likely leak a reference as it would be returning a strong reference which is not owned by Python and the caller expects a floating reference. There are a number of potential solutions: 1. Don't sink floating references upon object creation, but add a new reference. This would fix the immediate problem but more thought needs to be put into potential fallout. Another thing to consider is if the callee holds onto the reference it returns, we would want to sink the ref before returning the GObject. This can be detected in marshaling code by looking at the ref count of the PyObject wrapper, if it is greater than one and the GObject is floating, we sink it. This would then essentially be returning a "borrowed reference" and in this case the caller would most likely be using g_object_ref_sink which would add it's own new reference. 2. A sort of opposite idea from the first one would be to always sink floating refs as we do now, but re-float and add an extra ref upon out argument marshaling if the object is derived from GInitallyUnowned and Python would otherwise destroy it (the PyObject and GObject ref counts are only one). Likewise, if the PyObject ref count is greater than one, we are returning a borrowed reference as expected and would not want to re-float the GObject. 3. Always require vfuncs to use transfer full (a new value reference), this would basically solve all the problems but is unrealistic. The reason this is nice is there is really no confusion about floating refs or methods which imply returning an internal borrowed reference (something like Atk.Object.get_parent) Returning Borrowed References ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (transfer none with no expectation from the caller a floating ref should be returned) In regards to vfuncs which imply returning an internal borrowed reference, we can detect potential errors by again looking at the outgoing PyObject wrapper ref-count before returning the GObject. Consider the following examples: .. code-block:: python class SomethingAccessible(Atk.Object): def do_get_parent(self): return self.parent .. code-block:: python class SomethingAccessible(Atk.Object): def do_get_parent(self): return ParentObject() If the PyObject wrapper ref count is only one (latter case), it means Python would normally collect this, so we need to increment the GObject ref count to keep Python from also destroying the GObject and print a warning stating that this might be a leak. While this case may rarely happen in the real world, it is a possibility bindings need to explicitly address in order to minimize future support load. Additional Considerations ------------------------- Toggle References ~~~~~~~~~~~~~~~~~~ Beyond the situations given above, we also have the added complexity of toggle references in cases where we need to keep the Python wrapper alive and carried along with the GObject through its lifetime. This can occur when instance attributes are set on a PyObject wrapper: .. code-block:: python btn = Gtk.Button() btn.some_custom_py_attr = 'foo' In this case pygobject will detect the dictionary modification and add a toggle ref to keep the wrapper alive along with the GObject. Final Thoughts -------------- Importantly, unittests for all the combinations of the above situations need to be written. There is already some work being done in the following ticket to address this (687522_) Analysis -------- Some analysis of existing .gir files was accomplished by using the attached gir-query script which you can give a directory of .gir files and query them using xpath. VFuncs with Object Return ~~~~~~~~~~~~~~~~~~~~~~~~~ This shows a variety of the possibilities talked about above. :: $ gir-query --print-closure-arg-types "Object,GObject.Object,Widget,Gtk.Widget,Atk.Object" | grep "|| in ||" ============================================================== =============== =========== ============== ======== Closure Arg Closure Type Direction Arg Type Transfer ============================================================== =============== =========== ============== ======== ``Nautilus.LocationWidgetProvider.get_widget.window`` virtual-method in Gtk.Widget none ``Nautilus.MenuProvider.get_background_items.window`` virtual-method in Gtk.Widget none ``Nautilus.MenuProvider.get_file_items.window`` virtual-method in Gtk.Widget none ``GcrUi.ImportButton.imported.importer`` signal in GObject.Object none ``GcrUi.ImportButton.importing.importer`` signal in GObject.Object none ``Gtk.Buildable.add_child.child`` virtual-method in GObject.Object none ``Gtk.Buildable.custom_finished.child`` virtual-method in GObject.Object none ``Gtk.Buildable.custom_tag_end.child`` virtual-method in GObject.Object none ``Gtk.Buildable.custom_tag_start.child`` virtual-method in GObject.Object none ``Gtk.TextTag.event.event_object`` virtual-method in GObject.Object none ``Gtk.Action.connect_proxy.proxy`` virtual-method in Widget none ``Gtk.Action.disconnect_proxy.proxy`` virtual-method in Widget none ``Gtk.Assistant.prepare.page`` virtual-method in Widget none ``Gtk.CellArea.activate.widget`` virtual-method in Widget none ``Gtk.CellArea.event.widget`` virtual-method in Widget none ``Gtk.CellArea.foreach_alloc.widget`` virtual-method in Widget none ``Gtk.CellArea.get_preferred_height.widget`` virtual-method in Widget none ``Gtk.CellArea.get_preferred_height_for_width.widget`` virtual-method in Widget none ``Gtk.CellArea.get_preferred_width.widget`` virtual-method in Widget none ``Gtk.CellArea.get_preferred_width_for_height.widget`` virtual-method in Widget none ``Gtk.CellArea.render.widget`` virtual-method in Widget none ``Gtk.CellRenderer.activate.widget`` virtual-method in Widget none ``Gtk.CellRenderer.get_aligned_area.widget`` virtual-method in Widget none ``Gtk.CellRenderer.get_preferred_height.widget`` virtual-method in Widget none ``Gtk.CellRenderer.get_preferred_height_for_width.widget`` virtual-method in Widget none ``Gtk.CellRenderer.get_preferred_width.widget`` virtual-method in Widget none ``Gtk.CellRenderer.get_preferred_width_for_height.widget`` virtual-method in Widget none ``Gtk.CellRenderer.get_size.widget`` virtual-method in Widget none ``Gtk.CellRenderer.render.widget`` virtual-method in Widget none ``Gtk.CellRenderer.start_editing.widget`` virtual-method in Widget none ``Gtk.Container.add.widget`` virtual-method in Widget none ``Gtk.Container.composite_name.child`` virtual-method in Widget none ``Gtk.Container.get_child_property.child`` virtual-method in Widget none ``Gtk.Container.get_path_for_child.child`` virtual-method in Widget none ``Gtk.Container.remove.widget`` virtual-method in Widget none ``Gtk.Container.set_child_property.child`` virtual-method in Widget none ``Gtk.Container.set_focus_child.widget`` virtual-method in Widget none ``Gtk.HandleBox.child_attached.child`` virtual-method in Widget none ``Gtk.HandleBox.child_detached.child`` virtual-method in Widget none ``Gtk.List.select_child.child`` virtual-method in Widget none ``Gtk.List.unselect_child.child`` virtual-method in Widget none ``Gtk.MenuShell.insert.child`` virtual-method in Widget none ``Gtk.MenuShell.select_item.menu_item`` virtual-method in Widget none ``Gtk.Notebook.create_window.page`` virtual-method in Widget none ``Gtk.Notebook.insert_page.child`` virtual-method in Widget none ``Gtk.Notebook.insert_page.tab_label`` virtual-method in Widget none ``Gtk.Notebook.insert_page.menu_label`` virtual-method in Widget none ``Gtk.Notebook.page_added.child`` virtual-method in Widget none ``Gtk.Notebook.page_removed.child`` virtual-method in Widget none ``Gtk.Notebook.page_reordered.child`` virtual-method in Widget none ``Gtk.Notebook.switch_page.page`` virtual-method in Widget none ``Gtk.Overlay.get_child_position.widget`` virtual-method in Widget none ``Gtk.PrintOperation.custom_widget_apply.widget`` virtual-method in Widget none ``Gtk.PrintOperation.update_custom_widget.widget`` virtual-method in Widget none ``Gtk.Style.draw_arrow.widget`` virtual-method in Widget none ``Gtk.Style.draw_box.widget`` virtual-method in Widget none ``Gtk.Style.draw_box_gap.widget`` virtual-method in Widget none ``Gtk.Style.draw_check.widget`` virtual-method in Widget none ``Gtk.Style.draw_diamond.widget`` virtual-method in Widget none ``Gtk.Style.draw_expander.widget`` virtual-method in Widget none ``Gtk.Style.draw_extension.widget`` virtual-method in Widget none ``Gtk.Style.draw_flat_box.widget`` virtual-method in Widget none ``Gtk.Style.draw_focus.widget`` virtual-method in Widget none ``Gtk.Style.draw_handle.widget`` virtual-method in Widget none ``Gtk.Style.draw_hline.widget`` virtual-method in Widget none ``Gtk.Style.draw_layout.widget`` virtual-method in Widget none ``Gtk.Style.draw_option.widget`` virtual-method in Widget none ``Gtk.Style.draw_polygon.widget`` virtual-method in Widget none ``Gtk.Style.draw_resize_grip.widget`` virtual-method in Widget none ``Gtk.Style.draw_shadow.widget`` virtual-method in Widget none ``Gtk.Style.draw_shadow_gap.widget`` virtual-method in Widget none ``Gtk.Style.draw_slider.widget`` virtual-method in Widget none ``Gtk.Style.draw_spinner.widget`` virtual-method in Widget none ``Gtk.Style.draw_string.widget`` virtual-method in Widget none ``Gtk.Style.draw_tab.widget`` virtual-method in Widget none ``Gtk.Style.draw_vline.widget`` virtual-method in Widget none ``Gtk.Style.render_icon.widget`` virtual-method in Widget none ``Gtk.TextLayout.allocate_child.child`` virtual-method in Widget none ``Gtk.TipsQuery.widget_entered.widget`` virtual-method in Widget none ``Gtk.TipsQuery.widget_selected.widget`` virtual-method in Widget none ``Gtk.UIManager.add_widget.widget`` virtual-method in Widget none ``Gtk.UIManager.connect_proxy.proxy`` virtual-method in Widget none ``Gtk.UIManager.disconnect_proxy.proxy`` virtual-method in Widget none ``Gtk.Widget.hierarchy_changed.previous_toplevel`` virtual-method in Widget none ``Gtk.Widget.parent_set.previous_parent`` virtual-method in Widget none ``Gtk.Window.set_focus.focus`` virtual-method in Widget none ``Gtk.TextLayout.allocate-child.object`` signal in Object none ``Gtk.AccelGroup.accel-activate.acceleratable`` signal in GObject.Object none ``Gtk.TextTag.event.object`` signal in GObject.Object none ``Gtk.ActionGroup.connect-proxy.proxy`` signal in Widget none ``Gtk.ActionGroup.disconnect-proxy.proxy`` signal in Widget none ``Gtk.Assistant.prepare.page`` signal in Widget none ``Gtk.Container.add.object`` signal in Widget none ``Gtk.Container.remove.object`` signal in Widget none ``Gtk.Container.set-focus-child.object`` signal in Widget none ``Gtk.HandleBox.child-attached.object`` signal in Widget none ``Gtk.HandleBox.child-detached.object`` signal in Widget none ``Gtk.List.select-child.object`` signal in Widget none ``Gtk.List.unselect-child.object`` signal in Widget none ``Gtk.Notebook.create-window.page`` signal in Widget none ``Gtk.Notebook.page-added.child`` signal in Widget none ``Gtk.Notebook.page-removed.child`` signal in Widget none ``Gtk.Notebook.page-reordered.child`` signal in Widget none ``Gtk.PrintOperation.custom-widget-apply.widget`` signal in Widget none ``Gtk.PrintOperation.update-custom-widget.widget`` signal in Widget none ``Gtk.TipsQuery.widget-entered.object`` signal in Widget none ``Gtk.TipsQuery.widget-selected.object`` signal in Widget none ``Gtk.UIManager.add-widget.widget`` signal in Widget none ``Gtk.UIManager.connect-proxy.proxy`` signal in Widget none ``Gtk.UIManager.disconnect-proxy.proxy`` signal in Widget none ``Gtk.Widget.hierarchy-changed.previous_toplevel`` signal in Widget none ``Gtk.Widget.parent-set.old_parent`` signal in Widget none ``Gtk.Window.set-focus.object`` signal in Widget none ``Gst.ControlBinding.sync_values.object`` virtual-method in GObject.Object none ``Gst.Object.deep_notify.orig`` virtual-method in GObject.Object none ``Gst.ChildProxy.child_added.child`` virtual-method in GObject.Object none ``Gst.ChildProxy.child_removed.child`` virtual-method in GObject.Object none ``Gst.Object.deep-notify.prop_object`` signal in GObject.Object none ``Gst.ChildProxy.child-added.object`` signal in GObject.Object none ``Gst.ChildProxy.child-removed.object`` signal in GObject.Object none ``NMClient.DeviceWifi.access-point-added.ap`` signal in GObject.Object none ``NMClient.DeviceWifi.access-point-removed.ap`` signal in GObject.Object none ``NMClient.DeviceWimax.nsp-added.nsp`` signal in GObject.Object none ``NMClient.DeviceWimax.nsp-removed.nsp`` signal in GObject.Object none ``NMClient.RemoteSettings.new-connection.object`` signal in GObject.Object none ``Gio.SocketService.incoming.source_object`` virtual-method in GObject.Object none ``Gio.ThreadedSocketService.run.source_object`` virtual-method in GObject.Object none ``Gio.SocketService.incoming.source_object`` signal in GObject.Object none ``Gio.ThreadedSocketService.run.source_object`` signal in GObject.Object none ``Json.Parser.object_end.object`` virtual-method in Object none ``Json.Parser.object_member.object`` virtual-method in Object none ``Json.Parser.object-end.object`` signal in Object none ``Json.Parser.object-member.object`` signal in Object none ``GnomeDesktop.BGCrossfade.finished.window`` signal in GObject.Object none ``Gladeui.Widget.replace_child`` virtual-method in GObject.Object none ``Gladeui.Widget.replace_child`` virtual-method in GObject.Object none ``Gladeui.BaseEditor.build_child`` virtual-method in Widget none ``Gladeui.BaseEditor.change_type`` virtual-method in Widget none ``Gladeui.BaseEditor.child_selected`` virtual-method in Widget none ``Gladeui.BaseEditor.delete_child`` virtual-method in Widget none ``Gladeui.BaseEditor.delete_child`` virtual-method in Widget none ``Gladeui.BaseEditor.get_display_name`` virtual-method in Widget none ``Gladeui.BaseEditor.move_child`` virtual-method in Widget none ``Gladeui.BaseEditor.move_child`` virtual-method in Widget none ``Gladeui.Editable.load.widget`` virtual-method in Widget none ``Gladeui.Project.add_object.widget`` virtual-method in Widget none ``Gladeui.Project.remove_object.widget`` virtual-method in Widget none ``Gladeui.Project.widget_name_changed.widget`` virtual-method in Widget none ``Gladeui.Widget.add_child`` virtual-method in Widget none ``Gladeui.Widget.remove_child`` virtual-method in Widget none ``Gladeui.App.signal-editor-created.signal_editor`` signal in GObject.Object none ``Gladeui.App.widget-adaptor-registered.adaptor`` signal in GObject.Object none ``Gladeui.BaseEditor.build-child.gparent`` signal in GObject.Object none ``Gladeui.BaseEditor.change-type.object`` signal in GObject.Object none ``Gladeui.BaseEditor.child-selected.gchild`` signal in GObject.Object none ``Gladeui.BaseEditor.delete-child.gparent`` signal in GObject.Object none ``Gladeui.BaseEditor.delete-child.gchild`` signal in GObject.Object none ``Gladeui.BaseEditor.get-display-name.gchild`` signal in GObject.Object none ``Gladeui.BaseEditor.move-child.gparent`` signal in GObject.Object none ``Gladeui.BaseEditor.move-child.gchild`` signal in GObject.Object none ``Gladeui.Project.add-widget.arg1`` signal in Widget none ``Gladeui.Project.remove-widget.arg1`` signal in Widget none ``Gladeui.Project.widget-name-changed.arg1`` signal in Widget none ``Gladeui.Project.widget-visibility-changed.widget`` signal in Widget none ``Gck.Module.authenticate_object.object`` virtual-method in Object none ``Gck.Module.authenticate-object.object`` signal in Object none ``Soup.Session.connection-created.connection`` signal in GObject.Object none ``Soup.Session.tunneling.connection`` signal in GObject.Object none ``Peas.ExtensionSet.extension-added.exten`` signal in GObject.Object none ``Peas.ExtensionSet.extension-removed.exten`` signal in GObject.Object none ``Gcr.Collection.added.object`` virtual-method in GObject.Object none ``Gcr.Collection.contains.object`` virtual-method in GObject.Object none ``Gcr.Collection.removed.object`` virtual-method in GObject.Object none ``Atk.Object.set_parent.parent`` virtual-method in Object none ``Atk.Table.set_caption.caption`` virtual-method in Object none ``Atk.Table.set_column_header.header`` virtual-method in Object none ``Atk.Table.set_row_header.header`` virtual-method in Object none ``Atk.Table.set_summary.accessible`` virtual-method in Object none ============================================================== =============== =========== ============== ======== :: $ gir-query --print-closure-arg-types "Object,GObject.Object,Widget,Gtk.Widget,Atk.Object" | grep "|| out ||" ============================================================== =============== =========== ============== ======== Closure Arg Closure Type Direction Arg Type Transfer ============================================================== =============== =========== ============== ======== ``GtkSource.CompletionProvider.get_info_widget`` virtual-method out Gtk.Widget none ``PeasGtk.Configurable.create_configure_widget`` virtual-method out Gtk.Widget full ``Nautilus.LocationWidgetProvider.get_widget`` virtual-method out Gtk.Widget none ``Gtk.Buildable.construct_child`` virtual-method out GObject.Object full ``Gtk.Buildable.get_internal_child`` virtual-method out GObject.Object none ``Gtk.Action.create_menu`` virtual-method out Widget none ``Gtk.Action.create_menu_item`` virtual-method out Widget none ``Gtk.Action.create_tool_item`` virtual-method out Widget none ``Gtk.PrintOperation.create_custom_widget`` virtual-method out Widget None ``Gtk.UIManager.get_widget`` virtual-method out Widget none ``Gtk.Widget.get_accessible`` virtual-method out Atk.Object none ``Gtk.PrintOperation.create-custom-widget`` signal out GObject.Object none ``Gst.ChildProxy.get_child_by_index`` virtual-method out GObject.Object full ``Gst.ChildProxy.get_child_by_name`` virtual-method out GObject.Object full ``Gio.AsyncResult.get_source_object`` virtual-method out GObject.Object full ``Gladeui.BaseEditor.build_child`` virtual-method out Widget None ``Gladeui.EditorProperty.create_input`` virtual-method out Gtk.Widget None ``Gladeui.BaseEditor.build-child`` signal out GObject.Object None ``Atk.Component.ref_accessible_at_point`` virtual-method out Object full ``Atk.Hyperlink.get_object`` virtual-method out Object none ``Atk.Object.get_parent`` virtual-method out Object none ``Atk.Object.ref_child`` virtual-method out Object None ``Atk.Selection.ref_selection`` virtual-method out Object full ``Atk.Table.get_caption`` virtual-method out Object none ``Atk.Table.get_column_header`` virtual-method out Object none ``Atk.Table.get_row_header`` virtual-method out Object none ``Atk.Table.get_summary`` virtual-method out Object full ``Atk.Table.ref_at`` virtual-method out Object full ============================================================== =============== =========== ============== ======== ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/analysis/property_object_transfer.rst0000664000000000000000000007126015074673150024573 0ustar00rootrootProperty Object Transfer Analysis ================================= **GIR** **Code** ========================================================== =============== =========== ========================= ======== **Property** **Type** Transfer **get** **set** ========================================================== =============== =========== ========================= ======== ``GObject.Binding.source`` Object none adds ref steals ref ``GObject.Binding.target`` Object none adds ref steals ref ``Nautilus.PropertyPage.label`` Gtk.Widget none adds ref adds ref ``Nautilus.PropertyPage.page`` Gtk.Widget none adds ref adds ref ``Gtk.AccelLabel.accel-widget`` Widget full adds ref adds weak-ref ``Gtk.Accessible.widget`` Widget full adds ref depends on implementation of widget_set ``Gtk.Button.image`` Widget none adds ref steals ref ``Gtk.ColorSelectionDialog.cancel-button`` Widget full adds ref N/A ``Gtk.ColorSelectionDialog.color-selection`` Widget full adds ref N/A ``Gtk.ColorSelectionDialog.help-button`` Widget full adds ref N/A ``Gtk.ColorSelectionDialog.ok-button`` Widget full adds ref N/A ``Gtk.Container.child`` Widget full N/A depends on "add" closure implementation ``Gtk.Expander.label-widget`` Widget full adds ref sinks/adds ref ``Gtk.FileChooser.extra-widget`` Widget full depends on implementation depends on implementation ``Gtk.FileChooser.preview-widget`` Widget full depends on implementation depends on implementation ``Gtk.Frame.label-widget`` Widget full adds ref sinks/adds ref ``Gtk.ImageMenuItem.image`` Widget full adds ref sinks/adds ref ``Gtk.Label.mnemonic-widget`` Widget full adds ref adds weak-ref ``Gtk.Menu.attach-widget`` Widget none adds ref nothing (sinks parent menu) ``Gtk.MessageDialog.image`` Widget none adds ref depends on "add" closure implementation ``Gtk.MessageDialog.message-area`` Widget none adds ref N/A ``Gtk.ToolButton.icon-widget`` Widget full adds ref sinks/adds ref ``Gtk.ToolButton.label-widget`` Widget full adds ref sinks/adds ref ``Gtk.ToolItemGroup.label-widget`` Widget full ``Gtk.TreeViewColumn.widget`` Widget full adds ref sinks/adds ref ``Gtk.Window.attached-to`` Widget none adds ref adds ref ``Gst.ControlBinding.object`` Object none adds ref adds weak-ref ``Gst.Object.parent`` Object none adds ref adds/sinks ref ========================================================== =============== =========== ========================= ======== ========================================================== ========================= =========== **Property** **Type** Transfer ========================================================== ========================= =========== ``GObject.Binding.source`` Object none ``GObject.Binding.target`` Object none ``GtkSource.Completion.view`` View none ``GtkSource.Gutter.view`` View none ``GtkSource.GutterRenderer.view`` Gtk.TextView none ``GtkSource.CompletionContext.completion`` Completion none ``GtkSource.View.completion`` Completion none ``GtkSource.PrintCompositor.buffer`` Buffer none ``GtkSource.Buffer.style-scheme`` StyleScheme none ``GtkSource.CompletionItem.icon`` GdkPixbuf.Pixbuf none ``GtkSource.CompletionWords.icon`` GdkPixbuf.Pixbuf none ``GtkSource.GutterRendererPixbuf.pixbuf`` GdkPixbuf.Pixbuf none ``GtkSource.MarkAttributes.pixbuf`` GdkPixbuf.Pixbuf none ``GtkSource.Buffer.language`` Language none ``PeasGtk.PluginManager.view`` PluginManagerView none ``PeasGtk.PluginManager.engine`` Peas.Engine none ``PeasGtk.PluginManagerView.engine`` Peas.Engine none ``Nautilus.MenuItem.menu`` Menu none ``Nautilus.PropertyPage.label`` Gtk.Widget none ``Nautilus.PropertyPage.page`` Gtk.Widget none ``GcrUi.ViewerWidget.parser`` Gcr.Parser none ``GcrUi.KeyRenderer.object`` Gck.Object none ``Tracker.SparqlCursor.connection`` Tracker.SparqlConnection None ``Rest.ProxyCall.proxy`` Proxy none ``Gtk.Entry.buffer`` EntryBuffer none ``Gtk.RadioMenuItem.group`` RadioMenuItem none ``Gtk.Application.active-window`` Window none ``Gtk.MountOperation.parent`` Window none ``Gtk.Window.transient-for`` Window none ``Gtk.MenuButton.popup`` Menu none ``Gtk.MenuItem.submenu`` Menu none ``Gtk.MenuToolButton.menu`` Menu none ``Gtk.Window.application`` Application none ``Gtk.StyleContext.paint-clock`` Gdk.FrameClock none ``Gtk.MenuButton.align-widget`` Container none ``Gtk.Widget.parent`` Container none ``Gtk.CellAreaContext.area`` CellArea none ``Gtk.CellView.cell-area`` CellArea none ``Gtk.ComboBox.cell-area`` CellArea none ``Gtk.EntryCompletion.cell-area`` CellArea none ``Gtk.IconView.cell-area`` CellArea none ``Gtk.TreeViewColumn.cell-area`` CellArea none ``Gtk.Entry.completion`` EntryCompletion none ``Gtk.AccelLabel.accel-widget`` Widget none ``Gtk.Accessible.widget`` Widget none ``Gtk.Button.image`` Widget none ``Gtk.ColorSelectionDialog.cancel-button`` Widget none ``Gtk.ColorSelectionDialog.color-selection`` Widget none ``Gtk.ColorSelectionDialog.help-button`` Widget none ``Gtk.ColorSelectionDialog.ok-button`` Widget none ``Gtk.Container.child`` Widget none ``Gtk.Expander.label-widget`` Widget none ``Gtk.FileChooser.extra-widget`` Widget none ``Gtk.FileChooser.preview-widget`` Widget none ``Gtk.Frame.label-widget`` Widget none ``Gtk.ImageMenuItem.image`` Widget none ``Gtk.Label.mnemonic-widget`` Widget none ``Gtk.Menu.attach-widget`` Widget none ``Gtk.MessageDialog.image`` Widget none ``Gtk.MessageDialog.message-area`` Widget none ``Gtk.ToolButton.icon-widget`` Widget none ``Gtk.ToolButton.label-widget`` Widget none ``Gtk.ToolItemGroup.label-widget`` Widget none ``Gtk.TreeViewColumn.widget`` Widget none ``Gtk.Window.attached-to`` Widget none ``Gtk.RecentChooser.recent-manager`` RecentManager none ``Gtk.Application.app-menu`` Gio.MenuModel none ``Gtk.Application.menubar`` Gio.MenuModel none ``Gtk.MenuButton.menu-model`` Gio.MenuModel none ``Gtk.TextBuffer.tag-table`` TextTagTable none ``Gtk.RadioButton.group`` RadioButton none ``Gtk.CellArea.edited-cell`` CellRenderer none ``Gtk.CellArea.focus-cell`` CellRenderer none ``Gtk.NumerableIcon.style-context`` StyleContext none ``Gtk.Style.context`` StyleContext none ``Gtk.StyleContext.parent`` StyleContext none ``Gtk.Image.pixbuf-animation`` GdkPixbuf.PixbufAnimation none ``Gtk.Widget.style`` Style none ``Gtk.RadioAction.group`` RadioAction none ``Gtk.PrintOperation.default-page-setup`` PageSetup none ``Gtk.Invisible.screen`` Gdk.Screen none ``Gtk.MountOperation.screen`` Gdk.Screen none ``Gtk.StatusIcon.screen`` Gdk.Screen none ``Gtk.StyleContext.screen`` Gdk.Screen none ``Gtk.Window.screen`` Gdk.Screen none ``Gtk.TreeView.expander-column`` TreeViewColumn none ``Gtk.ActionGroup.accel-group`` AccelGroup none ``Gtk.ImageMenuItem.accel-group`` AccelGroup none ``Gtk.Menu.accel-group`` AccelGroup none ``Gtk.CellView.cell-area-context`` CellAreaContext none ``Gtk.TextView.buffer`` TextBuffer none ``Gtk.CellRendererSpin.adjustment`` Adjustment none ``Gtk.Range.adjustment`` Adjustment none ``Gtk.ScaleButton.adjustment`` Adjustment none ``Gtk.Scrollable.hadjustment`` Adjustment none ``Gtk.Scrollable.vadjustment`` Adjustment none ``Gtk.ScrolledWindow.hadjustment`` Adjustment none ``Gtk.ScrolledWindow.vadjustment`` Adjustment none ``Gtk.SpinButton.adjustment`` Adjustment none ``Gtk.Activatable.related-action`` Action none ``Gtk.RadioToolButton.group`` RadioToolButton none ``Gtk.PrintOperation.print-settings`` PrintSettings none ``Gtk.Action.action-group`` ActionGroup none ``Gtk.AboutDialog.logo`` GdkPixbuf.Pixbuf none ``Gtk.CellRendererPixbuf.pixbuf`` GdkPixbuf.Pixbuf none ``Gtk.CellRendererPixbuf.pixbuf-expander-closed`` GdkPixbuf.Pixbuf none ``Gtk.CellRendererPixbuf.pixbuf-expander-open`` GdkPixbuf.Pixbuf none ``Gtk.Entry.primary-icon-pixbuf`` GdkPixbuf.Pixbuf none ``Gtk.Entry.secondary-icon-pixbuf`` GdkPixbuf.Pixbuf none ``Gtk.Image.pixbuf`` GdkPixbuf.Pixbuf none ``Gtk.StatusIcon.pixbuf`` GdkPixbuf.Pixbuf none ``Gtk.Window.icon`` GdkPixbuf.Pixbuf none ``Gtk.Plug.socket-window`` Gdk.Window none ``Gtk.Widget.window`` Gdk.Window none ``Gtk.FileChooser.filter`` FileFilter none ``Gtk.LockButton.permission`` Gio.Permission none ``Gtk.RecentChooser.filter`` RecentFilter none ``Gst.Pad.template`` PadTemplate none ``Gst.ControlBinding.object`` Object none ``Gst.Object.parent`` Object none ``GtkClutter.Actor.contents`` Gtk.Widget none ``GstController.ARGBControlBinding.control-source-a`` Gst.ControlSource none ``GstController.ARGBControlBinding.control-source-b`` Gst.ControlSource none ``GstController.ARGBControlBinding.control-source-g`` Gst.ControlSource none ``GstController.ARGBControlBinding.control-source-r`` Gst.ControlSource none ``GstController.DirectControlBinding.control-source`` Gst.ControlSource none ``Gtk.OptionMenu.menu`` Menu none ``Gtk.TipsQuery.caller`` Widget none ``Gtk.Layout.hadjustment`` Adjustment none ``Gtk.Layout.vadjustment`` Adjustment none ``Gtk.ProgressBar.adjustment`` Adjustment none ``Gtk.TreeView.hadjustment`` Adjustment none ``Gtk.TreeView.vadjustment`` Adjustment none ``Gtk.Viewport.hadjustment`` Adjustment none ``Gtk.Viewport.vadjustment`` Adjustment none ``Vte.Terminal.pty-object`` Pty none ``Vte.Terminal.background-image-pixbuf`` GdkPixbuf.Pixbuf none ``Gdk.Window.cursor`` Cursor none ``Gdk.PangoRenderer.screen`` Screen none ``Gdk.DisplayManager.default-display`` Display none ``Clutter.Actor.effect`` Effect none ``Clutter.StageManager.default-stage`` Stage none ``Clutter.InputDevice.device-manager`` DeviceManager none ``Clutter.BehaviourPath.path`` Path none ``Clutter.PathConstraint.path`` Path none ``Clutter.Transition.interval`` Interval none ``Clutter.ChildMeta.container`` Container none ``Clutter.Text.buffer`` TextBuffer none ``Clutter.Animation.object`` GObject.Object none ``Clutter.Actor.actions`` Action none ``Clutter.Actor.first-child`` Actor none ``Clutter.Actor.last-child`` Actor none ``Clutter.ActorMeta.actor`` Actor none ``Clutter.AlignConstraint.source`` Actor none ``Clutter.BindConstraint.source`` Actor none ``Clutter.ChildMeta.actor`` Actor none ``Clutter.Clone.source`` Actor none ``Clutter.DragAction.drag-handle`` Actor none ``Clutter.SnapConstraint.source`` Actor none ``Clutter.Stage.key-focus`` Actor none ``Clutter.Actor.constraints`` Constraint none ``Clutter.Animation.alpha`` Alpha none ``Clutter.Behaviour.alpha`` Alpha none ``Clutter.Alpha.timeline`` Timeline none ``Clutter.Animation.timeline`` Timeline none ``Clutter.Animator.timeline`` Timeline none ``Clutter.ModelIter.model`` Model none ``Clutter.DeviceManager.backend`` Backend none ``Clutter.InputDevice.backend`` Backend none ``Clutter.Settings.backend`` Backend none ``Clutter.Actor.layout-manager`` LayoutManager none ``Clutter.LayoutMeta.manager`` LayoutManager none ``Gdk.Device.associated-device`` Device none ``Gdk.Device.device-manager`` DeviceManager none ``Gdk.AppLaunchContext.display`` Display none ``Gdk.Cursor.display`` Display none ``Gdk.Device.display`` Display none ``Gdk.DeviceManager.display`` Display none ``SecretUnstable.Collection.service`` Service none ``SecretUnstable.Item.service`` Service none ``GUsb.Device.context`` Context none ``GUsb.DeviceList.context`` Context none ``NMClient.Device.dhcp4-config`` DHCP4Config none ``NMClient.DeviceWimax.active-nsp`` WimaxNsp none ``NMClient.Device.ip4-config`` IP4Config none ``NMClient.DeviceWifi.active-access-point`` AccessPoint none ``NMClient.Device.active-connection`` ActiveConnection none ``NMClient.Device.ip6-config`` IP6Config none ``NMClient.DeviceOlpcMesh.companion`` DeviceWifi none ``NMClient.Device.dhcp6-config`` DHCP6Config none ``GstNet.NetTimeProvider.clock`` Gst.Clock none ``Gio.SocketConnection.socket`` Socket none ``Gio.UnixCredentialsMessage.credentials`` Credentials none ``Gio.TlsConnection.database`` TlsDatabase none ``Gio.FilterOutputStream.base-stream`` OutputStream none ``Gio.IOStream.output-stream`` OutputStream none ``Gio.DBusConnection.authentication-observer`` DBusAuthObserver none ``Gio.DBusServer.authentication-observer`` DBusAuthObserver none ``Gio.DBusConnection.stream`` IOStream none ``Gio.TcpWrapperConnection.base-io-stream`` IOStream none ``Gio.TlsConnection.base-io-stream`` IOStream none ``Gio.ZlibCompressor.file-info`` FileInfo none ``Gio.ZlibDecompressor.file-info`` FileInfo none ``Gio.Emblem.icon`` GObject.Object none ``Gio.TlsCertificate.issuer`` TlsCertificate none ``Gio.TlsConnection.certificate`` TlsCertificate none ``Gio.TlsConnection.peer-certificate`` TlsCertificate none ``Gio.DBusObjectManagerClient.connection`` DBusConnection none ``Gio.DBusObjectManagerServer.connection`` DBusConnection none ``Gio.DBusObjectProxy.g-connection`` DBusConnection none ``Gio.DBusProxy.g-connection`` DBusConnection none ``Gio.InetAddressMask.address`` InetAddress none ``Gio.InetSocketAddress.address`` InetAddress none ``Gio.Application.action-group`` ActionGroup none ``Gio.UnixFDMessage.fd-list`` UnixFDList none ``Gio.FilterInputStream.base-stream`` InputStream none ``Gio.IOStream.input-stream`` InputStream none ``Gio.Socket.local-address`` SocketAddress none ``Gio.Socket.remote-address`` SocketAddress none ``Gio.SocketClient.local-address`` SocketAddress none ``Gio.TlsConnection.interaction`` TlsInteraction none ``GnomeDesktop.IdleMonitor.device`` Gdk.Device none ``GnomeDesktop.RRScreen.gdk-screen`` Gdk.Screen none ``GnomeDesktop.RRConfig.screen`` RRScreen none ``Gladeui.DesignView.project`` Project none ``Gladeui.Inspector.project`` Project none ``Gladeui.Palette.project`` Project none ``Gladeui.Widget.project`` Project none ``Gladeui.Editor.widget`` Widget none ``Gladeui.SignalModel.widget`` Widget none ``Gladeui.Widget.parent`` Widget none ``Gladeui.Widget.template`` Widget none ``Gladeui.BaseEditor.container`` GObject.Object none ``Gladeui.Widget.object`` GObject.Object none ``Gladeui.Project.add-item`` WidgetAdaptor none ``Gladeui.Widget.adaptor`` WidgetAdaptor none ``Gck.Object.module`` Module none ``Gck.Password.module`` Module none ``Gck.Session.module`` Module none ``Gck.Slot.module`` Module none ``Gck.Object.session`` Session none ``Gck.Password.key`` Object none ``Gck.Password.token`` Slot none ``Gck.Session.slot`` Slot none ``Gck.Enumerator.interaction`` Gio.TlsInteraction none ``Gck.Session.interaction`` Gio.TlsInteraction none ``Gck.Enumerator.chained`` Enumerator none ``Soup.MultipartInputStream.message`` Message none ``Soup.Request.session`` Session none ``Soup.Session.tls-database`` Gio.TlsDatabase none ``Soup.Message.tls-certificate`` Gio.TlsCertificate none ``Soup.Server.tls-certificate`` Gio.TlsCertificate none ``Soup.Socket.tls-certificate`` Gio.TlsCertificate none ``Soup.Server.interface`` Address none ``Soup.Session.local-address`` Address none ``Soup.Socket.local-address`` Address none ``Soup.Socket.remote-address`` Address none ``Peas.ExtensionSet.engine`` Engine none ``Peas.Activatable.object`` GObject.Object none ``Gcr.SystemPrompt.secret-exchange`` SecretExchange none ``Gcr.CertificateRequest.private-key`` Gck.Object none ``Gcr.FilterCollection.underlying`` Collection none ``Gcr.Importer.interaction`` Gio.TlsInteraction none ``Atk.Object.accessible-parent`` Object none ``Atk.Object.accessible-table-caption-object`` Object none ``Atk.Object.accessible-table-column-header`` Object none ``Atk.Object.accessible-table-row-header`` Object none ``Atk.Object.accessible-table-summary`` Object none ========================================================== ========================= =========== ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/analysis/signal_transfer.rst0000664000000000000000000002567115074673150022643 0ustar00rootrootSignal Transfer Analysis ======================== .. code-block:: bash $ gir-query --print-closure-arg-types "Object,GObject.Object,Widget,Gtk.Widget,Atk.Object" | grep "|| signal ||" ============================================================== =============== ============= =============== =========== Closure Arg Closure Type **Direction** **Arg Type** **Transfer** ============================================================== =============== ============= =============== =========== ``GcrUi.ImportButton.imported.importer`` signal in GObject.Object none ``GcrUi.ImportButton.importing.importer`` signal in GObject.Object none ``Gtk.PrintOperation.create-custom-widget`` signal out GObject.Object none ``Gtk.AccelGroup.accel-activate.acceleratable`` signal in GObject.Object none ``Gtk.TextTag.event.object`` signal in GObject.Object none ``Gtk.ActionGroup.connect-proxy.proxy`` signal in Widget none ``Gtk.ActionGroup.disconnect-proxy.proxy`` signal in Widget none ``Gtk.Assistant.prepare.page`` signal in Widget none ``Gtk.Container.add.object`` signal in Widget none ``Gtk.Container.remove.object`` signal in Widget none ``Gtk.Container.set-focus-child.object`` signal in Widget none ``Gtk.HandleBox.child-attached.widget`` signal in Widget none ``Gtk.HandleBox.child-detached.widget`` signal in Widget none ``Gtk.MenuShell.insert.child`` signal in Widget none ``Gtk.Notebook.create-window.page`` signal in Widget none ``Gtk.Notebook.page-added.child`` signal in Widget none ``Gtk.Notebook.page-removed.child`` signal in Widget none ``Gtk.Notebook.page-reordered.child`` signal in Widget none ``Gtk.Notebook.switch-page.page`` signal in Widget none ``Gtk.Overlay.get-child-position.widget`` signal in Widget none ``Gtk.PrintOperation.custom-widget-apply.widget`` signal in Widget none ``Gtk.PrintOperation.update-custom-widget.widget`` signal in Widget none ``Gtk.UIManager.add-widget.widget`` signal in Widget none ``Gtk.UIManager.connect-proxy.proxy`` signal in Widget none ``Gtk.UIManager.disconnect-proxy.proxy`` signal in Widget none ``Gtk.Widget.hierarchy-changed.previous_toplevel`` signal in Widget none ``Gtk.Widget.parent-set.old_parent`` signal in Widget none ``Gtk.Window.set-focus.object`` signal in Widget none ``Gst.Object.deep-notify.prop_object`` signal in Object none ``Gst.ChildProxy.child-added.object`` signal in GObject.Object none ``Gst.ChildProxy.child-removed.object`` signal in GObject.Object none ``Gtk.PrintOperation.create-custom-widget`` signal out GObject.Object none ``Gtk.TextLayout.allocate-child.object`` signal in Object none ``Gtk.AccelGroup.accel-activate.acceleratable`` signal in GObject.Object none ``Gtk.TextTag.event.object`` signal in GObject.Object none ``Gtk.ActionGroup.connect-proxy.proxy`` signal in Widget none ``Gtk.ActionGroup.disconnect-proxy.proxy`` signal in Widget none ``Gtk.Assistant.prepare.page`` signal in Widget none ``Gtk.Container.add.object`` signal in Widget none ``Gtk.Container.remove.object`` signal in Widget none ``Gtk.Container.set-focus-child.object`` signal in Widget none ``Gtk.HandleBox.child-attached.object`` signal in Widget none ``Gtk.HandleBox.child-detached.object`` signal in Widget none ``Gtk.List.select-child.object`` signal in Widget none ``Gtk.List.unselect-child.object`` signal in Widget none ``Gtk.Notebook.create-window.page`` signal in Widget none ``Gtk.Notebook.page-added.child`` signal in Widget none ``Gtk.Notebook.page-removed.child`` signal in Widget none ``Gtk.Notebook.page-reordered.child`` signal in Widget none ``Gtk.PrintOperation.custom-widget-apply.widget`` signal in Widget none ``Gtk.PrintOperation.update-custom-widget.widget`` signal in Widget none ``Gtk.TipsQuery.widget-entered.object`` signal in Widget none ``Gtk.TipsQuery.widget-selected.object`` signal in Widget none ``Gtk.UIManager.add-widget.widget`` signal in Widget none ``Gtk.UIManager.connect-proxy.proxy`` signal in Widget none ``Gtk.UIManager.disconnect-proxy.proxy`` signal in Widget none ``Gtk.Widget.hierarchy-changed.previous_toplevel`` signal in Widget none ``Gtk.Widget.parent-set.old_parent`` signal in Widget none ``Gtk.Window.set-focus.object`` signal in Widget none ``NMClient.DeviceWifi.access-point-added.ap`` signal in GObject.Object none ``NMClient.DeviceWifi.access-point-removed.ap`` signal in GObject.Object none ``NMClient.DeviceWimax.nsp-added.nsp`` signal in GObject.Object none ``NMClient.DeviceWimax.nsp-removed.nsp`` signal in GObject.Object none ``NMClient.RemoteSettings.new-connection.object`` signal in GObject.Object none ``Gio.SocketService.incoming.source_object`` signal in GObject.Object none ``Gio.ThreadedSocketService.run.source_object`` signal in GObject.Object none ``Json.Parser.object-end.object`` signal in Object none ``Json.Parser.object-member.object`` signal in Object none ``GnomeDesktop.BGCrossfade.finished.window`` signal in GObject.Object none ``Gladeui.BaseEditor.build-child`` signal out GObject.Object None ``Gladeui.App.signal-editor-created.signal_editor`` signal in GObject.Object none ``Gladeui.App.widget-adaptor-registered.adaptor`` signal in GObject.Object none ``Gladeui.BaseEditor.build-child.gparent`` signal in GObject.Object none ``Gladeui.BaseEditor.change-type.object`` signal in GObject.Object none ``Gladeui.BaseEditor.child-selected.gchild`` signal in GObject.Object none ``Gladeui.BaseEditor.delete-child.gparent`` signal in GObject.Object none ``Gladeui.BaseEditor.delete-child.gchild`` signal in GObject.Object none ``Gladeui.BaseEditor.get-display-name.gchild`` signal in GObject.Object none ``Gladeui.BaseEditor.move-child.gparent`` signal in GObject.Object none ``Gladeui.BaseEditor.move-child.gchild`` signal in GObject.Object none ``Gladeui.Project.add-widget.arg1`` signal in Widget none ``Gladeui.Project.remove-widget.arg1`` signal in Widget none ``Gladeui.Project.widget-name-changed.arg1`` signal in Widget none ``Gladeui.Project.widget-visibility-changed.widget`` signal in Widget none ``Gck.Module.authenticate-object.object`` signal in Object none ``Soup.Session.connection-created.connection`` signal in GObject.Object none ``Soup.Session.tunneling.connection`` signal in GObject.Object none ``Peas.ExtensionSet.extension-added.exten`` signal in GObject.Object none ``Peas.ExtensionSet.extension-removed.exten`` signal in GObject.Object none ============================================================== =============== ============= =============== =========== ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/dev_environ.rst0000664000000000000000000001511315074673150020143 0ustar00rootroot.. include:: ../icons.rst .. _devenv: ################################## Creating a Development Environment ################################## This describes how to setup a development environment for working on a project that uses PyGObject, or for working on PyGObject itself. Please follow the instructions on ":ref:`gettingstarted`" first, as they are a pre-requirement. .. _pipenv-setup: ***************** Environment Setup ***************** .. _install-dependencies: Install Dependencies ==================== In order to compile Python and pip install pygobject, dependencies are need for your operating system. =========================================== ======================================== ============================================== |ubuntu-logo| :ref:`Ubuntu ` |fedora-logo| :ref:`Fedora ` |arch-logo| :ref:`Arch Linux ` |windows-logo| :ref:`Windows ` |macosx-logo| :ref:`macOS ` |opensuse-logo| :ref:`openSUSE ` =========================================== ======================================== ============================================== .. _ubuntu-dep: |ubuntu-logo| Ubuntu / |debian-logo| Debian ------------------------------------------- .. code:: console sudo apt-get install -y python3-venv python3-wheel python3-dev sudo apt-get install -y gobject-introspection libgirepository-2.0-dev \ gir1.2-girepository-3.0 build-essential libbz2-dev libreadline-dev \ libssl-dev zlib1g-dev libsqlite3-dev wget curl llvm libncurses-dev \ xz-utils tk-dev libcairo2-dev .. _fedora-dep: |fedora-logo| Fedora -------------------- .. code:: console sudo dnf install -y python3-wheel sudo dnf install -y gcc zlib-devel bzip2 bzip2-devel readline-devel \ sqlite sqlite-devel openssl-devel tk-devel git python3-cairo-devel \ cairo-gobject-devel gobject-introspection-devel .. _arch-dep: |arch-logo| Arch Linux ---------------------- .. code:: console sudo pacman -S --noconfirm python-wheel sudo pacman -S --noconfirm base-devel openssl zlib git gobject-introspection .. _opensuse-dep: |opensuse-logo| openSUSE ------------------------ .. code:: console sudo zypper install -y python3-wheel gobject-introspection-devel \ python3-cairo-devel openssl zlib git sudo zypper install --type pattern devel_basis .. _windows-dep: |windows-logo| Windows ---------------------- To develop on Windows you need to have `MSYS2 `_ installed. .. code:: console pacman -S --needed --noconfirm base-devel mingw-w64-ucrt-x86_64-toolchain git \ mingw-w64-ucrt-x86_64-python mingw-w64-ucrt-x86_64-pycairo \ mingw-w64-ucrt-x86_64-gobject-introspection mingw-w64-ucrt-x86_64-libffi .. _macosx-dep: |macosx-logo| macOS ------------------- With homebrew: .. code:: console brew update brew install python3 gobject-introspection libffi export PKG_CONFIG_PATH=$(brew --prefix libffi)/lib/pkgconfig # use /usr/local/ for older Homebrew installs .. _install-pyenv: Install `pyenv`_ (Optional) =========================== `pyenv`_ lets you easily switch between multiple versions of Python. ============================================= ========================================= |linux-logo| :ref:`Linux ` |macosx-logo| :ref:`macOS ` ============================================= ========================================= .. _linux-pyenv: |linux-logo| Linux ------------------ .. code:: console curl https://pyenv.run | bash exec $SHELL pyenv install 3.11 pyenv global 3.11 .. _macosx-pyenv: |macosx-logo| macOS ------------------- .. code:: console brew install pyenv pyenv install 3.11 pyenv global 3.11 .. _projects-pygobject-dependencies: ***************** Work on PyGObject ***************** .. _platform-ind-steps: Platform Independent Steps ========================== First, check out the source code: .. code:: console git clone https://gitlab.gnome.org/GNOME/pygobject.git cd pygobject With a local copy of PyGObject, there's three ways to start developing: 1. PDM, a modern Python package and dependency manager 2. Pip, the default Python package installer 3. Meson, use the Meson build system directly PDM --- Make sure you have `PDM `_ 2.13 or newer installed. Then set up the project by running: .. code:: console pdm install You can run the unit tests with: .. code:: console pdm run pytest Pip --- It's always a good idea to work from within a Python virtual environment. PyGObject is built with `Meson `_. In order to support `editable installs `_, Meson-python, Meson, and Ninja should be installed in the virtual environment. .. code:: console python3 -m venv .venv source .venv/bin/activate python3 -m pip install meson-python meson ninja pycairo pytest pre-commit .. note:: For Python 3.12 and newer, also install ``setuptools``, since distutils is no longer provided in the standard library. Install PyGObject in your local environment with the ``--no-build-isolation`` to allow for dynamic rebuilds .. code:: console pip install --no-build-isolation --config-settings=setup-args="-Dtests=true" -e '.[dev]' By default the C libraries are built in "release" mode (no debug symbols). To compile the C libraries with debug symbols, run .. code:: console pip install --no-build-isolation --config-settings=setup-args="-Dbuildtype=debug" --config-settings=setup-args="-Dtests=true" -e '.[dev]' Open a Python console: .. code:: python from gi.repository import GObject Run the unittests: .. code:: console pytest Meson ----- It's also possible to run the tests from Meson. Tests are still run with Pytest, so it's important that Pytest is installed. .. code:: console meson setup _build # Needed only once meson test -C _build Contributing Changes ==================== First off, thank you for considering contributing to PyGObject. We really appreciate it! * Create your own fork of the repository * Add tests for your changes * Do the changes in your fork * If you like the change and think the project could use it: * Make sure you are following the `GNOME Code of Conduct `_ * Be sure you have the pre-commit hook installed with: .. code:: console pre-commit install It will ensure that lint and code formatting tools are run automatically. * Commit your changes * Create a merge request .. _pyenv: https://github.com/pyenv/pyenv ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/gbytes_marshaller_tutorial.rst0000664000000000000000000002143215074673150023260 0ustar00rootroot======================================== Tutorial - Adding a GBytes Marshaler ======================================== This tutorial is based on a request for adding a Python bytes to GBytes argument marshaler for introspected functions (`GnomeBug 729541 `_). Working with GI Interactively ============================= To get started, we can inspect a GI function which takes a GBytes argument interactively to determine what the argument is in terms of GI (ipython is very helpful here): PyGI exposes GI functions as custom callable objects which also implement the `GIFunctionInfo API `_ and its base classes. .. code-block:: python >>> from gi.repository import GLib >>> Gio.MemoryInputStream.new_from_bytes gi.FunctionInfo(new_from_bytes) Get the GIArgInfo: .. code-block:: python >>> Gio.MemoryInputStream.new_from_bytes.get_arguments() (gi.ArgInfo(bytes),) >>> arg, = _ >>> arg gi.ArgInfo(bytes) Determine argument type using: .. code-block:: python >>> ty = arg.get_type() >>> ty gi.TypeInfo(type_type_instance) >>> ty.get_tag_as_string() 'interface' At this point we know the argument type tag is an "interface" or `GI_TYPE_TAG_INTERFACE `_ so `g_type_info_get_interface `_ should be valid for the `GITypeInfo `_. .. code-block:: python >>> iface = ty.get_interface() StructInfo(Bytes) In this case get_interface() is giving us a `GIStructInfo `_. We can then verify a valid GType is available using `gi_registered_type_info_get_g_type() `_ (GIRegisteredTypeInfo is a base class of GIStructInfo): .. code-block:: python >>> gtype = iface.get_g_type() >>> gtype We also have to find the fundamental GType for GBytes: .. code-block:: python >>> gtype.fundamental Mapping out the C Code ====================== We now have enough information to correlate to the various switch statements in the PyGI caching system which will help us place our new marshaling code. Starting with `pygi-cache.c:pygi_arg_cache_new `_ you can trace through `_arg_cache_new_for_interface `_ and finally land in `pygi-struct-marshal.c:pygi_arg_struct_new_from_info `_. For this bug, we are looking to add a "from py" marshaling convenience. So we could add a new conditional in `_pygi_marshal_from_py_interface_struct `_ within the G_TYPE_BOXED conditional. However, note this text in the function: .. code-block:: c /* FIXME: handle this large if statement in the cache * and set the correct marshaller */ What this means is _pygi_marshal_from_py_interface_struct is actually dispatching to sub-types of GIStructInfo at runtime for every argument. Not very ideal considering we have this whole caching system for marshaling arguments. Instead what we should really do is create a new from_py_marshaller and from_py_cleanup callback pair specifically for GBytes arguments which are baked in at cache setup time. Essentially specializing GBytes as early as possible in `_arg_cache_from_py_interface_struct_setup `_ by setting arg_cache->from_py_marshaller and arg_cache->from_py_cleanup. Marshaler Callbacks =================== Relevant marshaler callbacks are declared in `pygi-cache.h `_ and we need an implementation of both PyGIMarshalFromPyFunc and PyGIMarshalCleanupFunc. .. code-block:: c typedef gboolean (*PyGIMarshalFromPyFunc) (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data); typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, /* always NULL for to_py cleanup */ gpointer data, gboolean was_processed); PyGIMarshalFromPyFunc is called for each argument prior to executing the callee, the relevant bits are as follows: * py_arg - This is the input PyObject the Python caller is passing to the GI function. We need to type check this and do a mini dispatch depending on the type (PyBytes or buffer protocol check, PyGIBoxed, and Py_None). * arg - This is the target memory area marshaler will fill out. In this case arg->v_pointer will be assigned a pointer to a GBytes object. * arg_cache->allow_none - If TRUE, py_arg can be Py_None and arg->v_pointer should be set to NULL, returning TRUE from the marshaling callback. * arg_cache->transfer - Determines how memory should be managed for the argument. * cleanup_data - This is an output argument that can be set to custom data which passed back to us in the cleanup callback as "data", used for freeing relevant memory after the callee returns. In our case this will either be NULL or a GBytes pointer, in which case we should call g_bytes_unref() on the data. PyGIMarshalCleanupFunc is called after the callee finishes and to cleanup any temporary data we created while the callee was running. Transfer Semantics ================== A py_arg input of type PyGIBoxed is a direct wrapping of an existing GBoxed. This is a fairly simple case to deal with, we just need to extract the boxed pointer (pyg_boxed_get) and assign it to arg->v_pointer. For GI_TRANSFER_EVERYTHING we also need to add a reference the callee can own by calling g_bytes_ref on this pointer. In the case where we are passed a PyBytes (or Python object implementing the buffer protocol), we need to create a new GBytes which holds a pointer to the PyBytes data. Zero copy can easily be achieved when transfer is GI_TRANSFER_NOTHING because a read-only buffer can be retrieved from Python and passed to the GBytes constructor (without a free_func). We know the lifetime of the PyBytes is valid at least until the callee completes. The trick here is we also need to set *cleanup_data* to the newly created GBytes so our cleanup callback can free the GBytes. Since we didn't set a free_func when constructing the GBytes, calling g_bytes_unref will not touch our Python owned data. For converting a PyBytes with transfer mode as GI_TRANSFER_EVERYTHING, we basically follow the same as above with some extra tricks. Since the callee is intending to own the GBytes we pass it, we must pass it something which is guaranteed to survive after our Python function returns (must exist after our cleanup callback). The easiest technique here is to memcpy the result of the PyBytes data and construct a GBytes using g_bytes_new_with_free_func, with a free_func of g_free and user_data of the bytes (no need for setting cleanup_data because the C callee owns everything). However, it is possible to achieve zero copy with PyBytes and GI_TRANSFER_EVERYTHING by creating a custom free_func which calls Py_DECREF. However, this free_func must wrap any Python API calls with PyGILState_Ensure/Release pairs: .. code-block:: c void threaded_py_bytes_free (PyObject *py_bytes) { PyGILState_STATE state = PyGILState_Ensure (); Py_DECREF (py_bytes); PyGILState_Release (state); } gboolean marshal (...) { /* ... py_arg type and transfer checks ... */ char *buf = NULL; Py_ssize_t length; PyBytes_AsStringAndSize (py_arg, &buf, &length); arg->v_pointer = g_bytes_new_with_free_func (buf, length, threaded_py_bytes_free, py_arg); *cleanup_data = NULL; return True; The above zero copy implementation could also possibly be implemented using memoryviews for accessing a Py_buffer instead of requiring a PyBytes type as input. Marshaler Implementation ======================== This section is left up to the reader as an exercise, remember to write tests! ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/index.rst0000664000000000000000000000050615074673150016734 0ustar00rootroot================= Development Guide ================= .. toctree:: :titlesonly: :maxdepth: 1 overview dev_environ style_guide override_guidelines gbytes_marshaller_tutorial initializer_deprecations introspection_porting profiling maintguide packagingguide analysis/index ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/initializer_deprecations.rst0000664000000000000000000000722015074673150022710 0ustar00rootroot======================== Initializer Deprecations ======================== Starting with PyGObject 3.11, overridden object creation and initialization (``__new__`` and ``__init__`` respectively) that contain side effects or dispatching beyond standard object creation with `g_object_newv `_ will issue deprecation warnings. Additionally, positional arguments and non-standard keyword argument names will also show deprecation warnings. Deprecations will be in the form of Gtk.PyGTKDeprecationWarning. These warnings are only issued in development releases (odd minor version, 3.9, 3.11, etc...). Stable releases with even minor versions will not show deprecations unless the "-Wd" command line option is specified when running Python. Updating calls which invoke these deprecations will work across all of the 3.x releases (backwards and forwards compatible) with the exception of Gtk.RecentChooserDialog(). With RecentChooserDialog, updating the "manager" argument to "recent_manager" (when used either positionally or as a keyword) is not compatible with versions of PyGObject prior to 3.11. However, the "manager" keyword is guaranteed to work across all versions of the 3.x series (even though a deprecation is printed). Rational ======== 1. Cut down class overrides for the benefit of performance. Having a large amount of class overrides causes each of the class types to be loaded and all of its GI methods added. 2. Avoid the potential for silent creation bugs like `GnomeBug 711487 `_ and inheritance confusion `GnomeBug 721226 `_. 3. Ensure consistency across all GObject creation. In essence, we would like to guarantee all objects can be created with the same technique: taking a variable number of keyword arguments mapped exactly to the classes property names as defined by using `g_object_newv `_. This will greatly help consistency, documentation, and discoverability/expectation once the API user understands property names are valid keyword arguments for object construction. 4. Additional side effects when creating objects belong in explicitly named function (e.g. Gtk.IconSet.new_from_pixbuf) as opposed to overloading initializers to dispatch functionality. 5. Dispatching/overloaded methods in general should be considered a sort of "anti-pattern". They add unnecessary support by requiring new methods of a similar class also be added to the dispatch. It also means we have to maintain custom documentation for the dispatching method. Additionally it can hurt readability when compared using explicitly named methods. Examples: .. code-block:: python cursor = Gdk.Cursor(display, cursor_type) cursor = Gdk.Cursor(display, pixbuf, x, y) The prior example at least uses variable names which give a clue to the reader. A worse example is shown with badly named variables: .. code-block:: python cursor = Gdk.Cursor(disp, c) cursor = Gdk.Cursor(disp, c, x, y) Explicit object creation enforces better readability as well as discoverability of documentation without having to dig into the dispatching method to figure out what is going on: .. code-block:: python cursor = Gdk.Cursor.new_for_display(display, cursor_type) cursor = Gdk.Cursor.new_from_pixbuf(display, pixbuf, x, y) References ========== * Bugzilla ticket for this deprecation: `GnomeBug 705810 `_ * `Mailing List Discussion `_ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/introspection_porting.rst0000664000000000000000000005146515074673150022301 0ustar00rootroot============================ Introspection Porting Guide ============================ .. contents:: :local: Beginning ========= Starting with PyGObject 3.1.92 there's a module called pygtkcompat which will make it easier to port an application from PyGTK. There are two different approaches to porting your application from PyGTK to gobject-introspection: 1. Using a PyGTK compatibility layer (pygtkcompat) 2. Using a shell script which converts the callsites (``pygi-convert.sh``) There are advantages and disadvantages with both: 1. Using pygtkcompat makes it possible to focus on porting to Gtk 3.x while not changing anything else, users and developers can keep on using the software as before. 2. Using pygtkcompat allows you to support both Gtk 2.x and Gtk 3.x with the same code base 3. Using ``pygi-convert.sh`` you can avoid using any layers and use the supported API directly Using pygtkcompat ----------------- The pygtkcompat module provides a PyGTK compatible API on top of gobject-introspection which makes it possible to run your application on top of **both** PyGTK and gobject-introspection at the same time. Before using it you should port your application to using latest API, available 2.24, for instance:: widget.window should be widget.get_window() container.child should be container.get_child() widget.flags() & gtk.REALIZED should be container.get_realized() and so on. Once an application has been updated to the latest PyGTK API, you can then import pygtkcompat and enable the parts you need. For instance, to enable PyGTK compatible API on top of the Gtk 3.0 typelib, use the following: .. code-block:: python from gi import pygtkcompat pygtkcompat.enable() pygtkcompat.enable_gtk(version='3.0') That's it, if you're lucky enough and you're not using any strange/weird apis you should be able to run your application. If you want an app to be compatible with both PyGTK and PyGI, you can use the following technique: .. code-block:: python try: from gi import pygtkcompat except ImportError: pygtkcompat = None if pygtkcompat is not None: pygtkcompat.enable() pygtkcompat.enable_gtk(version='3.0') import gtk .. note:: Porting the application from 2 to 3 is best covered in https://docs.gtk.org/gtk3/migrating-2to3.html. That usually includes things such as change expose-event to draw and do drawing with cairo. How does PyGI work? =================== Initial GI support was added to pygobject in version 2.19.0 (August 2009), but the entire GI/pygobject/annotations stack really only stabilized in version 2.28, so that in practice you will need at least this version and the corresponding latest upstream releases of GTK and other libraries you want to use. pygobject provides a ``gi.repository`` module namespace which generates virtual Python modules from installed typelibs on the fly. For example, if you have the GIR for GTK 3 installed, you can do: .. code-block:: console $ python -c 'from gi.repository import Gtk; print Gtk' and use it just like any other Python module. Absolutely unexpected first example: .. code-block:: console $ python -c 'from gi.repository import Gtk; Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, "Hello World").run()' Let's look at the corresponding C declaration: .. code-block:: c GtkWidget* gtk_message_dialog_new (GtkWindow *parent, GtkDialogFlags flags, GtkMessageType type, GtkButtonsType buttons, const gchar *message_format, ...); and the C call: .. code-block:: c GtkMessageDialog* msg = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "Hello World"); msg.run() So what do we see here? 1. The C API by and large remains valid in Python (and other languages using the GI bindings), in particular the structure, order, and data types of arguments. There are a few exceptions which are mostly due to the different way Python works, and in some cases to make it easier to write code in Python; see below for details. But this means that you can (and should) use the normal API documentation for the C API of the library. Devhelp is your friend! 2. As Python is a proper object oriented language, pygobject (and in fact the GI typelib already) expose a GObject API as proper classes, objects, methods, and attributes. I. e. in Python you write .. code-block:: python button = Gtk.Button() button.set_label("foo") instead of the C gobject syntax .. code-block:: c GtkWidget* button = gtk_button_new(...); gtk_button_set_label(button, "foo"); The class names in the typelib (and thus in Python) are derived from the actual class names stated in the C library (like ``GtkButton``), except that the common namespace prefix (``Gtk`` here) is stripped, as it becomes the name of the module. 3. Global constants would be a heavy namespace clutter in Python, and thus pygobject exposes them in a namespaced fashion as well. I. e. if the ``MessageDialog`` constructor expects a constant of type ``GtkMessageType``, then by above namespace split this becomes a Python class ``Gtk.MessageType`` with the individual constants as attributes, e. g. ``Gtk.MessageType.INFO``. 4. Data types are converted in a rather obvious fashion. E. g. when the C API expects an ``int*`` array pointer, you can supply a normal Python array ``[0, 1, 2]``. A Python string ``"foo"`` will match a ``gchar*``, Pythons ``None`` matches ``NULL``, etc. So the GObject API actually translates quite naturally into a real OO language like Python, and after some time of getting used to above transformation rules, you should have no trouble translating the C API documentation into their Python equivalents. When in doubt, you can always look for the precise names, data types, etc. in the .gir instead, which shows the API broken by class, method, enum, etc, with the exact names and namespaces as they are exposed in Python. As I mentioned above, this is in no way restricted to GTK, GNOME, or UI. For example, if you handle any kind of hardware and hotplugging, you almost certainly want to query udev, which provides a nice glib integration (with signals) through the gudev library. This example lists all block devices (i. e. hard drives, USB sticks, etc.): .. code-block:: pycon >>> from gi.repository import GUdev >>> c = GUdev.Client() >>> for dev in c.query_by_subsystem("block"): ... print dev.get_device_file() ... /dev/sda /dev/sda1 /dev/sda2 [...] See `the GUDevClient documentation `_ for the corresponding C API. GI is not even restricted to GObject, you can annotate any non-OO function based API with it. E. g. there is already a ``/usr/share/gir-1.0/xlib-2.0.gir`` (although it's horribly incomplete). These will behave as normal functions in Python (or other languages) as well. Differences to the C API ======================== The structure of method arguments is by and large the same in C and in GI/Python. There are some notable exceptions which you must be aware of: Constructors ------------ The biggest one is constructors. There is actually two ways of calling one: * Use the real constructor implementation from the library. Unlike in normal Python you need to explicitly specify the constructor name: .. code-block:: python Gtk.Button.new() Gtk.Button.new_with_label("foo") * Use the standard GObject constructor and pass in the initial property values as named arguments: .. code-block:: python Gtk.Button(label="foo", use_underline=True) The second is actually the recommended one, as it makes the meaning of the arguments more explicit, and also underlines the GObject best practice that a constructor should do nothing more than to initialize properties. But otherwise it's pretty much a matter of taste which one you use. Passing arrays -------------- Unlike C, higher level languages know how long an array is, while in the C API you need to specify that explicitly, either by terminating them with ``NULL`` or explicitly giving the length of the array in a separate argument. Which one is used is already specified in the annotations and thus in the typelib, so Python can automatically provide the right format without the developer needing to append an extra ``None`` or a separate len(my_array) argument. For example, in C you have .. code-block:: c gtk_icon_theme_set_search_path (GtkIconTheme *icon_theme, const gchar *path[], gint n_elements) In Python you can just call this as .. code-block:: python my_icon_theme.set_search_path(['/foo', '/bar']) and don't need to worry about the array size. Output arguments ---------------- C functions can't return more than one argument, so they often use pointers which the function then fills out. Conversely, Python doesn't know about pointers, but can easily return more than one value as a tuple. The annotations already describe which arguments are "out" arguments, so in Python they become part of the return tuple: first one is the "real" return value, and then all out arguments in the same order as they appear in the declaration. For example: .. code-block:: c GdkWindow* gdk_window_get_pointer (GdkWindow *window, gint *x, gint *y, GdkModifierType *mask) In Python you would call this like .. code-block:: python x, y, mask = mywindow.get_pointer() The Python help system shows the correct input, output and return argument expectations: .. code-block:: pycon >>> from gi.repository import Gdk >>> help(Gdk.Window.get_pointer) Help on function get_pointer: get_pointer(*args, **kwargs) get_pointer(self) -> x:int, y:int, mask:Gdk.ModifierType GDestroyNotify -------------- Some GLib/GTK functions take a callback method and an extra ``user_data`` argument that is passed to the callback. In C they often also take a ``GDestroyNotify`` function which is run once all callbacks are done, in order to free the memory of user_data. As Python has automatic memory management, pygobject will take care of all this by itself, so you simply don't specify the GDestroyNotify argument. For example: .. code-block:: c void gtk_enumerate_printers (GtkPrinterFunc func, gpointer user_data, GDestroyNotify destroy, gboolean wait) In Python you call this as .. code-block:: python Gtk.enumerate_printers(my_callback, my_user_data, True) Non-introspectable functions/methods ------------------------------------ When you work with PyGI for a longer time, you'll inevitably stumble over a method that simply doesn't exist in the bindings. These usually are marked with ``introspectable="0"`` in the GIR. In the best case this is because there are some missing annotations in the library which don't have a safe default, so GI disables these to prevent crashes. They usually come along with a corresponding warning message from g-ir-scanner, and it's usually quite easy to fix these. Another common case are functions which take a variable number of arguments, such as ``gtk_cell_area_add_with_properties()``. Varargs cannot be handled safely by libgirepository. In these cases there are often alternatives available (such as ``gtk_cell_area_cell_set_property()``). For other cases libraries now often have a ``..._v()`` counterpart which takes a list instead of variable arguments. Threads ======= For using threads with PyGObject, please see: `Threads/Concurrency with Python and the GNOME Platform <./Projects(2f)PyGObject(2f)Threading.html>`_ Overrides ========= A specialty of pygobject is the possibility of replacing functions, methods, or classes of the introspected library with custom code, called "overrides". As the goal is to stay very close to the original API, they should be used and written sparsely, though. One major use case is to provide replacements for unintrospectable methods. For example, ``Gtk.Menu.popup()`` is not introspectable in GTK, but the GTK override implements this method in terms of ``Gtk.Menu.popup_for_device()``, so in this case the override actually helps to get closer to the original API again. Another important case is automatic data type conversion, most prominently to allow passing unicode objects to methods which expect an UTF-8 encoded ``gchar*``. This also actually helps to prevent workarounds in application code and maintain a clean API. Thirdly, overrides are useful if they help to massively ease development. For example it is quite laborious to do GDBus calls or GVariant constructions with the native Gio/GLib API. pygobject offers convenience overrides to make these a lot simpler and more Pythonic, but of course without actually breaking the original API. Overrides should be quite easy to understand. In general you should not even be required to know about it, as most of them really just fix stuff to work as expected. :-) Porting from PyGTK 2 to PyGI GTK 3 =================================== Note that this is really two migrations in one step, but is recommended as GTK2 still has a lot of breakage with PyGI. It is recommended to port applications to PyGI/GTK+ 3 first, then port to Python 3 as an additional step if Python 3 support is desired. Otherwise you can end up with a conflated and hard to track set of changes. See the `GTK2 → GTK3 migration documentation `_. If we compare the PyGTK vs. PyGI code for a "Hello" message box, we see that it's actually very similar in structure: .. code-block:: console $ python -c 'import gtk; gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, "Hello World").run()' vs. .. code-block:: console $ python -c 'from gi.repository import Gtk; Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, "Hello World").run()' So PyGTK also does the representation of the C functions as proper classes and methods, thus if you port from PyGTK to PyGI, the structure by and large remains the same. Step 1: The Great Renaming -------------------------- The biggest part in terms of volume of code changed is basically just a renaming exercise. E. g. ``gtk.*`` now becomes ``Gtk.*``, and ``gtk.MESSAGE_INFO`` becomes ``Gtk.MessageType.INFO``. Likewise, the imports need to be updated: ``import gtk`` becomes ``from gi.repository import Gtk``. Fortunately this is is a mechanical task which can be automated. The `pygobject git tree `_ has a script `pygi-convert.sh `_ which is a long list of perl -pe 's/old/new/' string replacements. It's really blunt, but surprisingly effective, and for small applications chances are that it will already produce something which actually runs. Note that this script is in no way finished, and should be considered a collaborative effort amongst porters. So if you have something which should be added there, please don't hesitate to open a bug or ping on IRC (#python on irc.gnome.org)). We will be happy to improve the script. When you just run ``pygi-convert.sh`` in your project tree, it will work on all ``*.py`` files. If you have other Python code there which is named differently (such as ``bin/myprogram``), you should run it once more with all these file names as argument. * Make sure you don't keep using the static bindings for a library that we are using through introspection. That would cause wrappers from both bindings be mixed and compatibility issues would arise. Step 2: Wash, rinse, repeat --------------------------- Once the mechanical renamings are out of the way, the tedious and laborious part starts. As Python does not have a concept of "compile-time check" and can't even check that called methods exist or that you pass the right number of parameters, you now have to enter a loop of "start your program", "click around until it breaks", "fix it", "goto 1". The necessary changes here are really hard to generalize, as they highly depend on what your program actually does, and this will also involve the GTK 2 → 3 parts. One thing that comes up a lot are ``pack_start()``/``pack_end()`` calls. In PyGTK they have default values for ``expand``, ``start``, and ``padding`` attributes, but as GTK does not have them, you won't have them in PyGI either (see `bgo#558620 - Add default values `_). .. warning:: Note that you can't do a migration halfway: If you try to import both ``gtk`` and ``gi.repository.Gtk``, you'll get nothing but program hangs and crashes, as you are trying to work with the same library in two different ways. You can mix static and GI bindings of *different* libraries though, such as ``dbus-python`` and ``gi.repository.Gtk``. If your application uses plugins, you can use libpeas. It is a GObject plugins library that support C, Python and Javascript languages though introspection. Step 3: Packaging changes ------------------------- After you have your code running with PyGI and committed it to your branch and released it, you need to update the dependencies of your distro package for PyGI. You should grep your code for "gi.repository" and collect a list of all imported typelibs, and then translate them into the appropriate package name. For example, if you import "Gtk, Notify, Gudev" you need to add dependencies to the packages which ship them: * Debian/Ubuntu ship them in separate packages named ``gir--``, so in this example ``gir1.2-gtk-3.0``, ``gir1.2-notify-0.7``, and ``gir1.2-gudev-1.0``. You can find out with e. g. ``dpkg -S /usr/lib/girepository-1.0/Gtk-3.0.typelib``. * Fedora ships the typelibs together with the shared libraries, so in this example ``gtk3``, ``libgudev1``, ``libnotify``. You can find out with e. g. ``rpm -qf /usr/lib/girepository-1.0/Gtk-3.0.typelib``. At the same time you should drop the old static bindings, like python-gtk2, python-notify, etc. Finally you should also bump the version of the pygobject dependency to (>= 2.28) to ensure that you run with a reasonably bug free PyGI. Examples ======== * pygobject's git tree has a very comprehensive `gtk-demo `_ showing off pretty much all available GTK widgets in PyGI * Examples of previously done pygtk → pyGI ports: * Apport: http://bazaar.launchpad.net/~apport-hackers/apport/trunk/revision/1801 * Jockey: http://bazaar.launchpad.net/~jockey-hackers/jockey/trunk/revision/679 * system-config-printer: https://git.fedorahosted.org/cgit/system-config-printer.git/log/?h=pygi * gtimelog: http://bazaar.launchpad.net/~gtimelog-dev/gtimelog/trunk/revision/181 (this is interesting because it makes the code work with *both* PyGTK and PyGI, whichever is available) Comments ======== * What versions of the python packages do we need, and how do we get the for different distributions (gentoo, deb-based, rpm-based...?) * Can we just fallback to import gtk, gdk.... if we detect old enough python packages, or do we need to perform other workarounds? One of the biggest challenges in porting is that all of the constants have changed names. The above ``pygi-convert.sh`` script gives a good idea about what the new names are, but if you have any problems, refer to the relevant .gir file directly. For example, if your old code says "gtk.TREE_VIEW_COLUMN_AUTOSIZE" and you're not sure what the new code should be, search in /usr/share/gir-1.0/Gtk-2.0.gir for "COLUMN_AUTOSIZE", and you'll find some code that looks like this: .. code-block:: xml Looking at that, you can determine the new constant name. It starts with "Gtk", then a period, then the enumeration name ("TreeViewColumnSizing"), then another period, then the member name in ALL CAPS ("AUTOSIZE"). So, this tells you to change "gtk.TREE_VIEW_COLUMN_AUTOSIZE" into "Gtk.TreeViewColumnSizing.AUTOSIZE" Problems ======== * Listening to signals: if you are listening a signal like "size-allocate" and when you print the allocation you get as the type GdkRectangle instead of CairoRectangleInt, the way to fix it is by overriding the signal instead of listening to it. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/maintguide.rst0000664000000000000000000000174215074673150017756 0ustar00rootroot================ Maintainer Guide ================ Making a Release ---------------- #. Make sure the `meson.build` file contains the right version number #. Update the NEWS file #. Build new version using ``python3 -m build --sdist`` #. Commit NEWS as ``"release 3.X.Y"`` and push #. Tag with: ``git tag -s 3.X.Y -m "release 3.X.Y"`` #. Push tag with: ``git push origin 3.X.Y`` #. In case of a stable release, upload to PyPI: ``twine upload dist/pygobject-3.X.Y.tar.gz`` #. Commit post-release version bump to pyproject.toml #. In case the release happens on a stable branch copy the NEWS changes to the main branch Branching --------- Each cycle after the feature freeze, we create a stable branch so development can continue in the main branch unaffected by the freezes. #. Create the branch locally with: ``git checkout -b pygobject-3-2`` #. Push new branch: ``git push origin pygobject-3-2`` #. In main, update pyproject.toml to what will be the next version number (3.3.0) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/override_guidelines.rst0000664000000000000000000000745515074673150021666 0ustar00rootroot========================== Python Override Guidelines ========================== This document serves as a guide for developers creating new PyGObject overrides or modifying existing ones. This document is not intended as hard rules as there may always be pragmatic exceptions to what is listed here. It is also a good idea to study the Zen of Python by Tim Peters in :pep:`20`. In general, overrides should be minimized and preference should always be placed on updating the underlying API to be more bindable, adding features to GI to support the requirement, or adding mechanical features to PyGObject which can apply generically to all overrides (:bzbug:`721226` and :bzbug:`640812`). If a GI feature or more bindable API for a library is in the works, it is a good idea to avoid the temptation to add temporary short term workarounds in overrides. The reason is this can creaste unnecessary conflicts when the bindable API becomes a reality (:bzbug:`707280`). * Minimize class overrides when possible. *Reason*: Class overrides incur a load time performance penalty because they require the classes GType and all of the Python method bindings to be created. See :bzbug:`705810` * Prefer monkey patching methods on repository classes over inheritance. *Reason*: Class overrides add an additional level to the method resolution order (mro) which has a performance penalty. Since overrides are designed for specific repository library APIs, monkey patching is reasonable because it is utilized in a controlled manner by the API designer (as opposed to monkey patching a third-party library which is more fragile). * Avoid overriding ``__init__`` *Reason*: Sub-classing the overridden class then becomes challenging and has the potential to cause bugs (see :bzbug:`711487` and reasoning listed in :doc:`initializer_deprecations`). * Unbindable functions which take variadic arguments are generally ok to add Python implementations, but keep in mind the prior noted guidelines. A lot of times adding bindable versions of the functions to the underlying library which take a list is acceptable. For example: :bzbug:`706119`. Another problem here is if an override is added, then later a bindable version of the API is added which takes a list, there is a good chance we have to live with the override forever which masks a working version implemented by GI. * Avoid side effects beyond the intended repositories API in function/method overrides. *Reason*: This conflates the original API and adds a documentation burden on the override maintainer. * Don't change function signatures from the original API and don't add default values. *Reason*: This turns into a documentation discrepancy between the libraries API and the Python version of the API. Default value work should focus on bug :bzbug:`558620`, not cherry-picking individual Python functions and adding defaults. * Avoid implicit side effects to the Python standard library (or anywhere). * Don't modify or use sys.argv *Reason*: sys.argv should only be explicitly controlled by application developers. Otherwise it requires hacks to work around a module modifying or using the developers command line args which they rightfully own. .. code:: python saved_argv = sys.argv.copy() sys.argv = [] from gi.repository import Gtk sys.argv = saved_argv * Never set Pythons default encoding. *Reason*: Read or watch Ned Batchelders "`Pragmatic Unicode `__" * Prefer adapter patterns over of inheritance and overrides. *Reason*: An adapter allows more flexibility and less dependency on overrides. It allows application developers to use the raw GI API without having to think about if a particular typelibs overrides have been installed or not. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/overview.rst0000664000000000000000000000051515074673150017473 0ustar00rootroot======== Overview ======== See :doc:`/bugs_repo` for information on where to find the bug tracker and the source code. Continuous Testing ------------------ The test suite gets regularly run on all supported platforms. You can find the build pipelines in the `source code repository `_. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/packagingguide.rst0000664000000000000000000000226315074673150020571 0ustar00rootrootPackaging Guide =============== PyGObject uses Meson, here are some notes on how to package PyGObject. Source packages can be found at https://download.gnome.org/sources/pygobject Existing Packages: * https://archlinux.org/packages/extra/x86_64/python-gobject * https://tracker.debian.org/pkg/pygobject * https://github.com/MSYS2/MINGW-packages/tree/master/mingw-w64-pygobject Building:: meson setup --prefix /usr --buildtype=plain _build -Dc_args=... -Dc_link_args=... meson compile -C _build meson test -C _build DESTDIR=/path/to/staging/root meson install -C _build Runtime dependencies: * glib * libgirepository-2.0 (shipped with GLib ≥ 2.80) * libffi * Python 3 The overrides directory contains various files which includes various Python imports mentioning gtk, gdk etc. They are only used when the corresponding library is present, they are not direct dependencies. Build dependencies: * The runtime dependencies * cairo (optional) * pycairo (optional) * pkg-config * setuptools (optional) Test Suite dependencies: * The runtime dependencies * GTK 4 (optional) * pango (optional) * pycairo (optional) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/profiling.rst0000664000000000000000000000263315074673150017621 0ustar00rootroot=================== Profiling PyGObject =================== Setup ===== General vpath build setup with jhbuild shell (x86_64): .. code-block:: bash mkdir _build cd _build export PYTHON=`which python3.3` jhbuild shell ../configure --prefix=$JHBUILD_PREFIX --libdir=$JHBUILD_LIBDIR --with-python=$PYTHON make Devise a simple script to profile (myproftest.py): .. code-block:: python from gi.repository import Gtk model = Gtk.ListStore(str, str, str, int, int, int) columns = [0, 1, 2, 3, 4, 5] row = ['a'*16, 'b'*16, 'c'*16, 1, 2, 3] for i in range(100000): model.insert_with_valuesv(-1, columns, row) Python Profile ============== Use cProfile and kcachegrind (via pyprof2calltree): .. code-block:: bash PROFTEST=myproftest $PYTHON -m cProfile -o $PROFTEST.pyprof $PROFTEST.py pyprof2calltree -i $PROFTEST.pyprof -k C Extension (callgrind) ======================= .. code-block:: bash PROFTEST=myproftest valgrind --tool=callgrind --callgrind-out-file=$PROFTEST.callgrind $PYTHON $PROFTEST.py kcachegrind $PROFTEST.callgrind C Extension (gperftools) ======================== Google PerfTools https://code.google.com/p/gperftools .. code-block:: bash PROFTEST=myproftest $PYTHON -m yep -o $PROFTEST.py.prof $PROFTEST.py google-pprof --callgrind $PYTHON $PROFTEST.py.prof > $PROFTEST.callgrind kcachegrind $PROFTEST.callgrind ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/devguide/style_guide.rst0000664000000000000000000000744115074673150020147 0ustar00rootroot================ Style Guidelines ================ Python Code ----------- * Generally follow Python's :pep:`8` style guidelines. We run Ruff to format our code which should help ensure consistent style. Make sure to run the following prior to committing changes: .. code-block:: python pre-commit install You can also check all files prior to a commit by running: .. code-block:: python pre-commit run --all-files * Break up logical blocks of related code with a newline. Specifically add a blank newline after conditional or looping blocks. * Don't comment what is obvious. Instead prefer meaningful names of functions and variables: .. code:: python # Get the functions signal annotations <-- this comment is unnecessary return_type, arg_types = get_signal_annotations(func) * Use comments to explain non-obvious blocks and conditionals, magic, workarounds (with bug references), or generally complex pieces of code. Good examples: .. code:: python # If a property was defined with a decorator, it may already have # a name; if it was defined with an assignment (prop = Property(...)) # we set the property's name to the member name if not prop.name: prop.name = name .. code:: python # Python causes MRO's to be calculated starting with the lowest # base class and working towards the descendant, storing the result # in __mro__ at each point. Therefore at this point we know that # we already have our base class MRO's available to us, there is # no need for us to (re)calculate them. if hasattr(base, '__mro__'): bases_of_subclasses += [list(base.__mro__)] Python Doc Strings ------------------ * Doc strings should generally follow :pep:`257` unless noted here. * Use `reStructuredText (reST) `__ annotations. * Use three double quotes for doc strings (``"""``). * Use a brief description on the same line as the triple quote. * Include function parameter documentation (including types, returns, and raises) between the brief description and the full description. Use a newline with indentation for the parameters descriptions. .. code:: python def spam(amount): """Creates a Spam object with the given amount. :param int amount: The amount of spam. :returns: A new Spam instance with the given amount set. :rtype: Spam :raises ValueError: If amount is not a numeric type. More complete description. """ * For class documentation, use the classes doc string for an explanation of what the class is used for and how it works, including Python examples. Include ``__init__`` argument documentation after the brief description in the classes doc string. The class ``__init__`` should generally be the first method defined in a class putting it as close as possible (location wise) to the class documentation. .. code:: python class Bacon(CookedFood): """Bacon is a breakfast food. :param CookingType cooking_type: Enum for the type of cooking to use. :param float cooking_time: Amount of time used to cook the Bacon in minutes. Use Bacon in combination with other breakfast foods for a complete breakfast. For example, combine Bacon with other items in a list to make a breakfast: .. code-block:: python breakfast = [Bacon(), Spam(), Spam(), Eggs()] """ def __init__(self, cooking_type=CookingType.BAKE, cooking_time=15.0): super(Bacon, self).__init__(cooking_type, cooking_time) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/extra.css0000664000000000000000000000172115074673150015134 0ustar00rootroot.wy-side-nav-search { background-color: initial; } .wy-nav-top { background-color: #171A2F; } .wy-side-nav-search input[type="text"] { border-color: transparent; } .wy-nav-content { margin: initial; } .wy-nav-side { background-color: #171A2F; } .rst-content div[role=navigation], footer { font-size: 0.85em; color: #999; } .rst-content div[role=navigation] hr { margin-top: 6px; } footer hr { margin-bottom: 6px; } .rst-footer-buttons { display: none; } a.icon-home, a.icon-home:hover { display: inline-block; padding: 4px 4px 4px 21px; background: transparent url(pygobject-small.svg) center left no-repeat; background-size: 1.2em; margin-top: 0.2em; margin-bottom: 1em; } .fa-home::before, .icon-home::before { content: ""; } .wy-nav-top a { margin: -2em; background: transparent url(pygobject-small.svg) center left no-repeat; background-size: 1.2em; padding: 4px 4px 4px 24px; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/getting_started.rst0000664000000000000000000001507215074673150017224 0ustar00rootroot.. include:: icons.rst .. _gettingstarted: =============== Getting Started =============== To get things started we will try to run a very simple `GTK `_ based GUI application using the :doc:`PyGObject ` provided Python bindings. First create a small Python script called ``hello.py`` with the following content and save it somewhere: .. code:: python import sys import gi gi.require_version("Gtk", "4.0") from gi.repository import GLib, Gtk class MyApplication(Gtk.Application): def __init__(self): super().__init__(application_id="com.example.MyGtkApplication") GLib.set_application_name('My Gtk Application') def do_activate(self): window = Gtk.ApplicationWindow(application=self, title="Hello World") window.present() app = MyApplication() exit_status = app.run(sys.argv) sys.exit(exit_status) Before we can run the example application we need to install PyGObject, GTK and their dependencies. Follow the instructions for your platform below. For full IDE support (incl. autocomplete) you will also need typing stubs available here `PyGObject-stubs `_. ======================================================= ==================================================== ========================================================== |ubuntu-logo| :ref:`Ubuntu ` |fedora-logo| :ref:`Fedora ` |arch-logo| :ref:`Arch Linux ` |windows-logo| :ref:`Windows ` |macosx-logo| :ref:`macOS ` |opensuse-logo| :ref:`openSUSE ` ======================================================= ==================================================== ========================================================== After running the example application have a look at the :doc:`/tutorials/index` for an overview of how to create GTK apps and the `GNOME Python API docs `__ for API documentation for all supported libraries. .. _windows-getting-started: |windows-logo| Windows ---------------------- #) Go to https://www.msys2.org/ and download the x86_64 installer #) Follow the instructions on the page for setting up the basic environment #) Run ``C:\msys64\ucrt64.exe`` - a terminal window should pop up #) Execute ``pacman -Suy`` #) Execute ``pacman -S mingw-w64-ucrt-x86_64-gtk4 mingw-w64-ucrt-x86_64-python3 mingw-w64-ucrt-x86_64-python3-gobject`` #) To test that GTK is working you can run ``gtk4-demo`` #) Copy the ``hello.py`` script you created to ``C:\msys64\home\`` #) In the mingw32 terminal execute ``python3 hello.py`` - a window should appear. .. figure:: images/start_windows.png :scale: 60% .. _ubuntu-getting-started: |ubuntu-logo| Ubuntu / |debian-logo| Debian ------------------------------------------- Installing the system provided PyGObject: #) Open a terminal #) Execute ``sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-4.0`` #) Change the directory to where your ``hello.py`` script can be found (e.g. ``cd Desktop``) #) Run ``python3 hello.py`` Installing from PyPI with pip: #) Open a terminal and enter your virtual environment #) Execute ``sudo apt install libgirepository-2.0-dev gcc libcairo2-dev pkg-config python3-dev gir1.2-gtk-4.0`` to install the build dependencies and GTK #) Execute ``pip3 install pycairo`` to build and install Pycairo #) Execute ``pip3 install PyGObject`` to build and install PyGObject #) Change the working directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` .. figure:: images/start_linux.png :scale: 60% .. _fedora-getting-started: |fedora-logo| Fedora -------------------- Installing the system provided PyGObject: #) Open a terminal #) Execute ``sudo dnf install python3-gobject gtk4`` #) Change the working directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` Installing from PyPI with pip: #) Open a terminal and enter your virtual environment #) Execute ``sudo dnf install gcc gobject-introspection-devel cairo-gobject-devel pkg-config python3-devel gtk4`` to install the build dependencies and GTK #) Execute ``pip3 install pycairo`` to build and install Pycairo #) Execute ``pip3 install PyGObject`` to build and install PyGObject #) Change the working directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` .. _arch-getting-started: |arch-logo| Arch Linux ---------------------- Installing the system provided PyGObject: #) Open a terminal #) Execute ``sudo pacman -S python-gobject gtk4`` #) Change the working directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` Installing from PyPI with pip: #) Open a terminal and enter your virtual environment #) Execute ``sudo pacman -S python cairo pkgconf gobject-introspection gtk4`` to install the build dependencies and GTK #) Execute ``pip3 install pycairo`` to build and install Pycairo #) Execute ``pip3 install PyGObject`` to build and install PyGObject #) Change the working directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` .. _opensuse-getting-started: |opensuse-logo| openSUSE ------------------------ Installing the system provided PyGObject: #) Open a terminal #) Execute ``sudo zypper install python3-gobject python3-gobject-Gdk typelib-1_0-Gtk-4_0 libgtk-4-1`` #) Change the directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` Installing from PyPI with pip: #) Open a terminal and enter your virtual environment #) Execute ``sudo zypper install cairo-devel pkg-config python3-devel gcc gobject-introspection-devel`` to install the build dependencies and GTK #) Execute ``pip3 install pycairo`` to build and install Pycairo #) Execute ``pip3 install PyGObject`` to build and install PyGObject #) Change the working directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` .. _macosx-getting-started: |macosx-logo| macOS ------------------- #) Go to https://brew.sh/ and install homebrew #) Open a terminal #) Execute ``brew install pygobject3 gtk4`` #) Change the working directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` .. figure:: images/start_macos.png :scale: 70% ---- For more details on how to use a virtualenv with PyGObject, see the ":ref:`devenv`" page. .. toctree:: :hidden: :maxdepth: 1 changelog bugs_repo ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/api/api.rst0000664000000000000000000000373315074673150016455 0ustar00rootroot.. _guide-api: ================ GI Documentation ================ This is the API provided by the toplevel "gi" package. .. function:: gi.require_version(namespace, version) :param str namespace: The namespace :param str version: The version of the namespace which should be loaded :raises: ..py:exception:: ValueError Ensures the namespace gets loaded with the given version. If the namespace was already loaded with a different version or a different version was required previously raises ValueError. :: import gi gi.require_version('Gtk', '3.0') .. function:: gi.require_foreign(namespace, symbol=None) :param str namespace: Introspection namespace of the foreign module (e.g. "cairo") :param symbol: Optional symbol typename to ensure a converter exists. :type symbol: :obj:`str` or :obj:`None` :raises: ..py:exception:: ImportError Ensure the given foreign marshaling module is available and loaded. Example: .. code-block:: python import gi import cairo gi.require_foreign('cairo') gi.require_foreign('cairo', 'Surface') .. function:: gi.check_version(version) :param tuple version: A version tuple :raises: ..py:exception:: ValueError Compares the passed in version tuple with the gi version and does nothing if gi version is the same or newer. Otherwise raises ValueError. .. function:: gi.get_required_version(namespace) :returns: The version successfully required previously by :func:`gi.require_version` or :obj:`None` :rtype: str or :obj:`None` .. data:: gi.version_info :annotation: = (3, 18, 1) The version of PyGObject .. class:: gi.PyGIDeprecationWarning The warning class used for deprecations in PyGObject and the included Python overrides. It inherits from DeprecationWarning and is hidden by default. .. class:: gi.PyGIWarning Like :class:`gi.PyGIDeprecationWarning` but visible by default. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/api/basic_types.rst0000664000000000000000000000161215074673150020203 0ustar00rootroot=========== Basic Types =========== PyGObject will automatically convert between C types and Python types. In cases where it's appropriate it will use default Python types like :obj:`int`, :obj:`list`, and :obj:`dict`. Number Types ------------ All glib integer types get mapped to :obj:`int` and :obj:`float`. Since the glib integer types are always range limited, conversions from Python int/long can fail with :class:`OverflowError`: .. code:: pycon >>> GLib.random_int_range(0, 2**31-1) 1684142898 >>> GLib.random_int_range(0, 2**31) Traceback (most recent call last): File "", line 1, in OverflowError: 2147483648 not in range -2147483648 to 2147483647 >>> Text Types ---------- Text types are mapped to :obj:`str`. Other Types ----------- * GList <-> :obj:`list` * GSList <-> :obj:`list` * GHashTable <-> :obj:`dict` * arrays <-> :obj:`list` ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/api/error_handling.rst0000664000000000000000000000344615074673150020702 0ustar00rootroot.. currentmodule:: gi.repository ============== Error Handling ============== GLib has its own method of handling errors using :obj:`GLib.Error`. These are raised as Python exceptions, but with a few small differences. It's common in Python for exception subclasses to be used (e.g., :obj:`ValueError` versus :obj:`IOError`) to distinguish different types of errors. Libraries often define their own :obj:`Exception` subclasses, and library users will handle these cases explicitly. In GLib-using libraries, errors are all :obj:`GLib.Error` instances, with no subclassing for different error types. Instead, every :obj:`GLib.Error` instance has attributes that distinguish types of error: * :attr:`GLib.Error.domain` is the error domain, usually a string that you can convert to a ``GLib`` quark with :func:`GLib.quark_from_string` * :attr:`GLib.Error.code` identifies a specific error within the domain * :attr:`GLib.Error.message` is a human-readable description of the error Error domains are defined per-module, and you can get an error domain from ``*_error_quark`` functions on the relevant module. For example, IO errors from ``Gio`` are in the domain returned by :func:`Gio.io_error_quark`, and possible error code values are enumerated in :obj:`Gio.IOErrorEnum`. Once you've caught a :obj:`GLib.Error`, you can call :meth:`GLib.Error.matches` to see whether it matches the specific error you want to handle. Examples -------- Catching a specific error: .. code:: pycon >>> from gi.repository import GLib, Gio >>> f = Gio.File.new_for_path('missing-path') >>> try: ... f.read() ... except GLib.Error as err: ... if err.matches(Gio.io_error_quark(), Gio.IOErrorEnum.NOT_FOUND): ... print('File not found') ... else: ... raise File not found ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/api/flags_enums.rst0000664000000000000000000000370715074673150020210 0ustar00rootroot.. currentmodule:: gi.repository ============= Flags & Enums ============= Flags are subclasses of :class:`GObject.GFlags`, which in turn is a subclass of the standard library :class:`enum.IntFlag`. They represent bit fields where some bits also have names: .. code:: pycon >>> Gtk.DialogFlags.MODAL >>> Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT >>> int(_) 3 >>> Gtk.DialogFlags(3) >>> isinstance(Gtk.DialogFlags.MODAL, Gtk.DialogFlags) True >>> Bitwise operations on them will produce a value of the same type. Enums are subclasses of :class:`GObject.GEnum`, which in turn is a subclass of the standard library :class:`enum.IntEnum`. They represent a list of named constants: .. code:: pycon >>> Gtk.Align.CENTER >>> int(Gtk.Align.CENTER) 3 >>> int(Gtk.Align.END) 2 >>> Gtk.Align(1) >>> isinstance(Gtk.Align.CENTER, Gtk.Align) True Creating New Enums and Flags ---------------------------- New enumerations and flags types can be defined by subclassing :class:`GObject.GEnum` or :class:`GObject.GFlags` in the same way as standard library enumerations. A new GType is registered automatically. .. code:: pycon >>> from gi.repository import GObject >>> class E(GObject.GEnum): ... ONE = 1 ... TWO = 2 ... >>> E.ONE >>> E.ONE.value_name 'ONE' >>> E.ONE.value_nick 'one' >>> E.__gtype__ >>> E.__gtype__.name '__main__+E' The GType name can be set explicitly by providing a ``__gtype_name__`` attribute: .. code:: pycon >>> from gi.repository import GObject >>> class MyEnum(GObject.GEnum): ... __gtype_name__ = "MyEnum" ... ONE = 1 ... >>> MyEnum.__gtype__ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/api/gobject.rst0000664000000000000000000000431115074673150017312 0ustar00rootroot.. currentmodule:: gi.repository ============== GObject.Object ============== Compare to other types, :obj:`GObject.Object` has the best integration between the GObject and Python type system. 1) It is possible to subclass a :obj:`GObject.Object`. Subclassing creates a new :obj:`GObject.GType` which is connected to the new Python type. This means you can use it with API which takes :obj:`GObject.GType`. 2) The Python wrapper instance for a :obj:`GObject.Object` is always the same. For the same C instance you will always get the same Python instance. In addition :obj:`GObject.Object` has support for :any:`signals ` and :any:`properties ` .. toctree:: :titlesonly: :maxdepth: 1 :hidden: signals properties weakrefs Examples -------- Subclassing: .. code:: pycon >>> from gi.repository import GObject >>> class A(GObject.Object): ... pass ... >>> A() <__main__.A object at 0x7f9113fc3280 (__main__+A at 0x559d9861acc0)> >>> A.__gtype__ >>> A.__gtype__.name '__main__+A' >>> In case you want to specify the GType name we have to provide a ``__gtype_name__``: .. code:: pycon >>> from gi.repository import GObject >>> class B(GObject.Object): ... __gtype_name__ = "MyName" ... >>> B.__gtype__ >>> :obj:`GObject.Object` only supports single inheritance, this means you can only subclass one :obj:`GObject.Object`, but multiple Python classes: .. code:: pycon >>> from gi.repository import GObject >>> class MixinA(object): ... pass ... >>> class MixinB(object): ... pass ... >>> class MyClass(GObject.Object, MixinA, MixinB): ... pass ... >>> instance = MyClass() Here we can see how we create a :obj:`Gio.ListStore` for our new subclass and that we get back the same Python instance we put into it: .. code:: pycon >>> from gi.repository import GObject, Gio >>> class A(GObject.Object): ... pass ... >>> store = Gio.ListStore.new(A) >>> instance = A() >>> store.append(instance) >>> store.get_item(0) is instance True >>> ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/api/index.rst0000664000000000000000000000024215074673150017003 0ustar00rootroot============= API Reference ============= .. toctree:: :titlesonly: :maxdepth: 1 api basic_types flags_enums gobject error_handling ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/api/properties.rst0000664000000000000000000000722115074673150020074 0ustar00rootroot.. currentmodule:: gi.repository ========== Properties ========== Properties are part of a class and are defined through a :obj:`GObject.ParamSpec`, which contains the type, name, value range and so on. To find all the registered properties of a class you can use the :meth:`GObject.Object.list_properties` class method. .. code:: pycon >>> Gio.Application.list_properties() [, , , , , , , ] >>> param = Gio.Application.list_properties()[0] >>> param.name 'application-id' >>> param.owner_type >>> param.value_type >>> The :obj:`GObject.Object` contructor takes multiple properties as keyword arguments. Property names usually contain "-" for seperating words. In Python you can either use "-" or "_". In this case variable names don't allow "-", so we use "_". .. code:: pycon >>> app = Gio.Application(application_id="foo.bar") To get and set the property value see :meth:`GObject.Object.get_property` and :meth:`GObject.Object.set_property`. .. code:: pycon >>> app = Gio.Application(application_id="foo.bar") >>> app >>> app.get_property("application_id") 'foo.bar' >>> app.set_property("application_id", "a.b") >>> app.get_property("application-id") 'a.b' >>> Each instance also has a ``props`` attribute which exposes all properties as instance attributes: .. code:: pycon >>> from gi.repository import Gtk >>> button = Gtk.Button(label="foo") >>> button.props.label 'foo' >>> button.props.label = "bar" >>> button.get_label() 'bar' >>> To track changes of properties, :obj:`GObject.Object` has a special ``notify`` signal with the property name as the detail string. Note that in this case you have to give the real property name and replacing "-" with "_" wont work. .. code:: pycon >>> app = Gio.Application(application_id="foo.bar") >>> def my_func(instance, param): ... print("New value %r" % instance.get_property(param.name)) ... >>> app.connect("notify::application-id", my_func) 11L >>> app.set_property("application-id", "something.different") New value 'something.different' >>> You can define your own properties using the :obj:`GObject.Property` decorator, which can be used similarly to the builtin Python :any:`property` decorator: .. function:: GObject.Property(type=None, default=None, nick='', blurb='', \ flags=GObject.ParamFlags.READWRITE, minimum=None, maximum=None) :param GObject.GType type: Either a GType, a type with a GType or a Python type which maps to a default GType :param object default: A default value :param str nick: Property nickname :param str blurb: Short description :param GObject.ParamFlags flags: Property configuration flags :param object minimum: Minimum value, depends on the type :param object maximum: Maximum value, depends on the type .. code:: python class AnotherObject(GObject.Object): value = 0 @GObject.Property def prop_pyobj(self): """Read only property.""" return object() @GObject.Property(type=int) def prop_gint(self): """Read-write integer property.""" return self.value @prop_gint.setter def prop_gint(self, value): self.value = value ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/api/signals.rst0000664000000000000000000000546615074673150017351 0ustar00rootroot.. currentmodule:: gi.repository ======= Signals ======= GObject signals are a system for registering callbacks for specific events. To find all signals of a class you can use the :func:`GObject.signal_list_names` function: .. code:: pycon >>> GObject.signal_list_names(Gio.Application) ('activate', 'startup', 'shutdown', 'open', 'command-line', 'handle-local-options') >>> To connect to a signal, use :meth:`GObject.Object.connect`: .. code:: pycon >>> app = Gio.Application() >>> def on_activate(instance): ... print("Activated:", instance) ... >>> app.connect("activate", on_activate) 17L >>> app.run() ('Activated:', ) 0 >>> It returns number which identifies the connection during its lifetime and which can be used to modify the connection. For example it can be used to temporarily ignore signal emissions using :meth:`GObject.Object.handler_block`: .. code:: pycon >>> app = Gio.Application(application_id="foo.bar") >>> def on_change(*args): ... print(args) ... >>> c = app.connect("notify::application-id", on_change) >>> app.props.application_id = "foo.bar" (, ) >>> with app.handler_block(c): ... app.props.application_id = "no.change" ... >>> app.props.application_id = "change.again" (, ) >>> You can define your own signals using the :obj:`GObject.Signal` decorator: .. function:: GObject.Signal(name='', flags=GObject.SignalFlags.RUN_FIRST, \ return_type=None, arg_types=None, accumulator=None, accu_data=None) :param str name: The signal name :param GObject.SignalFlags flags: Signal flags :param GObject.GType return_type: Return type :param list arg_types: List of :class:`GObject.GType` argument types :param accumulator: Accumulator function :type accumulator: :obj:`GObject.SignalAccumulator` :param object accu_data: User data for the accumulator .. code:: python class MyClass(GObject.Object): @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, return_type=bool, arg_types=(object,), accumulator=GObject.signal_accumulator_true_handled) def test(self, *args): print("Handler", args) @GObject.Signal def noarg_signal(self): print("noarg_signal") instance = MyClass() def test_callback(inst, obj): print "Handled", inst, obj return True instance.connect("test", test_callback) instance.emit("test", object()) instance.emit("noarg_signal") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/api/weakrefs.rst0000664000000000000000000000172215074673150017507 0ustar00rootrootWeak References =============== While Python has a builtin ``weakref`` module it only allows one to create weak references to Python objects, but with PyGObject the Python object "wrapping" a GObject and the GObject itself might not have the same lifetime. The wrapper can get garbage collected and a new wrapper created again at a later point. If you want to get notified when the underlying GObject gets finalized use :meth:`GObject.Object.weak_ref`: .. method:: GObject.Object.weak_ref(callback, *user_data) Registers a callback to be called when the underlying GObject gets finalized. The callback will receive the give `user_data`. To unregister the callback call the ``unref()`` method of the returned GObjectWeakRef object. :param callback: A callback which will be called when the object is finalized :type callback: :func:`callable` :param user_data: User data that will be passed to the callback :returns: GObjectWeakRef ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/asynchronous.rst0000664000000000000000000001302015074673150017654 0ustar00rootroot.. currentmodule:: gi.repository Asynchronous Programming ======================== Asynchronous programming is an essential paradigm for handling tasks like I/O operations, ensuring that your application remains responsive. GLib supports asynchronous operations alongside its synchronous counterparts. These asynchronous functions typically have a ``_async`` suffix and execute tasks in the background, invoking a callback or returning a future-like object upon completion or cancellation. PyGObject offers two primary ways to implement asynchronous programming: 1. **Using Python's `asyncio` module** (available since PyGObject 3.50) 2. **Using callbacks** (the traditional approach) Asynchronous Programming with ``asyncio`` ----------------------------------------- .. attention:: Asyncio support for PyGObject is **experimental**. Feel free to explore its integration, but note that the API is subject to change as potential issues are addressed. Overview of `asyncio` Integration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PyGObject integrates seamlessly with Python's :mod:`asyncio` module by providing: 1. An :mod:`asyncio` event loop implementation, enabling normal operation of Python's asynchronous code. 2. Awaitable objects for Gio's asynchronous functions, allowing ``await`` syntax within Python coroutines. Event Loop Integration ~~~~~~~~~~~~~~~~~~~~~~ To use the :mod:`asyncio` event loop with GLib, set up the GLib-based event loop policy: .. code-block:: python import asyncio from gi.events import GLibEventLoopPolicy # Set up the GLib event loop policy = GLibEventLoopPolicy() asyncio.set_event_loop_policy(policy) Now, fetch the event loop and submit tasks: .. code-block:: python loop = policy.get_event_loop() async def do_some_work(): await asyncio.sleep(2) print("Done working!") task = loop.create_task(do_some_work()) .. note:: Keep a reference to the tasks you create, as :mod:`asyncio` only maintains weak references to them. Gio Asynchronous Function Integration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If the callback parameter of a Gio asynchronous function is omitted, PyGObject automatically returns an awaitable object (similar to :class:`asyncio.Future`). This allows you to use ``await`` and cancel operations from within a coroutine. .. code-block:: python loop = policy.get_event_loop() async def list_files(): f = Gio.file_new_for_path("/") for info in await f.enumerate_children_async( "standard::*", 0, GLib.PRIORITY_DEFAULT ): print(info.get_display_name()) task = loop.create_task(list_files()) Example: Download Window with Async Feedback ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here is a full example illustrating asynchronous programming with :mod:`asyncio` for a download window with async feedback. .. literalinclude:: download_asyncio.py :language: python Key Considerations ~~~~~~~~~~~~~~~~~~ * Async tasks use :obj:`GLib.PRIORITY_DEFAULT`. For background tasks, consider using a lower priority to avoid affecting the responsiveness of your GTK UI. Please see the `PRIORITY_* GLib Constants ` for other settings. * Prefer starting your application using :obj:`Gio.Application` or :obj:`Gtk.Application` instead of :func:`asyncio.run`, which is incompatible. Asynchronous Programming with Callbacks --------------------------------------- The traditional callback approach is a robust alternative for asynchronous programming in PyGObject. Consider this example of downloading a web page and displaying its source in a text field. The operation can also be canceled mid-execution. .. literalinclude:: download_callback.py :language: python Synchronous Comparison ~~~~~~~~~~~~~~~~~~~~~~ Before exploring the asynchronous method, let’s review the simpler blocking approach: .. code-block:: python file = Gio.File.new_for_uri( "https://developer.gnome.org/documentation/tutorials/beginners.html" ) try: status, contents, etag_out = file.load_contents(None) except GLib.GError: print("Error!") else: print(contents) Asynchronous Workflow with Callbacks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For asynchronous tasks, you’ll need: 1. A :class:`Gio.Cancellable` to allow task cancellation. 2. A :class:`Gio.AsyncReadyCallback` function to handle the result upon task completion. The example setup includes: * **Start Button**: The handler calls :meth:`Gio.File.load_contents_async` with a cancellable and a callback function. * **Cancel Button**: The handler calls :meth:`Gio.Cancellable.cancel` to stop the operation. Once the operation completes—whether successfully, due to an error, or because it was canceled—the ``on_ready_callback()`` function is invoked. This callback receives two arguments: the :class:`Gio.File` instance and a :class:`Gio.AsyncResult` instance containing the operation's result. To retrieve the result, call :meth:`Gio.File.load_contents_finish`. This method behaves like :meth:`Gio.File.load_contents`, but since the operation has already completed, it returns immediately without blocking. After handling the result, call :meth:`Gio.Cancellable.reset` to prepare the :class:`Gio.Cancellable` for reuse in future operations. This ensures that the "Load" button can be clicked again to initiate another task. The application enforces that only one operation is active at a time by disabling the "Load" button during an ongoing task using :meth:`Gtk.Widget.set_sensitive`. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/cairo_integration.rst0000664000000000000000000000210315074673150020621 0ustar00rootroot================= Cairo Integration ================= Despite `cairo `__ not being a GObject based library, PyGObject provides special cairo integration through `pycairo `__. Functions returning and taking cairo data types get automatically converted to pycairo objects and vice versa. Some distros ship the PyGObject cairo support in a separate package. If you've followed the instructions on ":ref:`gettingstarted`" you should have everything installed. If your application requires the cairo integration you can use :func:`gi.require_foreign`: .. code:: python try: gi.require_foreign("cairo") except ImportError: print("No pycairo integration :(") Note that PyGObject currently does not support `cairocffi `__, only pycairo. Demo ---- The following example shows a :obj:`Gtk.Window` with a custom drawing in Python using pycairo. .. figure:: images/cairo_integration.png :scale: 75% :align: center .. literalinclude:: code/cairo-demo.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/code/cairo-demo.py0000775000000000000000000000605215074673150017704 0ustar00rootroot#!/usr/bin/env python3 """Based on cairo-demo/X11/cairo-demo.c.""" import cairo import gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk SIZE = 30 class Application(Gtk.Application): def do_activate(self): window = Gtk.ApplicationWindow( application=self, default_width=450, default_height=600 ) drawing_area = Gtk.DrawingArea() drawing_area.set_draw_func(self.draw) window.set_child(drawing_area) window.present() def triangle(self, ctx): ctx.move_to(SIZE, 0) ctx.rel_line_to(SIZE, 2 * SIZE) ctx.rel_line_to(-2 * SIZE, 0) ctx.close_path() def square(self, ctx): ctx.move_to(0, 0) ctx.rel_line_to(2 * SIZE, 0) ctx.rel_line_to(0, 2 * SIZE) ctx.rel_line_to(-2 * SIZE, 0) ctx.close_path() def bowtie(self, ctx): ctx.move_to(0, 0) ctx.rel_line_to(2 * SIZE, 2 * SIZE) ctx.rel_line_to(-2 * SIZE, 0) ctx.rel_line_to(2 * SIZE, -2 * SIZE) ctx.close_path() def inf(self, ctx): ctx.move_to(0, SIZE) ctx.rel_curve_to(0, SIZE, SIZE, SIZE, 2 * SIZE, 0) ctx.rel_curve_to(SIZE, -SIZE, 2 * SIZE, -SIZE, 2 * SIZE, 0) ctx.rel_curve_to(0, SIZE, -SIZE, SIZE, -2 * SIZE, 0) ctx.rel_curve_to(-SIZE, -SIZE, -2 * SIZE, -SIZE, -2 * SIZE, 0) ctx.close_path() def draw_shapes(self, ctx, x, y, fill): ctx.save() ctx.new_path() ctx.translate(x + SIZE, y + SIZE) self.bowtie(ctx) if fill: ctx.fill() else: ctx.stroke() ctx.new_path() ctx.translate(3 * SIZE, 0) self.square(ctx) if fill: ctx.fill() else: ctx.stroke() ctx.new_path() ctx.translate(3 * SIZE, 0) self.triangle(ctx) if fill: ctx.fill() else: ctx.stroke() ctx.new_path() ctx.translate(3 * SIZE, 0) self.inf(ctx) if fill: ctx.fill() else: ctx.stroke() ctx.restore() def fill_shapes(self, ctx, x, y): self.draw_shapes(ctx, x, y, True) def stroke_shapes(self, ctx, x, y): self.draw_shapes(ctx, x, y, False) def draw(self, da, ctx, width, height): ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(SIZE / 4) ctx.set_tolerance(0.1) ctx.set_line_join(cairo.LINE_JOIN_ROUND) ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0) self.stroke_shapes(ctx, 0, 0) ctx.set_dash([], 0) self.stroke_shapes(ctx, 0, 3 * SIZE) ctx.set_line_join(cairo.LINE_JOIN_BEVEL) self.stroke_shapes(ctx, 0, 6 * SIZE) ctx.set_line_join(cairo.LINE_JOIN_MITER) self.stroke_shapes(ctx, 0, 9 * SIZE) self.fill_shapes(ctx, 0, 12 * SIZE) ctx.set_line_join(cairo.LINE_JOIN_BEVEL) self.fill_shapes(ctx, 0, 15 * SIZE) ctx.set_source_rgb(1, 0, 0) self.stroke_shapes(ctx, 0, 15 * SIZE) app = Application() app.run() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/debug_profile.rst0000664000000000000000000000544215074673150017740 0ustar00rootroot===================== Debugging & Profiling ===================== Things can go wrong, these tools may help you find the cause. If you know any more tricks please share them. GObject Instance Count Leak Check --------------------------------- Requires a development (only available in debug mode) version of glib. Jhbuild recommended. :: jhbuild shell GOBJECT_DEBUG=instance-count GTK_DEBUG=interactive ./quodlibet.py * In the GTK Inspector switch to the "Statistics" tab * Sort by "Cumulative" and do the action which you suspect does leak or where you want to make sure it doesn't repeatedly. Like for example opening and closing a window or switching between media files to present. * If something in the "Cumulative" column steadily increases there probably is a leak. cProfile Performance Profiling ------------------------------ * https://docs.python.org/2/library/profile.html * bundled with python :: python -m cProfile -s [sort_order] quodlibet.py > cprof.txt where ``sort_order`` can one of the following: calls, cumulative, file, line, module, name, nfl, pcalls, stdname, time Example output:: 885311 function calls (866204 primitive calls) in 12.110 seconds Ordered by: cumulative time ncalls tottime percall cumtime percall filename:lineno(function) 1 0.002 0.002 12.112 12.112 quodlibet.py:11() 1 0.007 0.007 12.026 12.026 quodlibet.py:25(main) 19392/13067 0.151 0.000 4.342 0.000 __init__.py:639(__get__) 1 0.003 0.003 4.232 4.232 quodlibetwindow.py:121(__init__) 1 0.000 0.000 4.029 4.029 quodlibetwindow.py:549(select_browser) 1 0.002 0.002 4.022 4.022 albums.py:346(__init__) ... ... SnakeViz - cProfile Based Visualization --------------------------------------- * https://jiffyclub.github.io/snakeviz/ * ``pip install snakeviz`` :: python -m cProfile -o prof.out quodlibet.py snakeviz prof.out Sysprof - System-wide Performance Profiler for Linux ---------------------------------------------------- * https://www.sysprof.com/ :: sysprof-cli -c "python quodlibet/quodlibet.py" sysprof capture.syscap GDB --- :: gdb --args python quodlibet/quodlibet.py # type "run" and hit enter Debugging Wayland Issues ------------------------ :: mutter --nested --wayland # start your app, it should show up in the nested mutter :: weston # start your app, it should show up in the nested weston Debugging HiDPI Issue --------------------- :: GDK_SCALE=2 ./quodlibet/quodlibet.py :: MUTTER_DEBUG_NUM_DUMMY_MONITORS=2 MUTTER_DEBUG_DUMMY_MONITOR_SCALES=1,2 mutter --nested --wayland # start your app, it should show up in the nested mutter ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/deploy.rst0000664000000000000000000000503515074673150016424 0ustar00rootroot.. include:: ../icons.rst ====================== Application Deployment ====================== There is currently no nice deployment story, but it's not impossible. This is a list of random notes and examples. |linux-logo| Linux ------------------ On Linux there is no single strategy. Quod Libet uses distutils, MyPaint uses SCons. Gramps uses distutils. |macosx-logo| macOS ------------------- On OSX you can use `gtk-osx `__ which is based on jhbuild and then `gtk-mac-bundler `__ for packaging things up and making libraries relocatable. With macOS bundles you generally have a startup shell script which sets all the various env vars relative to the bundle, similar to jhbuild. |windows-logo| Windows ---------------------- On Windows things are usually build to be relocatable by default, so no env vars are needed. You can build/install through MSYS2, copy the bits you need and you are done. For GUI application you'll also need an exe launcher that links against the python dll. Example Deployments ------------------- * `Quod Libet `__ provides a Windows installer based on MSYS2 and NSIS3. On macOS, jhbuild is used for building, gtk.mac-bundler for packing things up and `dmgbuild `__ for creating a dmg. distutis is used for building/installing the application into the final environment. Most of this is automated and scripts can be found in the git repo. * `MyPaint `__ provides a Windows installer based on MSYS2 and Inno Setup. It uses SCons for building/installing the application. * `Passphraser `__ uses the Hello World GTK template build system (see below). Other options ------------- * `PyInstaller `_ is a program that freezes (packages) Python programs into stand-alone executables, under Windows, Linux, Mac OS X, and more. PyInstaller's packager has built-in support for automatically including PyGObject dependencies with your application without requiring additional configuration. * `Hello World GTK `_ is a template build system for distributing Python-based GTK applications on Windows, macOS, and Linux. First, an application directory is assembled using PyInstaller. Then, a different program is used to package the resulting directory. For Windows, NSIS3 is used. For macOS, the built-in hdiutil is used. For Linux, AppImageKit is used. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/download_asyncio.py0000664000000000000000000000506115074673150020303 0ustar00rootrootimport asyncio import time import gi gi.require_version("Gtk", "4.0") from gi.repository import Gio, GLib, Gtk from gi.events import GLibEventLoopPolicy class DownloadWindow(Gtk.ApplicationWindow): def __init__(self, *args, **kwargs): super().__init__( *args, **kwargs, default_width=500, default_height=400, title="Async I/O Example", ) self.background_task = None self.cancel_button = Gtk.Button(label="Cancel") self.cancel_button.connect("clicked", self.on_cancel_clicked) self.cancel_button.set_sensitive(False) self.start_button = Gtk.Button(label="Load") self.start_button.connect("clicked", self.on_start_clicked) textview = Gtk.TextView(vexpand=True) self.textbuffer = textview.get_buffer() scrolled = Gtk.ScrolledWindow() scrolled.set_child(textview) box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, spacing=6, margin_start=12, margin_end=12, margin_top=12, margin_bottom=12, ) box.append(self.start_button) box.append(self.cancel_button) box.append(scrolled) self.set_child(box) def append_text(self, text): iter_ = self.textbuffer.get_end_iter() self.textbuffer.insert(iter_, f"[{time.time()}] {text}\n") def on_start_clicked(self, button): button.set_sensitive(False) self.cancel_button.set_sensitive(True) self.append_text("Start clicked...") self.background_task = asyncio.create_task(self.download()) def on_cancel_clicked(self, button): self.append_text("Cancel clicked...") self.background_task.cancel() async def download(self): file_ = Gio.File.new_for_uri("https://pygobject.gnome.org/") try: _success, content, _etag = await file_.load_contents_async() except GLib.GError as e: self.append_text(f"Error: {e.message}") else: content_text = content[:100].decode("utf-8") self.append_text(f"Got content: {content_text}...") finally: self.cancel_button.set_sensitive(False) self.start_button.set_sensitive(True) class Application(Gtk.Application): def do_activate(self): window = DownloadWindow(application=self) window.present() def main(): asyncio.set_event_loop_policy(GLibEventLoopPolicy()) app = Application() app.run() if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/download_callback.py0000664000000000000000000000504415074673150020373 0ustar00rootrootimport time import gi gi.require_version("Gtk", "4.0") from gi.repository import Gio, GLib, Gtk class DownloadWindow(Gtk.ApplicationWindow): def __init__(self, *args, **kwargs): super().__init__( *args, **kwargs, default_width=500, default_height=400, title="Async I/O Example", ) self.cancellable = Gio.Cancellable() self.cancel_button = Gtk.Button(label="Cancel") self.cancel_button.connect("clicked", self.on_cancel_clicked) self.cancel_button.set_sensitive(False) self.start_button = Gtk.Button(label="Load") self.start_button.connect("clicked", self.on_start_clicked) textview = Gtk.TextView(vexpand=True) self.textbuffer = textview.get_buffer() scrolled = Gtk.ScrolledWindow() scrolled.set_child(textview) box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, spacing=6, margin_start=12, margin_end=12, margin_top=12, margin_bottom=12, ) box.append(self.start_button) box.append(self.cancel_button) box.append(scrolled) self.set_child(box) def append_text(self, text): iter_ = self.textbuffer.get_end_iter() self.textbuffer.insert(iter_, f"[{time.time()}] {text}\n") def on_start_clicked(self, button): button.set_sensitive(False) self.cancel_button.set_sensitive(True) self.append_text("Start clicked...") file_ = Gio.File.new_for_uri("https://pygobject.gnome.org/") file_.load_contents_async(self.cancellable, self.on_ready_callback, None) def on_cancel_clicked(self, button): self.append_text("Cancel clicked...") self.cancellable.cancel() def on_ready_callback(self, source_object, result, user_data): try: _success, content, _etag = source_object.load_contents_finish(result) except GLib.GError as e: self.append_text(f"Error: {e.message}") else: content_text = content[:100].decode("utf-8") self.append_text(f"Got content: {content_text}...") finally: self.cancellable.reset() self.cancel_button.set_sensitive(False) self.start_button.set_sensitive(True) class Application(Gtk.Application): def do_activate(self): window = DownloadWindow(application=self) window.present() def main(): app = Application() app.run() if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/faq.rst0000664000000000000000000000074315074673150015700 0ustar00rootroot========================== Frequently Asked Questions ========================== How can I use PyGObject with the official CPython builds on Windows? -------------------------------------------------------------------- https://sourceforge.net/projects/pygobjectwin32 provides binaries which should be ABI compatible with the official CPython binaries. I'd recommend using msys2 if at all possible, since there are more people involved and it's easier to fix/patch things yourself. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/flatpak.rst0000664000000000000000000000051115074673150016544 0ustar00rootrootFlatpak ======= `Flatpak `_ is perfect for packaging applications for Linux. Flatpak comes with `great documentation `_ and a specific guide about using it to package Python applications can be found `here `_. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/gtk_template.rst0000664000000000000000000000567715074673150017624 0ustar00rootroot.. _guide-gtk-template: ============ Gtk.Template ============ A GtkWidget subclass can use a `GtkBuilder UI Definition `__ XML document as a template to create child widgets and set its own properties, without creating a GtkBuilder instance. This is implemented for Python by PyGObject with Gtk.Template. The subclass uses a ``@Gtk.Template`` decorator and declares a class variable ``__gtype_name__`` with the value of the XML ``template`` element ``class`` attribute. Child widgets are declared, typically with the same names as the XML ``object`` element ``id`` attributes, at the class level as instances of ``Gtk.Template.Child``. Signal handler methods, typically with the same names as the XML ``signal`` element ``handler`` attributes, use the ``@Gtk.Template.Callback`` decorator. ``Gtk.Template()`` takes a mandatory keyword argument passing the XML document or its location, either ``string``, ``filename`` or ``resource_path``. ``Gtk.Template.Child()`` and ``Gtk.Template.Callback()`` optionally take a ``name`` argument matching the value of the respective XML attribute, in which case the Python attribute can have a different name. Examples -------- .. code-block:: python xml = """\ """ @Gtk.Template(string=xml) class Foo(Gtk.Box): __gtype_name__ = "example1" hello_button = Gtk.Template.Child() @Gtk.Template.Callback() def hello_button_clicked(self, *args): pass Python attribute names that are different to the XML values: .. code-block:: python @Gtk.Template(string=xml) class Foo(Gtk.Box): __gtype_name__ = "example1" my_button = Gtk.Template.Child("hello_button") @Gtk.Template.Callback("hello_button_clicked") def bar(self, *args): pass Subclasses that declare ``__gtype_name__`` can be used as objects in the XML: .. code-block:: python xml = """\ """ class HelloButton(Gtk.Button): __gtype_name__ = "ExampleButton" @Gtk.Template(string=xml) class Foo(Gtk.Box): __gtype_name__ = "example3" hello_button = Gtk.Template.Child() @Gtk.Template.Callback() def hello_button_clicked(self, *args): pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/images/cairo_integration.png0000664000000000000000000005754215074673150022063 0ustar00rootroot‰PNG  IHDRÂKtO–ÈsBIT|dˆtEXtSoftwaregnome-screenshotï¿>^ôIDATxÚí˜E¾ö’%Çˬ"0Ü.ÈÓz?PÝEX¢ WDÆ»Œ. ’Àˆ‚ Iv]{%HÎ.(0 Ä!3CŒèêš®®±¾ó¶s¸ÌépÎéîªêwŸç÷ìàœî®úWŸþÍ¿ºB(ôËÿŠ…©wà 7þøã¨RŠöÿò«¯Ä__CÜ}ogÑ"­èб“xåÕ׌ÿnV¶Ï?ÿ\Œ;N¤Ýþ›¨ޝÂç@™w_WqcÚÍÆ¹_ _ë«Bç¾ôX”¡c—®âÿµï RnjeüÿÚ¿¯»ðùXË{éuPîQ㲌zì?p@\—z£çH ååŸÃùy/R„^pO§ûŒëýî¾.† Ïœ9#îíúû¸ïCŠ(Ë+¯½n|úãâèÑcâtøKñD~?ñ…ÅŽ»ÄgŸ}&þgî<ã³#ÆŒµáÓC†ŠÎŸ¿ðßÿò×Wÿ>:k¼øè£Œkàß‹Yù¦dO+ò¸Â×|íÍ9Æ¿Ÿzf°qÍI“§ÿ~cÎß.+×ËyE|°uëÿýûÏÛ¶ï0~¾óî߯]ÞÈyG†cTø¸ì3ß?úxÆ…ràß/M›nü{¤x?´'ÃkûðCq×=¿½ CüAˆŸÛ¦ß-9B’àÑ®Ã=Æ—`ßþý–ŸýòË/ÏþWûtKž8qâ¢cñ—&þ;¾„ø÷ÑcÇlý 9u\ák"kÿ‘]áßþ}O§Î—•ëܹsâŸÿüü¿Ϟ=gdŽøÙZ¼åœŸ/|\ûßv4þ½1'ç—Þ•.¾øâ‹ Cμ)B?dÐ#’—ŸÏw„$˜4¿ñ&ã‹€ŒïÒß}°m›xð‘GÅÍ¿ù/£k4ò¥ÁÏV"¼ô\©­Ûÿ]„øwDFèvŒÖu„ÿvC«´"+|”›ZÙÕt}ËV¶Ëyé¿í”×ìawéq8_ä3]zôü% |~’ñÿ·µ½ó¢n\BºÍ©S§l0rmü¡vüø Š0#¼ôwè*ÁïV¯]k<Ø?ùäÇB‰€/šU†U”íd„‘:|xü¸í‡Õ¿í”7–Œ,Zºô¢z9Š÷"EèY9Nœ-êKkW„x 3B7aúïî5F¤ZÂD×"ç´¾í7¦Ž…‹—]ލxä±þbÝúwc¡òš‰0Ê )¢…?÷çy£¬—þŽè;mA–r@x…³?ü9JB<™ã¸ùý÷ ²Ø?1n„ê !Á!FÔ"ÓÆ £ ›61n„"$„G„èrÅïÛÜ~‡xkþ|ÆŒP„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„È/BL’%„B‚JB!A%tøpž „B‚Jhò䉂B *¡>:'!„ BB¡ !„ŠB¡ !„ŠB¡ !„ŠB¡ !„ŠB¡ !„ŠB¡ !„ŠB¡ !„ŠB¡ !„ŠB¡ !„ŠB¡ !„ŠB¡ !„ŠB¡ !„ŠB ¦7oΣGýû÷¿ˆÉ“_4=nüøñ—£Ò±£F4êîwœ ó·¿Í1=‡ŠÇzgBE般¬,Q¢D  ….ãŽ;î0=öÆ[yœÌÇ^qÅ}uG üŒsaüqó›CÑc½Š3!„"tDNNŽéÃY7:´Ècį8A„^ÄY6Þ~{A êKˆ’"D—•ÕƒYF“`ÄÂÏ8A„nÇY&¶jÕʨïÝwß͇!ª‹Q]„x/gUO/к‹pðàgb¾Ž.Œ€®ø÷Þ{—6BTíµ’¡*"\±b¹¨X±bÔc¼î²£õúž:uR¤¥¥E­3³BB$,3r¤½n»±cÇ(Ý5j&Ô”o˜"ÔÈ.Z‘¾ûîz>Ü‘yú„Õû³ªU«ŠwÞyç²ã²³³Å!ƒ‹döì—M¯éDZ¡“®_·ˆVv°páÛÊD¢ûóÒÉÌ QlB}4F“ ªÎ ý`‚sr6‰×^{Uœ;w–Ya8zôˆ§’%KŠJ•*‰:uꈛnºItéÒE 6LÌ›7×ø cõ ùùyFLıB̬æô>œ/NŸ>E:‘¡n,,C  áŠ"Œ·+ôºë®¯¿þš!ÄhY!ÞAwîÜIlß¾-°÷Þ£ÆóÊ,Z´0Ðß«3gN Xàž+^¼x‘1š6-ÛôO>ù¤¨\¹²èÙ³‡X¹rEh%C%8bĈð_D£Œ(BÏ»A#B¼çž{.`ç.^¼ØI{ÿý÷[~öÊ+¯Œzß”-[Vœßºuk±lÙRа(00F5 F^¦Lédˆaõ±.O¦"Ë—/‹ù]¤êc"ó  ]wÝ»wÅŠ»ð½Ü»wé1ÈT¢Åõ–[n1=vÍšÕ†t—¥Õ”·1cF›f”åË—¿ì´QÝ6£cà•W^Ç—F‚d“aPçÕéÞóY бzàë2æzõê9¾×ñ½×?ýéO¦Ç¢«ŸKJªe<“T|Ÿˆ2Ïû–égöìÙµ[<ú袻zõ*S‰&''‹ Þ£J/¶ýtmL2¤ƒ3M"è“çÑZTÖ0&//zÖaö€G·³ÙûÇK³É*UªˆÌÌLqèÐAéc†2¢¬(séÒ¥Åîݹ¦Ÿ¿þúëcüÐC™ŠÏs´Eƒýœ†`5íCR„ÁɃ B«P¡‚éwò™gžŽi°Ì‘#‡£÷׿¾õ8ÈcÐ-([¼0zÙ+ÊX¸Ìýúõ3=nÀ€Që{à 7D=®zõê¦1ž0a»Fã‘ 2Ä_ÞfAFÀ‚!IøK½OŸ>EÞÿN³AßeõîÝËòûˆ‡ññãF=ljÇ8¯[÷wñ “Ä AƒÄ}÷Ýgz]<üÍ®‰LgÏž‘*V˜úРAƒ"Ë[®\¹pæ|Ȳ‹±lÔ¨‘£I“ž7bf–£Û8ZŒð>—ƒe A?døâ‹/˜ÊP–y‚¡^ìÚµó2!b´¨c‘ÙàÁU­Z5íºQ1…óÚÌ–mDÖœÈîJ¼Ó2{a oÉ'¼CF¨Y¹1ÍÁìÌXx«]p\‡.ºVjjª­é-aHã­þ⃘¼Ü„5š eš,OêÉÎ; !â¡f%µˆñÈ©¿ûÝï¤.ûsÏ=gºåvIqr¾¾}¶|faã\º’ÍÖ1íÚµ+E˜( ZÉðÁ´¼©T›"Ám˜ÔÚ†)Z6ÈÁ-ÿǵ×6‰Ÿìlù»1¶«û\Zv¼Ós:jªþã?þÃô™…ka€Žj™~aÐæ¡£ Æy¦4nB3ª8OÓ 8ÝA'0-¡T©RQc¤Ê>ŒÈ̱Æf¤ÜÍš5‹yâÿÖ­)ÖÈ:žªô ‰Ö®hs«))a ]œÑ$M†ªN–§Õï·~ýë_34K(F‹OÅŠ•«ÏèÑ£Œ×-xh糞ŸÂKËaÍUœ[µx  ·)’š&Mšˆ;î¸ÃÓ¬V›w„f2´À¥2TyÅŠP-0Ý{õë×÷<\¹r…xöÙ!Òwõ›e *¶¹ù¢èéúÏÿüO1s挨ŸÁ;`Äû#Zm²++X‘#Hñ‡Ÿ™¬V£F‹’¡Ý‡D†ª/›Fª 7¢›ÙàªU+ÕP"•y•$Lˆv?·o—–÷DÙ7£J'Nœõ³˜zÁ‘í¡© #~<`TœDLSˆ:Ž÷'n P•.Ø-[6#/²×ÿ(~ÿûßõ:ôYíÚYQQóê°å¿¡cFú1Þxc‹@È"$E‰pPŽü™søïÿ~‚q¢ãï*½T†è‡Ÿ2e EH´G§iøÞb;*æ÷â]±Õ€?€×72-”M*:x&"C|™"ëÜq;%ŠŸS5äÌ Çk¼/‹¼3Ó±}‘ bG ;"Ī2Aß2‰"LÐtŠF‰ÿ÷×bºE¨–Ÿzê)1þ<)³Bw±7kß~ýÕâÆê8v$ذaC-V ¢=`úôi¶n*]&ÐS„ꈰðI-[¶ôEˆEe…Œ‘žÞ^¬[÷wéÚ7+++jûÞ~ûíZÜÃóæÍ½hN`4±M—lüéO-Z¤„=üðÃÆQX s"½ÜÑ^;bµQ×¼ãŽ;L¯%Ë FV {Ûl‘k°víÚ„fŸ:tˆz-Lÿx≠)LÉØXv_û1b•¤utáµ×^•R€…Á÷²ŽgìIíØM›6Šƒïö0wïs± ÇßÿþNÔc̶‚·Ür‹S ¯IZx_hvŽ>}z‹Aƒï3ÌõC ÍÞ þêW¿²ü£E†ù´R‰ÂÁ_ “&=/åô J"4ƒkŠzÇŠËE… I ŒÖ>·ÝvkÔã0 ð2iEîSÙ笢›;Ú»U0eÊÓ˜Õ?ÚqØ`×ì8´!Ú’","ë’U†vÆ$b~QK„:dƒª±xñâ‹æêaë"³A«V­ŒÚ> 40½²–hÇ¢Û[•=L1x{_V©Rå¢: v˜¦í8솋‘1V¯^=ª—,YÂw„fïád•¡#GŽäN÷!æ³]:±Y¥I骂‰ôØ‹qƲcfŸÅüºh÷J¹råLŨ٢F¨â]êÑ£G”‹ÊŒ²×ªUËV÷$–ß‹E„Ѿ£õë'Û0q°Œ‘™ªÉ0"A?çr&ÿ¶aÂ;¼?¹Tˆ:eƒˆ¹q2uóæçç‰ÿh9‡Ðì&€l)Ú±Ø/’Ù4kÖLLœ8ѵ©^‚: .V™Yûöw™.îm5ž#Ò%‹gzÏž=Œ6ãô‰(âˆ&CþšŽV¯eÈ õr,ù…‡ „¨K6`¤ûWE¹÷èÑÝôYóÎ;ï˜TØçÏ÷‹èþ5‹ÕÂøCs)µ•V"Dwú¦U[½Å©Ð½¬E(—ßz봠ʃ°µÙ÷ôÕWÿÊû¶0¥Â*a±ÊðdßDÙ÷®Q3ª Áµkרšà‹ÑS!Q ì™g6ïLµ¬Ý{Øe#ÒM‡.=üŒwŒ­Zµsç¾Åv2HpÞ¼¹bذaÆ~šˆb†Ø!†ˆ%–¼S¹Ž¾‹[‰ ÏýÒ/YñâÅLËêØhïü<eµ"¼tééDhö>Äú.RÖcÝĬLfk+¢«Hæc­Ö 唢¾‹ÐlX2v-VíX?%èT„Vƒâx ã±®~‘bì6ÊÊÊ’úXN !!E—½– Eè7oηß~»X¶l©Ö"´“"|˜Š"”B‚¡w",<¯êöÛoÓZ„VY!bÁ‡)¡)‹ŽÅƒÁ 5ñU7™YëÕÚj‚±N",œb Ä¥"EH(BŠÐѱnƒyN…GúU„ˆ›s¾.³î"D}1PéÒcÝŽ3!!ExPEÒA!êŽxgÝEXÔ±^Å™íEˆm_¢-‘õ “´;ÖËÁVsÍ–'³Z·QÖcÑMçåàHœÍÊd¶&+«x¬×q&DkB!!!„BB!!!„BB!!!„BB!!!„BB!!!„BB!!!„BB!!!„BB!!!„BB!!!„BB!!!„BB!!!„"ƒ7oΣGýû÷£F4êÎ8ëg¿ˆ´oPêKˆ6"ÌÊÊ%J”¡P( îˆã¬GœýâÒöÕ½¾„h#œœœ@?œ ?´ ÆYí8ûņ ïÙ¾øoøj„H,Btáýá±`œÕ޳_Ü}÷ÝQë‹ßñ¡FEøôàÁÏ0Æ<þøãZ}Yß{ï]qÅWD­/~‡ÏðÁF»FÝeGê+B³lY!!Š –9’YaJJŠ«1¦õ¡U6Ȭ…¦O :ÔÖC¬jÕªbÈÁJ€²Ú©êîv|ÍDX¬X1ebj—J•*B„v²Af…„(4¡Þ® ½‡nu1¡n]…A©¯ÝlYáÅœ>}J,[¶T 6LtìØÑè©Q£Æ…?žJ•*eü\·n]ѺukÑ¥Kã³óæÍùùyDˆb‚Ø F­Zµ2b†Ø!†ˆ%~FlcÄŸEìÑ¡æ2”±¡~õu’ 2+<'V¬X.zöì!*W®s·zñâÅE³fÍŒEV®\¸¢Î¨ûu×]gÄ"Ö8V©REôîÝËhŠPCÊZvŠP¯ú:̓œ.Y²D¤¥¥¹ò¾999YdfÔrnjá¨#êêF Û´icd‰¡&2”¹Ì¡^õ% ZVˆ®;d€xîÅ ,dŠÏ??Qœ:uRùØ¡¨ êäEìðÚêðá|ŠPeÊ^VŠPŸúZeƒ™(ƒnܸAÔ¯Ÿì˨䤤$1bÄqìØQåâ†2£ìIIµ|‰Ú mG*(CÊHêS_;’³#K»BË—/ïû4Œê©§Ä¡C¥ʈ²âÝßq«P¡‚Xºt E¨’hTÉZ)B=êëDpAÌ 1ø¢bÅŠRÍ[ÅÈÉáÇK9ReBÙ̦ùÚP†4ÒíG(£pT꺥õ¨¯¹-+ÌÍÝ%jÖ¬éèa‹{!;;[¼ÿþqàÀ~ã<'Ož{öìëׯ3Þ“ 4H4jÔHT¯^=®‡{ƒ Äüùó¤‰Ê‚2ÅS'Lhذ¡xúéAbÒ¤ç˜!vˆ!®±oß^#¶S§N=ö˜£?RЖhSŠPbñ¨6˜‡"T¿¾±ˆ-(Yá™3§E‹©¶¾“˜ï–“³Éñ5Î;+V¯^eÜ?ñ¼LOO;vl÷-V¸6Êû{¼úbÀ€F,“XF¡¦¦Úk«–-o4Ú–"”P@*Žh¥Õ¯o,R JV8vìËïc¹r匇w¢®¹jÕJÑ·ïÃ1ɤL™2F—äÙ³g<‹®… í¸v,e~䑾 Ÿ qܸ±¡l"RuŽ#E¨v}ãšîYáÞ½{,¨Mš4ÇèÚTƒ‰'ŠzõêÅ4‡nçήÇ×À*9Nˇ:¹9%£T7nlùŽ]¬¡$BRy¢?E¨v}ã‘™îY!V:±šÎàÅÜ>táMŸ>Í®ÓÁ4³fÍt­\8·ÓÁ0¨ÃŒÓ=é–DÛXM×ðë;Rá क़T_ú"T·¾‰™®Ya^^žåT‰È ¯À{3tç]uÕUŽäÓ¹s§„N(ǹ:uº×QPf”=–wñ°ÿ>ËMhkŠÐGAé°þ)E¨n}!1]³Â¬¬,ÓïäK/½ä[ÙÐ;pན«]»¶X»vMÜׯ9p.'ï,±Œš[ÝÇv@[™•q„ ¡_¢ÒeG ŠPÍú&R`:f…f£ÝÞãÓ.[·~ îºëNGRš9sFÌ×ñeË–µ}=”mÛ¶­RĪyóæQˉ¶¦}–NÛBQ„jÖ7‘òÒ-+ܽ;×tÑÑ£GIUÞñãÇÛžçˆzedd8UŠÏ>ñD†íµUQ ò‘)FÕj´9E衸t’ E¨f}Ý—NY!&i›}7e\üïÂÚ¶mk;[k×®8rä°åyñ|ÖÉyQÙâƒ63+7Úœ"ôH†ºI"T³¾nHK§¬°k×®Qëqçí¤.;2±+¯¼ÒÖs«Ú|ðÁûQÏ…ßá3vÎ…kÊ–^Jzzû¨åïÖ­Eè… u” E¨^}Ý–.Y¡Ùü3,÷%{ù±ÂJ:ul=oªU«Vä ü7üÎÎ9®¹æ%öMļÅhu¸öÚ&¡Û2ÔU‚¡zõuSV:d…X,ºT©RQë€**ܧ'NÝ»w·½6ê¢E /‹Ÿ±Sƒc{ôèn\K…˜ ÃV´¹—‹—‡tx:›Î¤Õª¯¢R=+ܼ9ÇtP…j÷ë˜1£E‰%,Ÿ? :gΛvF†âœX~Nµx˜ øÙ²e3Eè– u– E¨V}½”êYáÛo/0ÝAÅ{vîÜ·DåÊ•ö¼Â¹dÚí f;} í)BŸd¨²)Buê률TÎ §MËŽZööíïRö¾Å–Eñn°5Î¥jÌæ]bé7ŠÐª.AŠPúz)'•³B³en»íV¥ï],V·nݘŸWÉÉɶ¦\È Ú0ZýÐö¡Ç2ÔA‚¡õõCLªf…Ï>;$j¹±¬ê÷/6¶u²MáUbdœ?é”~ýú™<“Ÿ¥½”¡.¤Õ¨¯RR5+4kß.]ºhqcç,Äm÷yuß}}ÝÄ6‘  £ÕmOR„¡†õõSH*f…A¸Ÿ!5'»G೺ˆmH²k”Ž€Õ×O©˜¡kÔÉ’i…WÔÁ±ì¥9X†"Tª¾2ˆHµ¬Ðl°ÌÍ7߬ô½‹}÷š6½6æçŽÍÏÏS:mÚ´á`NŸ ƒT_$¤ZV¨ëô Lçô óéÓ§O£9¡ž"Ô©¾2 H¥¬pÁ‚ù¦«©pBý/êçÍ›«d,Š/Î õ\b" J}e’JY¡Ùk€j÷+öN´»ÄÚo¼n€ |u]b ëªr‰5%Ï1ë«“xTÉ ­ÝÎÉÙ¤Ä}Š9vÝÆÛñ,º­Êü Þã¢Û~IPwR„òÕWF騔bK–áŠ'«­Zµªím˜Ö¬Y}Ù9V¯^eûÈ”U؆ mÇm˜|” Î2¤媯ÌÂQ%+4›tݤI©ïO§óš |ÁïtÚ˜·iӦܘ×o ê*CŠP®úÊ,U²Â©S§F-#²$»÷ïßçh~`Û¶mm­ŠÏ8=/Ê"cWq•*U¢–;;;›"ôZ\:É"”§¾*ˆF…¬p÷î\Ó}ëž{î9©îÉY³fŠš5kÚz¦ ^âìÙ3¶ÏÏⳘeA™dŠÑ¸qcMc²gÏnŠÐaé"CŠPžúª U²ÂÔÔÔ¨eÄ2”qÛ¶­ŽÐÆhÐxÞqΜ9ÃÖ¦½…êÞ¾}›±ªS§NÔr¢­½.OˆÔK†¡õUi0Š Â6[aÌž=Û·²?þ¡ÈÌhkšC„Úµk‹µk×Ä}mœçr"_”eö+^³g¿lZÆ &P„~ JuR„rÔW¥Ië*HË‘•/_Þô;yàÀ~OËtîÜY1eÊqõÕW;šÝ#°a¢Ês9Y´ Ì(;êàeÌÐFfåªT©’ÑÖ¡bRY†¡ÿõUqqkÄÝ¿Ëï¤g°ó–~kܸ±#ùà!ïæ»:t•âNÊ„:`)3/v³@ÛX•gÀ€¾Ü[!JP/R„þ×WÅíŽT÷Þ½{LW"‰ÈÆ­n?ìö€9±ì*Å¥wíÚézŒvîÜ!Z·ní¸|¨¦[¸µ£ÚÄjQ´Ý¾}{)BÙD¤¢ )Bë«ê¸ªÜl´aa°jI¢®¹jÕJÑ·ïÃ1­ŠÁ,Çw4*4^p­aÆ9zgY˜GékLàOTyÞ}w½­ë¢mýº¯B” ^2¤ý­¯ŠÙ JG^‹©¶¾“}úôŽéŽ÷fXìûÉ'Ÿõë×y1ì:ˆ;¶û+\;===æò£îˆbË»D¬Ó«WO[×jÙ²¥¯› ‡(A½dHúW_•³A•Dž›»Ëö<=€ð@Ÿ<ùE±qã‘—wÈ8ωÇ9ŠëׯS¦Lƒ 2Þ™U¯^=®Ý °½ä!K›¢,ñnù„˜`%ıBÌ;Äð—ÁL‡Œ,üÅ_0bmwŽcdž#ÎågŒB” ^2¤ý«¯ÊÙ j2_±b¹åûB¯Á;®#FxºX´]P&”Íé`·A®\¹Â÷ø„(A½ÊHúS_²AÕ„¾téÛ»2¸ – ËÌ̇”¾mQF”Õly3/%ˆ6”!.!JP¯²R„þÔW‡lPE©£«³~ýd_äIIµŒ0ÇŽUî{sôè£ì¨ƒ±ÃûÇM›6JÅ¢W™)Bïë«S6¨¢ØóóóDÏž=½—ЇæÍ›S TÙ÷ÏjJêÒ¬Y3Ob‡{m•È”¡Ê×e-;Eè}}uÊU–;ºÙÒÒÒ\y€'''K“aoAݾC°‡!ꈺºCÌ¥\¶l©”uQ$zÕ"ô¶¾:fƒª iz÷î×{0Œ4Eæ‡ÕldÌá5¨3êŽ ±ÆÛda ÚDæú†(½êBz[_³A]$‘’Ë—/3&—wìØQ¤¤¤Cõ##'K—.müŒ «±tíÚÕøì¼ys¥ëºóÄ1Al#Ī^½zFìÃȈYÄ1F¬ñYÈOÆ´RˆÐ®8ðWþ"Q»1y!C31Ubj³ºº-B+Qèo«÷=*‹ž_D8räH©æ°øbৃ„Û"4˃‚Ê]¿„x.B¼ˆ-Q¢DàˆbAª-B š°Êƒb óB&”Q£˜ F@,(BµEÈûÙ›û™ŠÆ™q¦ a×(»FgÆ9¨q&D»Á2YYY~x îˆãÌ83΄xú^¬=J 28P ûÈËAŒ3ã¬Sœ Äî„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„ø-£Gˆþýû ÔÙë8oÛ¶5pqFùÅ&„H/¬¬q"  ÔÙk Ö®];pqF)CBˆô"lÔ¨QàШ3%HÆKNNNÔl¿ãCD¸hÑÂÀ> QwJ2Œ‡»ï¾;jñ;>ÔQ@„÷ÜsO`Ψ»Ûñ<ø™ÀK0Âã?®Õ—õ½÷ÞW\qEÔúâwø l„H,ÂÝ»sEÉ’%û`FÝŠ"Lt6ȬEDøæ›oþáŒP„a¢³Af…„(Ô5:tèP[±ªU«Š!C+Êj§N¨»Ÿ]£ÅŠS&¦v©T©R Dh'dVHˆB£FíÊÐ qèV3êÖU”úÚÍ™^ÌéӧIJeKŰaÃDÇŽEJJЍQ£Æ…?žJ•*eü\·n]ѺukÑ¥Kã³óæÍùùyDˆb‚Ø F­Zµ2b†Ø!†ˆ%~FlcÄŸEìÑ¡æ2”±¡~õu’ 2+<'V¬X.zöì!*W®s·zñâÅE³fÍŒi)+W®\ QgÔýºë®3bk«T©"z÷îe´ E¨¡ e-;E¨W}fƒAÎ —,Y"ÒÒÒ\yßœœœ,23j=WuCQW7bئM#K¤5‘¡Ìe¦õªo,Ù`вBtÝ!Ä;p/a!S|þù‰âÔ©“ÊÇu@]P'/b‡?ÐÐV‡çS„*ËPö²R„úÔ×*„èÌD„¬pãÆ ¢~ýd_F%'%%‰#FˆcÇŽ*7”eOJªåKìÐfh;ŠPAªPFŠPŸúÚ‘œYêÜZ¾|yß§é`ÔøSO=%:(}ÌPF”ïîüŽ[… ÄÒ¥K(B•D£JÖJêQ_'‚ bVˆÁ+V”jÞ*FN>\Ê‘’(Êf6ÝÈІ2 ¤‘n?B…£R×-E¨G}È-hYanî.Q³fMG[Ü ÙÙÙâý÷·ˆöç9yò„سg·X¿~ñžlРAÆâøÕ«WëáÞ A1þ0tΜ7 ìŒ Å9±üœjñ0ð³eËfŠÐ-ê,AŠP­úz!)ճ·ß^`º#‚Š÷ìܹo‰Ê•+'ìy…sÉ´Û…Ìvú@ÛS„>ÉPe R„êÔ×KA©œN›–µìíÛߥì}‹-‹âÝ `k$œKÕ8˜Í»ÄÒo¡2T]‚¡:õõRN*g…f+ÊÜvÛ­Jß»X­nݺ1?¯’““mM¹´a´ú¡í)Be¨ƒ)B5ê뇘TÍ Ÿ}vHÔrcXÕï_llëd5šÂ«ÄÈ8Ò)ýúõ3y&?Kz)C]$HªQ_?¤¤jVhÖ¾]ºtÑâÆÎXˆÛîóê¾û:ûº‰m"AF«'Úž"¤)B ëë§TÌ ƒp?CjNvÀgu!Ú"d×(«¯Ÿ2R1+ Bר“%Ó ¯¨ƒcÙ5Jr° E¨T}e‘jY¡Ù`™›o¾Yé{ûî5mzmÌÏ+›ŸŸ§t Ú´iÃÁ2œ>A©¾2HHµ¬P×é˜,ÎéæÓ'¦OŸFrB=E¨S}eJYá‚óMWSá„ú_&ÔÏ›7WÉX/^œê¹ÄE”úÊ$•²B³%Ö ÕîWìhw‰µ7ÞxÝøêºÄÖUåkK0žc(ÖW'ñ¨’Z-º“³I‰ûsþì.º¶ãYt[•ù…6¼ÇE·ý’ î2¤嫯ŒÒQ)+Ä–<2,ÃOV[µjUÛÛ0­Y³ú²s¬^½Êö9)«° ÚŽÛ0ù(AeHÊU_™…£JVh6éºI“&RߟN7æ5ø‚ßé´1oÓ¦M¹1¯ßÔU†¡\õ•Y6ªd…S§NZFdI2vîß¿ÏÑüÀ¶mÛÚZ7Ÿqz^”EÆ®â*UªD-wvv6E赸t’!E(O}U Yáîݹ¦ûÖ=÷ÜsRÝ“³fÍ5kÖ´õLA½222ÄÙ³glŸŸÅ1f1) Ê‚2É£qãÆšÆdϞݡÂÒE†¡<õUA2ªd…©©©Qˈd(ã¶m[- Ñ ñ¼ãœ9s†­M{ /Ô½}û6)bU§N¨åD[{]ž%¨— )B9ê«Ò`„m¶Â ˜={¶oe;~üC‘™9ÐÖ4‡µk×k×®‰ûÚ8ÎåD¾(+ÊìW¼fÏ~Ù´Œ&L ý”ê2¤娯J“ÖU6–#+_¾¼éwòÀýž–éܹ³bÊ”)âꫯv4»G`/ÂD•çr²h7@™QvÔÁ˘¡ÌÊU©R%£­)B Ĥ² )Bÿë«ââÖ*ˆ»ÿþ–ßI/Î`ç,ýÖ¸qcGòÁCÞÍwuè*Å5œ” uÀRf^ìf¶±*Ï€|¹·B” ^2¤ý¯¯ŠÛ© ï½{÷˜®D‘[Ý~ØísbÙU‹KïÚµÓõíܹC´nÝÚqùP'L·pkG ´‰Õ¢h»}ûöR„²‰HER„þÖWÕ pU¸ÙhÃÂ`Õ’D]sÕª•¢o߇cZƒY†îhTh¼àZÆ sôβ0<ÒטÀŸ¨ò¼ûîz[×EÛúu_…(A½dHú[_³A•$Ž.¼-Rm}'ûôéÓïͰØ÷“O>)êׯóbØ:t;vl÷-V¸vzzzÌåGÝÄ"–w‰X!§W¯ž¶®Õ²eK_7Q‚zÉ"ô¯¾*gƒ*‰<7w—íyz;à>yò‹bãÆ "/ïqž'Žsׯ_'¦L™, d¼3«^½z\»A`{%ÈC–6EYâÝò 1ÁJ0ˆb…˜!vˆá/ƒ™Yø‹/¾`ÄÚîÇÈH EèE‹ö¡º»ßmÛ¶:Ú±ZWÄÂÍXcYÆ cÔ]‡¹t„ø2j´Q£F{h Î^Å7è2ôB‚/^ìÙDn™@Qw>D E#YYã÷à@½ŒqPeè¥#tëÖ-pqFù%aœëÜáÝB@½Ž3„´8{-ApðàÀÅuæ”P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„BEH!„P„„¼÷Þ»Œ!!!äî»ï6`,¡ d6xÅW0+$„"$$Ù`(2`VHˆ„"ܱc»èß¿?qb–ˆØ¿ýöƳ€¿ýmŽÖÙ`D„Ì ‘4#:tè…/*1±JTÜ~†1-àñÇ×>dVHˆä]£”¡·¤õá¥Ù ³BBxGHz'AŠP• 2+$DÁ2”¡7¤õa´lY!!ŠŒ¥ Ý— E¨·ͲAf…„(2}‚2tW‚¡¾"´Ê™¢Ð}J,[¶T 6LtìØQ¤¤¤ˆ5jˆJ•*q*Uª”ñsݺuEëÖ­E—.]ŒÏΛ7WäççQ ˆ bƒájÄ ±C KüŒØ"ƈ5>‹Ø£ (BÍe(c(Býêë$dVxN¬X±\ôìÙCT®\9ænõâÅ‹‹fÍš 3¬\¹"p1DQ÷뮻ΈE¬q¬R¥ŠèÝ»—Ñ&¡†2”µì¡^õuš 9+\²d‰HKKså}srr²ÈÌ(rrr´ê†:¢®nİM›6F–Hj"C™ËLêUßX²Á e…èºCX¬X1Oa!S|þù‰âÔ©“ÊÇu@]P'/b‡?ÐÐV‡çS„*ËPö²R„úÔ×*ŒlÃä¬pãÆ ¢~ýd_F%'%%‰#FˆcÇŽ*7”eOJªåKìÐfh;ŠPAªPFŠPŸúÚ‘œYêÜZ¾|yß§é`ÔøSO=%:(}ÌPF”ïîüŽ[… ÄÒ¥K(B•D£JÖJêQ_'‚ bVˆÁ+V”jÞ*FN>\Ê‘’(Ê1+ hCÒH·¡ŒÂQ©ë–"Ô£¾Nä´¬07w—¨Y³¦£‡-î…ììlñþû[Äûóœ0tΜ7 ìŒ Å9±üœjñ0ð³eËfŠÐ-ê,AŠP­úz!)ճ·ß^`º#‚Š÷ìܹo‰Ê•+'ìy…sÉ´Û…Ìvú@ÛS„>ÉPe R„êÔ×KA©œN›–µìíÛߥì}‹-‹âÝ `k$œKÕ8˜Í»ÄÒo¡2T]‚¡:õõRN*g…f+ÊÜvÛ­Jß»X­nݺ1?¯’““mM¹´a´ú¡í)Be¨ƒ)B5ê뇘TÍ Ÿ}vHÔrcXÕï_llëd5šÂ«ÄÈ8Ò)ýúõ3y&?Kz)C]$HªQ_?¤¤jVhÖ¾]ºtÑâÆÎXˆÛîóê¾û:ûº‰m"AF«'Úž"¤)B ëë§TÌ ƒp?CjNvÀgu!Ú"d×(«¯Ÿ2R1+ Bר“%Ó ¯¨ƒcÙ5Jr° E¨T}e‘jY¡Ù`™›o¾Yé{ûî5mzmÌÏ+›ŸŸ§t Ú´iÃÁ2œ>A©¾2HHµ¬P×é˜,ÎéæÓ'¦OŸFrB=E¨S}eJYá‚óMWSá„ú_&ÔÏ›7WÉX/^œê¹ÄE”úÊ$•²B³%Ö ÕîWìhw‰µ7ÞxÝøêºÄÖUåkK0žc(ÖW'ñ¨’Z-º“³I‰ûsþì.º¶ãYt[•ù…6¼ÇE·ý’ î2¤嫯ŒÒQ)+Ä–<2,ÃOV[µjUÛÛ0­Y³ú²s¬^½Êö9)«° ÚŽÛ0ù(AeHÊU_™…£JVh6éºI“&RߟN7æ5ø‚ßé´1oÓ¦M¹1¯ßÔU†¡\õ•Y6ªd…S§NZFdI2vîß¿ÏÑüÀ¶mÛÚZ7Ÿqz^”EÆ®â*UªD-wvv6E赸t’!E(O}U Yáîݹ¦ûÖ=÷ÜsRÝ“³fÍ5kÖ´õLA½222ÄÙ³glŸŸÅ1f1) Ê‚2É£qãÆšÆdϞݡÂÒE†¡<õUA2ªd…©©©Qˈd(ã¶m[- Ñ ñ¼ãœ9s†­M{ /Ô½}û6)bU§N¨åD[{]ž%¨— )B9ê«Ò`„m¶Â ˜={¶oe;~üC‘™9ÐÖ4‡µk×k×®‰ûÚ8ÎåD¾(+ÊìW¼fÏ~Ù´Œ&L ý”ê2¤娯J“ÖU6–#+_¾¼éwòÀýž–éܹ³bÊ”)âꫯv4»G`/ÂD•çr²h7@™QvÔÁ˘¡ÌÊU©R%£­)B Ĥ² )Bÿë«ââÖ*ˆ»ÿþ–ßI/Î`ç,ýÖ¸qcGòÁCÞÍwuè*Å5œ” uÀRf^ìf¶±*Ï€|¹·B” ^2¤ý¯¯ŠÛ© ï½{÷˜®D‘[Ý~ØísbÙU‹KïÚµÓõíܹC´nÝÚqùP'L·pkG ´‰Õ¢h»}ûöR„²‰HER„þÖWÕ pU¸ÙhÃÂ`Õ’D]sÕª•¢o߇cZƒY†îhTh¼àZÆ sôβ0<ÒטÀŸ¨ò¼ûîz[×EÛúu_…(A½dHú[_³A•$Ž.¼-Rm}'ûôéÓïͰØ÷“O>)êׯóbØ:t;vl÷-V¸vzzzÌåGÝÄ"–w‰X!§W¯ž¶®Õ²eK_7Q‚zÉ"ô¯¾*gƒ*‰<7w—íyz;à>yò‹bãÆ "/ïqž'Žsׯ_'¦L™, d¼3«^½z\»A`{%ÈC–6EYâÝò 1ÁJ0ˆb…˜!vˆá/ƒ™Yø‹/¾`ÄÚîÇÈøàƒÒf9VÙó<à[ÜÐf¡Â2TI‚að²Á e…ÌáÇü0%K–}û>,òòò¤ʈ²¢Ì~Æ m¶~ý:ŠPEª&AŠ0˜Ù`P²Â£GˆzõêIsïÕ¨QC¼ðÂ$)GI¢L(Ê(K¼0mH*$C%H3 JVø‡?<"å=˜’’"V¯^%MœP”IÆXõë÷(E¨Š U• EÜlP÷¬CüK”(!í}xÅWˆûï¿_|øá1ßb„k£ (‹¬qBnÙ²™"”]†*K" n6¨{VØ­[7%îÇ_ÿú×bíÚ5žÇgÍšÕÆµUˆÑïÿ{ŠPfª.AŠ0ØÙ ®Y!–ùò{°‡ÓÁ4ƒ?#Ξ=ãzlp \Kµø:t"”Q†:H" v6¨kV˜•5NÉ{³eË–bûöm®ÅçÆ5TŒMVVE(› u‘ EÈlPǬ0--MÙû³R¥JbΜ7œçV5.hSŠP"ê$AŠÙ nYáñãŠR¥J)}/^ÜØ­!Q1Án8§Ê1A›¢m)B d¨›)Bfƒºe…óçÏÓæ^íܹ“8qâx̱À±8‡.ñðóþÔN„±ÊPG R„ÌuË ±=’N÷ëõ×_/rsw9ŽŽÁ±:ÅmKú(C]%H2Ô-+ìÞ½»v÷,öùs2Ÿ­U«–vq@ÛR„>ÉPg R„ÌuË ÝÜfÉOÊ—/oët ã³:ÆmKú CÝ%H2Ô-+Te’x,”.]Z¼öÚ«QëŽßá3ºÖ¿aÆ¡×2 ‚)Bfƒºe…UªTÑúþÅäòiÓ²/«wvv¶R“äc¡jÕª¡—2 Š)Bfƒºe…^m ë÷:¥ãÇ¿Pgü,óz¡‰Üð˜"ôH†A’ EÈlP·¬°X±b¸QO,•‚RgÈž"¤)ŠÐlPå¬"¤)BvR„š‰ÐlPå¬]£ì¥9X†"ÔH„~fƒªf…,ÃÁ2!§OP„‰ÐÏlPÕ¬Ó'8}‚"ä„zŠPÊ ª˜rB='ÔS„\b"ÔD„2dƒ*f…\bK¬Q„\t›"Ô@„2eƒªe…\t›‹nS„܆‰"Ô@„2eƒªe… Ìç6L܆‰"䯼¡Ê"”1T)+䯼znÌ‹A@ܘW ê(CŠÙ nYaZZš²÷g¥J•Äœ9o&<&8'έj\Ц¾>')A½eH2Ô-+Ìʧä½Ù²eK±}û6×â‚sã*Ʀð¡$ÔI†!³Aݲƒ(5¹eÅRigÏžq=6¸®¥R|ÐÕ}èÐAŠPF ê"CŠÙ ŽYa·nÝ”ˆ%X»vçñY³fµ2‹ø9mByz!AdH2Ô1+ܼ9G”(QBêõBï¿ÿ~ñá‡Ç|‹®2ȼN)ÚpË–Í¡ìT]†!³A]³ÂGýƒ”±KIIq4AÞmP”IÆXõë×OŽç$%¨· )Bfƒºf…GÉÉÉÒĬFâ…&‰sçÎJ+” eCe‰WýúÉFR„ IPUR„ÌuÎ ×­û»([¶¬ïƒaúö}XäååI/”eõ{0 Úlýúuò<')A½eH2Ô}^áܹoù"C\óÁ;vlW®§e~à|‹Û¼ysåzNR‚zË"d6„5H-Z(ªU«æÙ²bß¾½ÊO¯B àÙ†Çh#´•tÏIJPoR„̃²3²7·ijÖ¬™9r¤8|8_»5‰óó󌺡ŽnÅïÖ[o;wîó9I ê-CŠÙ`Ðv±ùåY¢I“& ©;ãà;ž““£ý&ÞPWÔ9Q‘ÐþóŸå~NR‚zË"d6´]ì#£$/^$úôé-êÖ­k»®W]u•¸óÎvÆ–@2 æðs0bÑ®];‘””d;ŽˆyŸ>}Œ6q­"TI‚²Ë"d6ĬðRöìÙmlá4yò‹bذabÈÁcÇŽ3gÎK—.ì¼ø¬@Œ+Ä ±‹Ä1ElqŸ ÖÊM3£õ–!EÈl0¨Y!!JŠPe Ê*CŠÙ ³BB¡”Q†!³Af…„( B$(› )BfƒÌ ‘\„:JP&R„Ì™"±u– ,2¤™ 2+$DRA‚2È"d6Ȭ ÷#$„B(BB!„"$„B(BB!„"$„B(BB!„"$„B(BB!„"$„B(BB!„"$„B(BB!„"$„B(BB!„"$„B(BB!!ƒ@!„"$„B(BB!„"$„B(BB!„"$„B(BB!„"$„B(BB!„"$„B(Âx9ôˆøºÿ@:{çO¶m \œQg~± !Ò‹ðˬqB„BuöZ‚?Ö®¸8£Î”!!DzþШQàШ3%HÆÝ¶99ѳáðïøP#D~¶ha`Ш;%HÆÃ·wßµÎøj„( Âoï¹'°gÔÝíø~5ø™ÀK0Â×?®Õ—õï½+ÄWD¯søwø l„H,Âw犟K– ìƒuG (BŠ0ÑÙ ³BBá?ß|#ðgÄ€"¤ž 2+$D®Ñ/‡µõû$ÌŸá»#GÃu÷³kôg…bj—D„v²Af…„¨4}¦ 3Ä$'S" Z‰pœñtÊ ˆÐv6ȬðbNŸŸ.[*¾6L|Û±£ø>%EüT£†ø¹R¥_þ0,UJüþùǺuÅw­[‹oºt1>ûÙ¼¹â|~ã™÷Žb‚Ø FßµjeÄ ±C X†FlcÄŸEìÑ¡æ2”M‚¡ž"t’ 2+<'>]±\|Ó³‡ø©r娻֋ß7kfLKùtåŠàÅ0\gÔýûë®3bkªRE|Ó»—Ñ&¡†2”Q‚¡~"tœ 8+ütÉñ]Zš;Óq’“Å×™µž«iÌQ ×uu#†ßµióK–Hê!CY%Hê'ÂX²Á e…èºC(Šód2Å/žŸ(Ο:©~ìÂu@]P'O±…ÿ@C[?œOª,C™%Hê%B«lð­‚œþcãñcýdmHJ_Ž!Î;ªžÃeFÙJªåOìÂm†¶£”¡ì¤õ¡Y6øS˜&üЬ]¡?—/ïû4ŸªV_=õ”øøÐAéc†2¢¬xwçû¼ê ħK—P„*ÉP R„úˆÐN6‰A³B ¾ø¹bE¹̨TI|9|¸œ#%ÃeBÙ"#f¥‰Y¸ eH#Ý~„2ÊP R„úˆÐN6‰AвÂsw‰ŸjÖ´ý°ý¼àÞï¦~˜êq+¦V˜¦a 38ÌÞ0çã]`¿AñÙüyÒÄ eA™â©ÓGaö…y&̃1«UCIJfAl{„_sÛu¸-Ѧ¡Ä2TI‚¡"t’ .+žrñA^˜âaºH×ÑèÒðƒþóY3]‹Îý“ÃÁ0¨Cׂ:¹7´ÍiIÊ)Ñâ¡ U– E¨¶ãÉuÏ ÏçåYN•¨îñ½‡÷f…9áôÝaçN PŽs}Ûé^Ge8QPöbǬ†Q¤hkŠÐGª.AŠPmÆ“ êž~‘•eúìéã=ˆ®Øa¾q2¡¼vmñéÚ5ñO# Ÿç²{]”q¸‹ÝÇvèiQÆ/&L ý’¡¤Õa"²A³ÂïS£Ý"ɽX/ÌÛÒ|>sFì]¡ác.[ÖöõP¶º’Äê³%ìÂmMú C]$Hª+ÂDdƒºf…ïÎ5]Gt€d÷䜳+Äp½¾ÎÈp6ª4üÙ¯ŸÈ°½¶ê¹‚A>2Åh ELÐæ¡‡2ÔI‚¡š"Ld6¨cVøùÔ©¦ßÍ’Þ—x¶ØAvø¯víÄù#‡­ß†?ƒÏÚ=²ÈŸRV‹ „Ûœ"ôH†ºI"TS„‰ÌuÌ ¿éÚ5j=J~"ûÚîŠ4‰O>x?úÔˆðïð;çúZÂ,ðR曽ËìÖ"ôB†:J"TO„ndƒºe…?4nµ*pb…•£v§XT«Vä ü7üÎÎ9Ž\Sö¸ÉPe R„êˆÐ‹lP‡¬ðóiÙQ˾@áû[íO€÷œKÕ8˜Í»ü|ÆtŠÐª.AŠPz‘ êš­(³Jñ{·b˜#qH0?LÅc°Êl…™pÛS„ËP R„jˆÐËlPõ¬ð«g‡D-÷x îßÒW£)¼JL) ê?Ál;­¡ÏR„^ÊP R„jˆÐËlPõ¬Ðì~~E“{;?¼æ@‚¯z´[„¼b&ÂpÛS„!E¨¡ýÈUÎ ƒp?Cj¯;áë‰pEÈ®Q>8‚'B?²A•³Â t.Š¡ktaÁ±ì¥9X†"TJ„~fƒªf…fƒeÖ*~ïV³3ŽÁ28¶’â1x‡ƒe8}‚" –ýÌUÍ u>ñïœ>a=}bú4Šê)BD(C6¨bVøÙ‚ù¦«©pBý/çú¢±ø‘ê¹ÄEÊ ª˜š-±ö©‚÷ë'K¬½ñº6ðÕu‰µÏ¹Äݦƒ!B™²Aå²B‹E·*rŸ–r²èv… q-º­ÊüÂÆ\t›Û0Q„Á¡LÙ ŠY!¶ä‰Vή Ü£¿Fvãd¦5«/߆iõ*ñSÕª¶»JU؆©+·aâÆ¼a0D(c6¨ZVøM—.QË™+ùýéxcÞ÷·Dï&ÿN§yw„¸1¯ïÔU†¡\"”1T-+ü|êÔèï‘””ð¾¬áp~à¿Ú¶ç¶Œ>ó¯vílŸwqAYdì*þ‡ÙˆÑìlŠÐ+ ê(CŠPÊœ ª”~¼;WˆbÅ¢–³¯d÷ä}aÎÙ•`¸^_gdˆÎž±“ðgqŒYL s® L2Åè1‹˜|¼g7Eè¥u“!E(eÎUË ¿OMZÆ#’Ü‹u. Ñ ñl5ôù̶6í-¼PwIbuÔ¤œhk¯ï¯%¨— )B9D¨B6¨RVh¶Â ¸×Çø• 3ïµHðÇڵŧk×Äœç²{Ýo ÊZÖÇxu²(ã&P„~IPR„rˆP…lP¥¬ð|^žø¹|yÓïduãV,L¯0ÇN€ÿö¾ÎâüáüÄÅ&|®o;Ýë¨ Ç Ê^Ìã˜U·Ê’+U2Úš"ôQ‚:È"ô_„*eƒ*e…_÷ïoùôbv~ø}˜ÝøSø!ÿù¬™î *š9ø†“2¡Ý<ÚÍ¢”Ñ®øro…(A½dHú/B•²A•²Â÷î?W¬hú}ü§‹Ý~¥ æÄ²«üwmÚˆOvít%ž;Äw­[;.ß‘‚é¥]ì>þÂF6øñ¾½¡,TY†¡¿"T1T)+ürÜX[ßÉÆ ŒKj˜b\ƒY¾>ÜÙ¨Ðx _ëËaÃl-ÍV“ÂÜÀø]k÷9n[¿î«%¨— )BE¨b6¨ÔÒ3§Å÷-Rm}'§Åø@Ç{³Û s(ŽÅ°¿íÐA|²c»ë´†¯ýmzzÌå?TƒÛb|—˜f†ÝŒ¹eK£m)B %¨¢ )BÿD¨r6¨Ô¼ÂÜ]â§š5íÐ,x ÷ óaªÔµL˜¤0MÃô3¸àÙù8wƒø¡Ac× ™vð@™â©Óù‚•`ĪiAìÊIJJA~A¬vòî4Ü–˜+êgŒB” ^2¤ý¡ÊÙ jó ?]±Üò}¡×à×—#FxºX´“ÅËQ¶Ÿ¦q=fá6ütå ßã¢õ’!EèuÈU[ƒôÓ¥KlïÊà&?U©"¾ÊÌ:(ýT4”eE™¥`¸ eˆKˆÔK†¡?"Ô!TqgŠlÜ ~¬Ÿì“jaÎ;ªÜzÍç1ÊŽ:ø»ê×ÿØ´Qšx„(A½dHz/B²Aw±?ŸŸ'¾éÙÃöÚ›ñò}óæâ‹‰ÅùS'•ßÔüüÉF]¾oÖÌ †ï´U"P^„*JPvR„Þ‹P§lPŬ°pWéwii®<ÀLN_gŸlÎQ^~QG™æäuD]݈!æR~ºl©”uQ‚zÉ"ôV„:fƒ*f…—¤ù¦w¯øÞƒ/nd~XÍF†ÁžÇ0\gÔ1@,bî>®ZU|Ó§·Ñ&2×7D ê%CŠÐ[ê˜ ªœ^:RòÓåËŒÉåßvì(¾OI1†êG–!û¹tiãgd@Xå›®]Ï~6o®t]w¾vŸ†c˜ 6ˆbõc½zFìÃÈòqˆ-bŒX㳆üdA+ƒíJs²áG‰dh&B¡PLí"|¡U6(4¯ÌY!!ÒŠðŸo¾!Õ?@ üap[„fÙ`P>+$D6bõ€ŸK– ìCuw{ŠÐb´ÝÏåÊ>ƈbÁ‡)¡ü}Ï=Áýë9\w¿»F)ÂÆzÈàÀÇ1àƒ”P„N×½[´0° ÔÝõ!ÐÛ¶:Ú±ZWÄÂÕxŸ:)~hØ0°1FÝ?Ò`.!¾Œý¡Q£à=4Âuöl>PÀeè‰#ÃÌ/öl"·T„댺ó!J(ÂXGŽf ܃uötrl@eè¥#|Ó­[àâŒ:óJ(Â8׹û… :{¾RDXA‹³×4<¸8£Î|€ŠB¡ !„ŠB¡ !„ŠB¡ !„uøÿ#p8±?E?~IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/imports.rst0000664000000000000000000000322315074673150016622 0ustar00rootrootImports ======= The toplevel ``gi`` package allows you to import the different libraries namespaces and ensure specific versions of them. The next code line will import the ``GTK`` and ``GLib`` libraries from the ``gi.repository`` module. ``gi.repository`` holds the libraries bindings. .. code:: python from gi.repository import Gtk, GLib If you want to ensure a specific version of a library you can use :func:`gi.require_version`. .. code:: python import gi gi.require_version('Gtk', '4.0') gi.require_version('GLib', '2.0') from gi.repository import Gtk, GLib Currently, when importing ``Gdk`` or ``Gtk``, their init functions (``Gdk.init_check()`` and ``Gtk.init_check()`` respectively) will be automatically called for backwards-compatibility reasons. This prevents, among other things, to use ``Gtk.disable_setlocale()``, as it shall be called before ``Gtk`` initialization. This behavior may be dropped in the future, but in the meanwhile you can use :func:`gi.disable_legacy_autoinit` before the import to skip the auto-init. .. code:: python import gi gi.disable_legacy_autoinit() from gi.repository import Gtk To avoid `PEP8/E402 `_ you can use a try block. .. code:: python import sys import gi try: gi.require_version('Gtk', '4.0') gi.require_version('Adw', '1') from gi.repository import Adw, Gtk except ImportError or ValueError as exc: print('Error: Dependencies not met.', exc) sys.exit(1) .. seealso:: For more detailed information of the methods provided by the ``gi`` module checkout :ref:`guide-api`. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/index.rst0000664000000000000000000000041015074673150016227 0ustar00rootroot========== User Guide ========== .. toctree:: :titlesonly: :maxdepth: 1 imports api/index cairo_integration gtk_template asynchronous threading debug_profile deploy testing porting sysdeps flatpak faq ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/porting.rst0000664000000000000000000000764515074673150016623 0ustar00rootroot============================ Porting from Static Bindings ============================ Before PyGObject 3, bindings where not generated automatically through gobject introspection and where provided as separate Python libraries like pygobject, pygtk, pygst etc. We call them static bindings. If your code contains imports like ``import gtk``, ``import gst``, ``import glib`` or ``import gobject`` you are using the old bindings and you should upgrade. Note that using old and new bindings in the same process is not supported, you have to switch everything at once. Static Bindings Library Differences ----------------------------------- **pygtk** supported GTK 2.0 and Python 2 only. PyGObject supports GTK >=3.0 and Python 2/3. If you port away from pygtk you also have to move to GTK 3.0 at the same time. **pygtkcompat** described below can help you with that transition. **pygst** supports GStreamer 0.10 and Python 2 only. Like with GTK you have to move to PyGObject and GStreamer 1.0 at the same time. **pygobject 2** supports glib 2.0 and Python 2. The new bindings also support glib 2.0 and Python 2/3. .. note:: Python 2 is no longer supported since PyGObject 3.38.0. General Porting Tips -------------------- PyGObject contains a shell script which can help you with the many naming differences between static and dynamic bindings: https://gitlab.gnome.org/GNOME/pygobject/raw/master/tools/pygi-convert.sh :: ./pygi-convert.sh mymodule.py It just does basic text replacement. It reduces the amount of naming changes you have to make in the beginning, but nothing more. 1) Run on a Python module 2) Check/Verify the changes made (e.g. using ``git diff``) 3) Finish porting the module by hand 4) Continue to the next module... Porting Tips for GTK -------------------- PyGObject does not support GTK 2.0. In order to use PyGObject, you'll need to port your code to GTK 3.0 right away. For some general advice regarding the migration from GTK 2.0 to 3.0 see the `offical migration guide `__. If you need to know how a C symbol is exposed in Python have a look at the `symbol mapping listing `__. Using the pygtkcompat Compatibility Layer ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. note The pygtkcompat module is deprecated since PyGObject 3.46. If your code is dependent on pygtkcompat, you have two options: 1. Update your code to use the GTK interface directly 2. Copy the bits you need into your own application As of PyGObject 3.48, the compatibility layer will be disfunctional, and it will be completely removed in 3.50. PyGObject versions prior to 3.48 ship a compatibility layer for pygtk which partially emulates the old interfaces: :: from gi import pygtkcompat pygtkcompat.enable() pygtkcompat.enable_gtk(version='3.0') import gtk ``enable()`` has to be called once before the first ``gtk`` import. Note that pygtkcompat is just for helping you through the transition by allowing you to port one module at a time. Only a limited subset of the interfaces are emulated correctly and you should try to get rid of it in the end. Default Encoding Changes ^^^^^^^^^^^^^^^^^^^^^^^^ Importing ``gtk`` had the side effect of changing the default Python encoding from ASCII to UTF-8 (check ``sys.getdefaultencoding()``) and that no longer happens with PyGObject. Since text with pygtk is returned as utf-8 encoded str, your code is likely depending auto-decoding in many places and you can change it manually by doing: :: # Python 2 only import sys reload(sys) sys.setdefaultencoding("utf-8") # see if auto decoding works: assert '\xc3\xb6' + u'' == u'\xf6' While this is not officially supported by Python I don't know of any downsides. Once you are sure that you explicitly decode in all places or you move to Python 3 where things are unicode by default you can remove this again. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/sysdeps.rst0000664000000000000000000000146415074673150016624 0ustar00rootrootSystem Dependencies =================== PyGObject not only depends on packages available from PyPI, but also requires certain system dependencies to be installed. Because their version isn't taken into account by pip's dependency resolver, you may need to restrict the version of PyGObject itself for the installation to succeed. This lists the minimum version of the system dependencies over time. 3.50.0+: * glib: >= 2.80.0 * libffi: >= 3.0 * gobject-introspection: >= 1.64.0 (for tests only) 3.46.0+: * glib: >= 2.64.0 * gobject-introspection: >= 1.64.0 * libffi: >= 3.0 Example distributions: Ubuntu 20.04, Debian Bullseye, or newer 3.40.0 - 3.44.x: * glib: >= 2.56.0 * gobject-introspection: >= 1.56.0 * libffi: >= 3.0 Example distributions: Ubuntu 18.04, or newer ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/testing.rst0000664000000000000000000000067515074673150016612 0ustar00rootroot.. include:: ../icons.rst ================================== Testing and Continuous Integration ================================== To get automated tests of GTK code running on a headless server use Mutter. It allows running your app on Wayland display server without real display hardware. :: export XDG_RUNTIME_DIR=/tmp eval $(dbus-launch --auto-syntax) mutter --wayland --no-x11 --sm-disable --headless -- python my_script.py ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/guide/threading.rst0000664000000000000000000001242115074673150017072 0ustar00rootroot=============== Multi Threading =============== Operations which could potentially block should not be executed in the main loop. The main loop is in charge of input processing and drawing and blocking it results in the user interface freezing. For the user this means not getting any feedback and not being able to pause or abort the operation which causes the problem. Such an operation might be: * Loading external resources like an image file on the web * Searching the local file system * Writing, reading and copying files * Calculations where the runtime depends on some external factor The following examples show * how Python threads, running in parallel to GTK, can interact with the UI * how to use and control asynchronous I/O operations in glib This page will discuss multi-threading. A separate page discusses :doc:asynchronous. This example uses a Python thread to execute code in the background while still showing feedback on the progress in a window. .. code:: python import threading import time import gi gi.require_version('Gtk', '4.0') from gi.repository import GLib, Gtk, GObject class Application(Gtk.Application): def do_activate(self): window = Gtk.ApplicationWindow(application=self) self.progress = Gtk.ProgressBar(show_text=True) window.set_child(self.progress) window.present() thread = threading.Thread(target=self.example_target) thread.daemon = True thread.start() def update_progress(self, i): self.progress.pulse() self.progress.set_text(str(i)) return False def example_target(self): for i in range(50): GLib.idle_add(self.update_progress, i) time.sleep(0.2) app = Application() app.run() The example shows a simple window containing a progress bar. After everything is set up it constructs a Python thread, passes it a function to execute, starts the thread and the GTK main loop. After the main loop is started it is possible to see the window and interact with it. In the background ``example_target()`` gets executed and calls :func:`GLib.idle_add` and :func:`time.sleep` in a loop. In this example :func:`time.sleep` represents the blocking operation. :func:`GLib.idle_add` takes the ``update_progress()`` function and arguments that will get passed to the function and asks the main loop to schedule its execution in the main thread. This is needed because GTK isn't thread safe; only one thread, the main thread, is allowed to call GTK code at all times. Threads: FAQ ------------ * I'm porting code from pygtk (GTK 2) to PyGObject (GTK 3). Has anything changed regarding threads? Short answer: No. Long answer: ``gtk.gdk.threads_init()``, ``gtk.gdk.threads_enter()`` and ``gtk.gdk.threads_leave()`` are now :func:`Gdk.threads_init`, :func:`Gdk.threads_enter` and :func:`Gdk.threads_leave`. ``gobject.threads_init()`` can be removed. * I'm using :func:`Gdk.threads_init` and want to get rid of it. What do I need to do? * Remove any :func:`Gdk.threads_init()`, :func:`Gdk.threads_enter` and :func:`Gdk.threads_leave` calls. In case they get executed in a thread, move the GTK code into its own function and schedule it using :func:`GLib.idle_add`. Be aware that the newly created function will be executed some time later, so other stuff can happen in between. * Replace any call to ``Gdk.threads_add_*()`` with their GLib counterpart. For example :func:`GLib.idle_add` instead of :func:`Gdk.threads_add_idle`. * What about signals and threads? Signals get executed in the context they are emitted from. In which context the object is created or where ``connect()`` is called from doesn't matter. In GStreamer, for example, some signals can be called from a different thread, see the respective signal documentation for when this is the case. In case you connect to such a signal you have to make sure to not call any GTK code or use :func:`GLib.idle_add` accordingly. * What if I need to call GTK code in signal handlers emitted from a thread? In case you have a signal that is emitted from another thread and you need to call GTK code during and not after signal handling, you can push the operation with an :class:`threading.Event` object to the main loop and wait in the signal handler until the operation gets scheduled and the result is available. Be aware that if the signal is emitted from the main loop this will deadlock. See the following example .. code:: python # [...] toggle_button = Gtk.ToggleButton() def signal_handler_in_thread(): def function_calling_gtk(event, result): result.append(toggle_button.get_active()) event.set() event = threading.Event() result = [] GLib.idle_add(function_calling_gtk, event, result) event.wait() toggle_button_is_active = result[0] print(toggle_button_is_active) # [...] * What about the Python `GIL `__ ? Similar to I/O operations in Python, all PyGObject calls release the GIL during their execution and other Python threads can be executed during that time. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/icons.rst0000664000000000000000000000202015074673150015135 0ustar00rootroot.. |python-logo| raw:: html .. |ubuntu-logo| raw:: html .. |debian-logo| raw:: html .. |fedora-logo| raw:: html .. |opensuse-logo| raw:: html .. |windows-logo| raw:: html .. |source-logo| raw:: html .. |arch-logo| raw:: html Arch Linux Arch Linux .. |macosx-logo| raw:: html .. |github-logo| raw:: html .. |git-logo| raw:: html .. |bug-logo| raw:: html .. |linux-logo| raw:: html ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/LICENSE0000664000000000000000000000030415074673150015545 0ustar00rootrootpygobject.svg and pygobject-small.svg are based on the GTK logo, created by Andreas Nilsson, licensed under CC BY-SA 3.0. For more info see https://commons.wikimedia.org/wiki/File:GTK%2B_logo.svg ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/arch-dark.svg0000664000000000000000000000042115074673150017115 0ustar00rootroot ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/arch.svg0000664000000000000000000000042015074673150016175 0ustar00rootroot././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/favicon.ico0000664000000000000000000010327615074673150016675 0ustar00rootroot hV ˆ ¾  ¨F00 ¨%î@@ (B–D(  ¤¤‹ÞîîîîîîîîÞ‰‹ÿÿ***ÿdddÿhhhÿ222ÿÿÿÿÿÿÿŠÞÿÿ¹¹¹ÿÁÁÁÿ···ÿúúúÿ€€€ÿÿÿÿÿÿÝîÿÿÿÿÿjjjÿüüüÿÿÿÿÿÿîîÿÿÿWWWÿ€€€ÿ|||ÿÿÿÿÿ888ÿÿfffÿÿÿîîÿÿ   ÿïïïÿžžžÿÍÍÍÿÿÿÿÿ<<<ÿOOOÿÿÿÿÿÿÿîîÿÿþþþÿVVVÿÿ...ÿÿÿÿÿ<<<ÿOOOÿÿÿÿÿÿÿîîÿ222ÿÿÿÿÿ666ÿÿ...ÿÿÿÿÿ<<<ÿOOOÿÿÿÿÿÿÿîîÿÿùùùÿ‹‹‹ÿÿ===ÿÿÿÿÿ<<<ÿOOOÿÿÿÿÿÿÿîîÿÿtttÿýýýÿ÷÷÷ÿëëëÿòòòÿ<<<ÿOOOÿÿÿÿÿÿÿîîÿÿÿÿ---ÿ ÿÿÿÿ111ÿÿÿîÞÿÿÿÿÿÿÿÿ[[[ÿÿÿÿÿÿÿÝŒÿÿÿÿÿÿÿÿÿXXXÿÿÿ‹ŒÞîîîîîîîîÞ‹ÿÿ€€€€€€€€€€€€€€ÿÿ(0 vv3_ffffffffffff_2ºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¸»ÿÿÿÿÿÿ+++ÿÿÿÿÿÿÿÿÿÿÿÿ¸4ÿÿÿÿ–––ÿòòòÿÿÿÿÿÿÿÿÿýýýÿÁÁÁÿ///ÿÿÿÿÿÿÿÿÿÿ2`ÿÿÿÿŠŠŠÿ¾¾¾ÿ‡‡‡ÿ‡‡‡ÿÈÈÈÿÿÿÿÿïïïÿ ÿÿÿÿÿÿÿÿÿ_fÿÿÿÿÿÿÿÿÿ¹¹¹ÿÿÿÿÿ‘‘‘ÿÿÿÿÿÿÿÿÿffÿÿÿÿÿÿÿÿÿ```ÿÿÿÿÿÉÉÉÿÿÿÿÿÿÿÿÿffÿÿÿÿÿ;;;ÿ¥¥¥ÿÉÉÉÿ¯¯¯ÿ™™™ÿÿÿÿÿØØØÿÿÿ£££ÿªªªÿÿÿÿÿffÿÿÿÿVVVÿüüüÿÿÿÿÿïïïÿðððÿÿÿÿÿÿÿÿÿØØØÿÿÿõõõÿÿÿÿÿÿÿÿÿffÿÿÿÿêêêÿÿÿÿÿvvvÿÿÿsssÿÿÿÿÿØØØÿÿÿõõõÿÿÿÿÿÿÿÿÿffÿÿÿ111ÿÿÿÿÿæææÿÿÿÿEEEÿÿÿÿÿØØØÿÿÿõõõÿÿÿÿÿÿÿÿÿffÿÿÿPPPÿÿÿÿÿËËËÿÿÿÿEEEÿÿÿÿÿØØØÿÿÿõõõÿÿÿÿÿÿÿÿÿffÿÿÿ:::ÿÿÿÿÿèèèÿÿÿÿEEEÿÿÿÿÿØØØÿÿÿõõõÿÿÿÿÿÿÿÿÿffÿÿÿÿøøøÿÿÿÿÿ}}}ÿÿÿhhhÿÿÿÿÿØØØÿÿÿõõõÿÿÿÿÿÿÿÿÿffÿÿÿÿ€€€ÿÿÿÿÿÿÿÿÿùùùÿóóóÿÿÿÿÿÿÿÿÿØØØÿÿÿõõõÿÿÿÿÿÿÿÿÿffÿÿÿÿÿ[[[ÿ´´´ÿÌÌÌÿ±±±ÿUUUÿ~~~ÿÿÿÿ£££ÿªªªÿÿÿÿÿffÿÿÿÿÿÿÿÿÿÿÿÿÿÿ+++ÿ777ÿÿÿÿÿf`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿøøøÿþþþÿ666ÿÿÿÿ_4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿéééÿöööÿ'''ÿÿÿÿ2½ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿº½ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»5`ffffffffffff`4ÿÿÿðÀÀ€€€€€€€€€€€€€€€€ÀÀðÿÿÿ( @ HHm»ÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝØºl#ØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖ! ×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖmÿÿÿÿÿ...ÿ{{{ÿ¼¼¼ÿÖÖÖÿåååÿÔÔÔÿ¢¢¢ÿFFFÿÿÿÿÿÿÿÿÿÿÿÿÿÿk¼ÿÿÿÿÿ···ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¨¨¨ÿÿÿÿÿÿÿÿÿÿÿÿÿºÙÿÿÿÿÿXXXÿÍÍÍÿ………ÿ[[[ÿPPPÿxxxÿâââÿÿÿÿÿÿÿÿÿŠŠŠÿÿÿÿÿÿÿÿÿÿÿÿØÝÿÿÿÿÿÿÿÿÿÿÿÿëëëÿÿÿÿÿ÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÝÝÿÿÿÿÿÿÿÿÿÿÿÿ”””ÿÿÿÿÿÿÿÿÿQQQÿÿÿÿÿÿÿÿÿÿÿÝÝÿÿÿÿÿÿÿÿÿ ÿÿÿqqqÿÿÿÿÿÿÿÿÿnnnÿÿÿÿÿÿÿÿÿÿÿÝÝÿÿÿÿÿÿÿ“““ÿëëëÿÿÿÿÿûûûÿÌÌÌÿ²²²ÿÿÿÿÿÿÿÿÿwwwÿÿÿˆˆˆÿÝÝÝÿÝÝÝÿÿÿÿÿÿÝÝÿÿÿÿÿÿÝÝÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿwwwÿÿÿœœœÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÝÝÿÿÿÿÿ°°°ÿÿÿÿÿÿÿÿÿ¼¼¼ÿHHHÿ000ÿ___ÿ×××ÿÿÿÿÿÿÿÿÿwwwÿÿÿœœœÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÝÝÿÿÿÿÿþþþÿÿÿÿÿØØØÿÿÿÿÿ\\\ÿÿÿÿÿÿÿÿÿwwwÿÿÿœœœÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÝÝÿÿÿÿ[[[ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ\\\ÿÿÿÿÿÿÿÿÿwwwÿÿÿœœœÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÝÝÿÿÿÿqqqÿÿÿÿÿÿÿÿÿcccÿÿÿÿÿ\\\ÿÿÿÿÿÿÿÿÿwwwÿÿÿœœœÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÝÝÿÿÿÿlllÿÿÿÿÿÿÿÿÿtttÿÿÿÿÿ\\\ÿÿÿÿÿÿÿÿÿwwwÿÿÿœœœÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÝÝÿÿÿÿIIIÿÿÿÿÿÿÿÿÿ¹¹¹ÿÿÿÿÿ\\\ÿÿÿÿÿÿÿÿÿwwwÿÿÿœœœÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÝÝÿÿÿÿ ÿóóóÿÿÿÿÿþþþÿlllÿÿÿ ÿ’’’ÿÿÿÿÿÿÿÿÿwwwÿÿÿœœœÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÝÝÿÿÿÿÿyyyÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÿäääÿüüüÿÿÿÿÿÿÿÿÿÿÿÿÿwwwÿÿÿœœœÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÝÝÿÿÿÿÿÿ€€€ÿøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿¿¿ÿÍÍÍÿÿÿÿÿwwwÿÿÿœœœÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÝÝÿÿÿÿÿÿÿÿQQQÿjjjÿbbbÿ...ÿÿÿ333ÿÿÿÿÿ333ÿ333ÿÿÿÿÿÿÝÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿhhhÿ<<<ÿÿÿÿÿÿÝÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿþþþÿ;;;ÿÿÿÿÿÙ¼ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛÿÿÿÿÿÿÿÿÿcccÿÿÿÿÿºoÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿJJJÿØØØÿ¬¬¬ÿ ÿÿÿÿÿm ÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØ$ÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØ# o½ÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÙ¼n ÿÿÿÿÿÿÿÿðàÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀàðÿÿÿÿÿÿÿÿ(0` $ìì?Ž´ËÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌË´>0ÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅ/NõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôM1õÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿô/Åÿÿÿÿÿÿÿÿÿÿÿ222ÿIIIÿYYYÿNNNÿ999ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ@ÿÿÿÿÿÿÿÿ///ÿŽŽŽÿÜÜÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÿ»»»ÿJJJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ>ÿÿÿÿÿÿÿÿ¬¬¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿÿÿÿÿÿÿÿLLLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÿóóóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´ÊÿÿÿÿÿÿÿÿÿÖÖÖÿ£££ÿYYYÿÿÿÿ ÿEEEÿ»»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ|||ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿîîîÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿÿÿÿÿÿÿÿÿÿÿMMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËËËÿÿÿÿÿÿÿÿÿÿÿÿÿ‰‰‰ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢¢¢ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡¡¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿÿÿ+++ÿqqqÿÿ”””ÿwwwÿJJJÿÿ‘‘‘ÿÿÿÿÿÿÿÿÿÿÿÿÿ±±±ÿÿÿÿÿ???ÿDDDÿDDDÿDDDÿÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿ...ÿÂÂÂÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëëëÿÙÙÙÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿGGGÿôôôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿ!!!ÿñññÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèèèÿÀÀÀÿÂÂÂÿíííÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿ¬¬¬ÿÿÿÿÿÿÿÿÿÿÿÿÿöööÿ]]]ÿÿÿÿÿQQQÿàààÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿüüüÿÿÿÿÿÿÿÿÿÿÿÿÿ___ÿÿÿÿÿÿÿ‰‰‰ÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿ```ÿÿÿÿÿÿÿÿÿÿÿÿÿãããÿÿÿÿÿÿÿÿ‰‰‰ÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿ’’’ÿÿÿÿÿÿÿÿÿÿÿÿÿ¨¨¨ÿÿÿÿÿÿÿÿ‰‰‰ÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿ¦¦¦ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‰‰‰ÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿ«««ÿÿÿÿÿÿÿÿÿÿÿÿÿœœœÿÿÿÿÿÿÿÿ‰‰‰ÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ···ÿÿÿÿÿÿÿÿ‰‰‰ÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿyyyÿÿÿÿÿÿÿÿÿÿÿÿÿèèèÿÿÿÿÿÿÿÿ‰‰‰ÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿAAAÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿhhhÿÿÿÿÿÿÿ‰‰‰ÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿâââÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÿpppÿ ÿÿÿÿFFFÿÑÑÑÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿaaaÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ÿÕÕÕÿÕÕÕÿøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿqqqÿîîîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóóóÿ|||ÿÿÿÿÿÿÿÿÿÿ²²²ÿÿÿÿÿëëëÿÿÿÿÿÿÿÿÿÿÿÿÿ666ÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿÿ ÿNNNÿ………ÿœœœÿ¢¢¢ÿŽŽŽÿZZZÿÿÿÿUUUÿUUUÿ;;;ÿÿÿÿÿ???ÿDDDÿDDDÿDDDÿÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’’’ÿ£££ÿ>>>ÿÿÿÿÿÿÿÿÿÌÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáááÿÿÿÿÿÿÿÿÿüüüÿ<<<ÿÿÿÿÿÿÿÿÊ·ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿSSSÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@@@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‰‰‰ÿÿÿÿÿÿÿÿAÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥¥¥ÿÿÿÿÿÿÿÿÿÙÙÙÿÿÿÿÿÿÿÿÿ?Çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ;;;ÿJJJÿ ÿÿÿÿÿÿÿÿÉ2öÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõ0NöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõM3ÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ1AµËÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ˵@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿü?øððàààààààààààààààààààààààààààààààààðøü?þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(@€ @]ª»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»ª]!¤ûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿû£føÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷d‰ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‡aÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿf"ùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ ¦ÿÿÿÿÿÿÿÿÿÿÿÿÿ000ÿlllÿ•••ÿ´´´ÿÉÉÉÿÎÎÎÿÇÇÇÿ´´´ÿžžžÿeeeÿ%%%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£ûÿÿÿÿÿÿÿÿÿÿ...ÿ‘‘‘ÿæææÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÇÇÿNNNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿû_ÿÿÿÿÿÿÿÿÿÿÿŸŸŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ\‘ÿÿÿÿÿÿÿÿÿÿÿ@@@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿÿÿÿÿÿÿÿÿÿÿÿßßßÿÿÿÿÿÿÿÿÿÿÿÿÿçççÿÃÃÃÿ¦¦¦ÿ™™™ÿªªªÿÏÏÏÿüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿¿¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¨»ÿÿÿÿÿÿÿÿÿÿÿÿÿÃÃÃÿwwwÿ///ÿÿÿÿÿÿÿÿŠŠŠÿüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿhhhÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿZZZÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáááÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®®®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿEEEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿIIIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‡‡‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ½½½ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÝÝÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÒÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$$$ÿÿÿÿÿÿÅÅÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçççÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿfffÿ···ÿöööÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÿÉÉÉÿ~~~ÿ!!!ÿ»»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ***ÿ»»»ÿ»»»ÿ»»»ÿ»»»ÿ»»»ÿ555ÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿSSSÿáááÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿôôôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿwwwÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿiiiÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿ'''ÿõõõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñññÿ™™™ÿ```ÿMMMÿ[[[ÿ‰‰‰ÿØØØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿ¥¥¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂÂÂÿÿÿÿÿÿÿÿXXXÿíííÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßßßÿ ÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿbbbÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿaaaÿÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿŸŸŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÿÿÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÈÈÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×××ÿÿÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÛÛÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂÂÂÿÿÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿèèèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ½½½ÿÿÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÝÝÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊÊÊÿÿÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÎÎÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿ©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,,,ÿÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿvvvÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’’’ÿÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿ...ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûÿCCCÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿËËËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÿzzzÿÿÿÿÿÿ"""ÿ„„„ÿöööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿGGGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÿÒÒÒÿ¾¾¾ÿÂÂÂÿâââÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿšššÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûÿâââÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿZZZÿáááÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÉÉÿ777ÿSSSÿÿÿÿÿÿÿÿÿÿÿÿÿíííÿÿÿÿÿÿ:::ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHHHÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿCCCÿŒŒŒÿ¶¶¶ÿËËËÿÝÝÝÿÏÏÏÿ¸¸¸ÿÿ777ÿÿÿÿfffÿfffÿfffÿ___ÿÿÿÿÿÿÿfffÿfffÿfffÿfffÿfffÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ111ÿ¸¸¸ÿæææÿ¼¼¼ÿ777ÿÿÿÿÿÿÿÿÿÿÿÿ»»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ+++ÿ÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿúúúÿ555ÿÿÿÿÿÿÿÿÿÿÿ»«ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶¶¶ÿÿÿÿÿÿÿÿÿÿÿ©“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐÐÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÞÞÿÿÿÿÿÿÿÿÿÿÿ`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸŸŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬¬¬ÿÿÿÿÿÿÿÿÿÿÿ]ûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìììÿÿÿÿÿÿÿÿÿÿÿÿÿñññÿ&&&ÿÿÿÿÿÿÿÿÿÿü§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšššÿÆÆÆÿžžžÿ!!!ÿÿÿÿÿÿÿÿÿÿÿ¥#ùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø!cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿh‹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‰iùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùg#§üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü¥"_‘ª»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»ª‘^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàÿÿ€ÿÿÿþü?øøððððððððððððððððððððððððððððððððððððððððððøøü?þÿÿÿ€ÿÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/logo.svg0000664000000000000000000002064115074673150016227 0ustar00rootroot image/svg+xml gi ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/overview-dark.svg0000664000000000000000000002046315074673150020056 0ustar00rootroot Python PyGObject GIRepository GLib GObject libffi Gtk-4.0.typelib libgtk-4.so ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/overview.dia0000664000000000000000000000353515074673150017076 0ustar00rootroot‹í\ËnÛ8Ýç+ w›Ð"EQdݤ@˜n2è3]´EÛjeÉè$îb¾}(J®mYòCÔAé")¤\ÝCR¼ç¾üáãË"è=‰8ñ£ð¾Õï‰py~8»ïý÷Ï;ÚÿøpóÁóù{õ3‹ù¢§ž“ôê¾?—rù~0x~~Á:á2ŠAà¯@"ÿñ àe4è?Üôz»<.yz/¿Ë¥ŒýñJŠ^Èâ¾?æ“ï³8Z…^?³Êí&QŽ'Ü÷ßMóO;ìy:â}Égb þ½Ú¹¥>ŒÕs¾qÑñb%¾2‘ëåI…Ÿô÷ŽMn•(£pöðîQH)âwY±ò›[e…­’ ÏüðKµP5ŽÍÒÔ±-äÚ›v¹nüºpÁëÂů ç'£e˘ûòrEàa†*㕨“Lx ºØ±jÁúÞ§¾”щòOyœSìöψ»4zg±ïÞ=‹ /ÞZýïO:}%Ͼ'磗Ž^Iæ}Ý‘÷'?ñÇ(+½ÊÖܯÛq_ì:OloØã2o•‰È£ÂND4[ùžHNtæ}› OóÜlpªÝ‹v ›Æó“eÀ×Ç«P4ªðÅCé+ã‰ðºeÊ/ïdtW ‰&”v)“Žé=ŸS£P&Qªê(%z·ŒT´&í@žÛ³[‘ªQUq^ÒO[yÚËÉ&/I//?ß¹ÅUuž6W;Ý={qy7þGòÐã±×»ë}Š^ú[9®Ä¸ïÝ÷¿XûaPl<åLIƒPÖm˜ë($ä–jcÊŠQzØdU0ãq%NkÎñÉ%É¥ iˆ Ñ[¨nÔƒXŒ&Qêæ¶k¨¡tú;¬å&õ©z` %Ø¢Ôq`Í…?›Ëj0¦*¥ ¬Íáz`ã(öD<ÚÏ7%‡àôß6ã\†’ñ¨døv:v/AQbTŒ¾E{B[Špµ8Hð—xÎ:Ù(æž¿Jª_аµÿA'ð²›YÌW‘À׿Uü+*¢„`S€jhï`çZªÿºn‡ "Ya®;„€úZ ~X]ä…¼B›y¾J…RL+MxÅàZÓ{(ãõˆëô\t¿™™(“¸Ä‹ºF/¾ìCŠyª³lªU—aÏ®PØ¿×r…“AGTXÕp< e\z¿7UÛ`}ßäjÈÞKä:Õ9˜öógÿˆV±/â]Evyúo)Óãf ûÔYûvû*~è.ß×+¦á3Sq(5ì™… QþRKæqí^&¥k¤ïhXxÁ°VH[uuTö8œM½Ú²gêÁ Å9ëδj¬`i–£ˆÂ.…‚ÒêY6u)"•]íT$·.êUˆ„Æmw–Bm#>Œdø-%Ãç/šMŒjèZ5PÀpª±ˆÑ F3\­f°Ï0Ú€8ľuMvºœaTHV†ÒQàÚêšk#_ƒth¥ ÏQ°Ûý˜ £ÎU?žù±Ð¾£xm4DÇ]hßR€fŽQFE\­ŠÀUºäV/v*"­‚´†@饒꘠·¬!Zh@³DaCÛŠAý¥ð J!}½>i„‚ ×+œ6„ƒ®ž[ë^)à ‰n¤‚¾¶ûæ¥Bã&4ZÁh…¶µBd'^K.°ŒÈ,#Œ\ø¥rag ô£ªa‰d w58?·ðŽw@*$ËÖH"{˜î °Ò™ÖvhÝÍ©a8¡w°3þìz–nV Ô#×Ü4­Bn²,–§ì¬M­nÞáveÕ˜#ÇÑsõFb„º"œ'»šøëAž¤¢šˆÛãÉÁ;Ùü¥7WqœæP¶2Ò—{Û¿îiÁêgaþ,Ú–.*¨¦qN,ÀhTn·¨RIJYK—¨¡ RC7ÝCU?¿œM3•¬>™‘šâº É’©&Ô€d¬ýgí¶Iæ“ø¡FTCS^À Í‚ë<²QHéA.\¥†¶Ò2d˜Õ>–$~ŒNMUMm ¸¾ÌÔR£ÂŽšnªZ4­q¶(íÉ*8(Géß Éý†$gÕ 9{£Âà¯d9ööX.)ZÓ4‰£g{]Ûy»4g«zA÷ÍåUÝ754ghîÐê‚æNœÌµZXËB·Pýb]¯c9&Û3‹œôL>Äo{«YÙÕ+³zÕòêÕtꛕ«îW®TÜ;#׬[™u«ëÝæmÇfî©LMºüÞžÈÒ@#lh»Y§sŒÕ¾ÐFžw¦Yqn0ºáLÝðY~¿³R¯f§l÷ÂÆÀql˜²r6ÂhˆëÕ¨ ¡'ö µ'öΔdHîÐvÓ×`Ý·­"7¡™m0ª¡í½²Z8$‘Q ]+{»„±ùþ/£^K1d×úˆnö¾¢øáæF·¾c././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/overview.svg0000664000000000000000000002004015074673150017126 0ustar00rootroot Python PyGObject GIRepository GLib GObject libffi Gtk-4.0.typelib libgtk-4.so ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/pygobject-dark.svg0000664000000000000000000003500015074673150020167 0ustar00rootroot image/svg+xml ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/pygobject-small.svg0000664000000000000000000002111115074673150020354 0ustar00rootroot image/svg+xml ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/pygobject.svg0000664000000000000000000003460315074673150017260 0ustar00rootroot image/svg+xml ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/start_linux.png0000664000000000000000000002324515074673150017633 0ustar00rootroot‰PNG  IHDR@“ÀØ­* pHYs  šœtIMEà 9)¿üÎäbKGDÿÿÿ ½§“&2IDATxÚíÝ œå7ðÿ ÷}ˆˆ*xFDEuÕhðŠG²¹³Ùd}“ÝMLÌÍfº9ÞMÞ$cŒÇz‹ÆDÄ/0àŠ(*÷} Ã9ýöSÚcÏ034§s|¿|Šê®ª®®zjªêWO=Ý]VUU¹\.Ö­[ .Ì­^½:6lØ›7oŽÚÒtAYYÙVÃZ·níÚµ‹®]»FŸ>}Ê:vìXcº²€R IÝk¯½–›2eJtïÞ=†šõ[µj¥d€&eË–-±råʘ>}zÖ?úè£càÀe)e]š …Ÿ_|1 ?^xaþE›cÓ¦MQД¤“*qÚ´i“õo¹åÖ>|x~øáeÕhΜ9¹I“&åÃÏQQQ!ôÍ* uêÔ)n¾ù–øÀ>ƒ *+O'ÕüœsÎ9±víZáhVR¶IçÜsÏ©S§f•=å©ÁsûöícóæMJh¶RÖI £-Z”+O ƒöÛo€š YKYgÀ€±bÅŠ(OuïÙ³§Rš½½öê™}ÍOyú´W‡”Ðì¥Ì“²Oyá;€š»Bî)W@KS®öhI² hqH1Åu7Ü”uMe¾@ÓÕZ °­pðÑK/VH@³‘²OkÅœBz/B .Šj/GïÞ½â¤| Ú·k— Û°qc<òè¤X´xñN-‡lÓ+³_™/¿’ý–N§ŽãÐCκ†–éÀT{xëÖ­¢Kç.±qÓ¦¨¬¬Ì¾ãØcFD¿¾ûÖ¾j¿¾¼¼<ºwë#{÷êU=ü¥™³âÙ©Ó²üèaÑ;Xþ<áþX±re>œûôî÷Þ7!žÉÏ«ß9g7¸ é½Ó|çÍ_“žx2ž|jrœsö™Õã×oØgqztëÖ5^{}n<ùôä,,1Ü„P»†eO·¥sÊÉ1a⃑~¶+… €Ò1¤s§N1fôI;5o ÍœõrÖrä‘Y°9ü°Ck /6lè­ÂOrP>õìÙãÝ tà ìëè“5k×ns† mÛ¶ý÷=_½fÍVï›æßªU«,„%oÍ›gãA×±C‡8íÔS¢K—.YJá'ÕB§Ú ‚v†  Akß (wÞ}OákÖl\êûY^е«õ|›ÁŽoÏ7Õê$ÅÞXºlY<÷×éY•øÆ«Ç­[WiãA3P^V–]Ü´jÝ*,hµÓó€€uȇµk+âü[D“Ç&=k+*bôI'Fß}ûDUUUÜxó­~âšÔVðþŠU«VW·ùY½zu6ì´1£wê·L  Aï;ôÐxfÊÔ˜2mZÖ¦&]y-^²$fΚcFŸüž/_Õ;A§m›6±eKUVMUcûJŠ÷úû³|äÑêð“O2ᇲôàÃÄYs†ì‡zH´oß.^œ9+îÿöm°Þ{÷Š÷vX£X¾÷?*Ц䊪õffùòѳG÷8å䓪k{RJá'ÝöÞe&LÈ 2X)-Âôé3| hy @€ @€ @€ €Ó:ý7sæ‹JhYè°ÃW@‹0}ú ·À€–G @€ª]wÃMzeûòa[5Õò±½€¦¦õÎà>zéÅÙðÔo,ÜR—¥x¹wå:¼<{v,\¸8N|ÿñuŽtÒã±oŸ>ñÔägÞ“r«Oåúõ1uÚs±`ÁÂØ¸qcìÕk¯8â}ï‹þýú¶¨ð°;·É{µ¯ìèr5Ö娣¨¾“Ã{y€Ü™÷Þ]Ë}àÀ1}Æ ±¶¢":wêTc\¶xÉÒ8aÔqqðA6ª?„ÇŸx*zôègŸyF´iÛ6–.]/¼8³Y âm¿'OòÂ@ @Ûsõ˜Ëåâù^ŒÙ¯Î‰›6Å€þýbäˆáѺuë=²bUUUñì”iñúܹQV^‡¿ï°:—»PPèïìIªU«VqH>ÜÌœõrŒ8zXq/Íœ‡|P6Mq¹5TVwÞ}OœrÒIѵk—X·®2n»ó®¸`ܹѡC‡Xµzu<ôÈcñ¡žµÓåµ$xN>ñýÕÛgŸÞ½³®Ôí¹zÍš˜öÜôX´hQTå§Ý·Ï>qÜÈc¢]»vÕå›ÊãÅ|¬[·.[÷4Ïé3žW_{-6mÚƒ8¼Ævzù•Ùñü‹/Åúõë³p6jäÈèÞ½Ûnû›ÙÖ:ÖµiØQCgÃZåÿÎÒ:¯\µ*^|iföºŽ•/ǽ·ÚWÒãcQïúm«<÷´íÙŸÓº}ÔЬLrùýð€öÏÊ­¼\“C ñØmG¤—ò`áâÅ1vÌ)1óÂ\üuúŒ=¶b3òëÕkVÇÙgþMœuÆi1þü¯ÊSW]¡zÈÁñÚësó'õMÕÃÒã×羇æÐö”U¿}ûæÇ-Ê¿5o^žÞš÷öº,Z´8úõÝw—,ó^={d'Ü5kÖîÐö|ô±Ç³õ>?ÎÎÿÐ9Y@›šŸ_±EùןyúØêrN'ÿEK–TÏs]eeéç/X§zJ\tþ¸üzö§Ÿyf·þÍ”ò7[{’ÊÊõqÞ¹Œ£†‰Çžx2[qùçCS¦N«÷ýZ¿RÊsOÚÞýyÁÂ…ùýîôlÿ[ê)<4Ù”®ìŠ»†Ìžýj;bDtîÜ)Ú¶mÃ>*æ¾ùÖ.]øÚËS¼L¯½öz3|xtìØ!ßuÌï)é*}¿ýãå|×fì?`@Wð •Uß|ÀY´hIu:ìÐC²~²p ßBTåªbÂÄM·Ü“ò'òÊ¢@²­í™nõÙ§wÐÚ´iÃòa`þ‚5Þã˜áGg'ò‚Wç̉‘ùíÒ¥sçlžµkÌŽ9"»˜j?ì°X¶|ÅnÝn¥üÍÖ^‡dèÐÁÙ:x@lÞ¼9†y÷ùÊ•+ë}¿†Ö¯”òÜSûÒŽìÏïî{bD¾Ìæä÷G€Æd§ÛÕ'µwÿ§{«Ÿ§*ô²²²]ºð -Oº Oë‚.]:ïÑ‚=ü°CãþŠ÷åK2ë•Wbì)§lwY¥“àäg§d'Ö%K—ÅûwŽ¿'ÿ|K,[¶,Nuì.YÞöíÛg·dR—nɼðâKñØãOf5¥lÏeË—ÇÔiå+Vd¨“ÚÛ»S­6Qé–^CÛ¥C~™ªÿP[·Š-[¶ìÖmVÊßlíuÈo>$­Þ¹ÅSü|KUÕ­_)å¹»÷¥â´½ûs}/pk×î4©´=:uêcFŸ¼UCà=¥cþ*=´»uíš=_³ví}ÿ.]ºDÏ=cîoF.ÿo¯ž=ë=Ù7TV© k~^³^~%zíÕ3»ú׬—_Žnݺfãwµ†† ·ÞqgÉÛó±IOd·|NìwB´mÓ&»å÷¿·ÞÞð6êØ1»å¶;Ûõ4¥¿Ù-ÏÆT6ÅûÞÚµÙþИì¶6@‡|p<õô䬡njœn<öø{lŰ<;ejV˺ô¸Þ~»vÙrîjG~XÖö¥—fmÕ{{Ê*ÝæJmšÒÇ瓾ûöÉž÷ÝE·¿’~4kß’j!6lØÏ¿ðBÖ.¨ÔeL5TmÚ´ÎnçTäO~O>½íö: “§LÉŸ ×fµÏ6Ð^fOx¯ÿf‹íHy6¦²©±ïMší-¢(5àŒ²ˆG”àºä¯‡ ¼Kߣ¾ï&JŽ<òˆì |÷½Î>}rD>€,X¸¨î rÄáñ— ³“ð®ü¨òÞ½zU×ФÇ;ZV)=“_—}÷};¥ 4eÚsYé]·½Šç¦ÏˆeK—emNz÷î'ŒUò2Ž:nd`ôDtèÐ> |o¼ùfƒï™¦I'úû&>˜õ‡ä·Ù{z’ß³¥Ú‘òlLeÓgŸ}âO¹/ Kì¿_¶?4&e&LÈ yò@óã Ænzþ‚ßs-Ž@;Ãí/@€ €=.û ô‹Ó-* 2TIMÒo¼¾]Ó/Z´Ø-0 åÙ*¥_x.t¿øÅ/JšÉ­·ÞZãu¥Ú‘×”2ÏÝ­Ô÷(eº=±¼ï…Æ´^;º, ý}]€¦äÜß´k^¨ —ËÅ?üÃ?ÔyÀ¯}Ð¿à‚ ²é·WzÍŽ¼®9ië¿§BÀøñãã„NÈ~­¾_¿~ñÙÏ~6–/_¾[·M}ÛÇß.ÐØ=¿àÑøÆ=§U‡•Ô]rmïøÖŸNéónñ!©ä[`-á€ÿÄOÄÈ‘#£S§Nqúé§ïÖ“+Ûïç?ÿy|ã߈¥K—ÆŒ3¢K—.ñ±}LÁÔáÆ)ßK†³úù]ŸÙ¿½äåøà‘—ÇÏùtZ²FÛhöìÙqæ™gFÇŽã”SN‰×_½FCC5Rÿþïÿ#FŒˆ5kÖlsžo¾ùfœwÞyñ­o}+.\}ûöo~óí?œÅ‹ǘ1c¢sçÎñõ¯½Æ{TTTÄG>ò‘èÑ£Gœx≱`Á‚ãÿõ_ÿ5{]z¿4ŸºÖa{×ý׿þuôêÕ+ú÷ï÷Ýw_õ¸Þ®½öÚX¿~ýv•ušgZ¯´œi=—,YR=nàÀ1sæÌìq*—ô¾›6mª±µÔ·œéS‡§vZtíÚ5ë ±¡õ»ÿþû³rIËÙ³gÏøÞ÷¾'N,ië›ç¶¶ßŽhhývÇv¨«ö'T‰#÷=±ÆðNm»ÇÈýÏŽOúIÜþ×gÃÖo®ˆ«úx\zí>qåÝcbź…ÕÓϘÿHüÓÇÅ…×tÏÜxp<ðòµu¾ß­Ïý0?ݨ¨Ü´¦FSíÇÉÊÊÅñ{ÏŒ‹ß+ë§çÅ5F×=ó­øð5=³šªUë—´¼töÙgÇ¿øÅìjÿƒü`|îsŸÛª6*u¿úÕ¯âŸøÄV¯¿æškâøCüùÏÎj ¶5Ï«¯¾:{ž†§éSºçž{²qW^ye 2$Þzë­X»vm÷ùÎw¾:tˆ¹sçf'»¯~õ«5Æ/[¶,{ÝСCk„§†jÔZÎdÖ¬Y1gΜøîw¿W\qEe¹ãŽ;â€Ȇ¿öÚk%—÷ºuë²åLëY~ÉèÑ£ãÈßvÛmÙò´iÓf«u¨k}ê[ί}íkqøá‡Ço¼‡vXV¾¥¼®¶Ç{, TÒú5Tf m¿±­õÛÕÛ`[µ?µÑçýñò’gß™ö_¢mëñÛK^‰aýOk'¿{®ºúáççóí¸ñc‹ãûgOȫǶšW E½òÇøÎߌmºT×6¥®öãä“¿z¼/þçÒÙÑ¿û¡ùç5—sÃæuñ»ËæÄ=ÇõÏ|w÷Ò„ rÅÒ¹ìíóYÝ¿­×64φTVVæ:vì¸ÕðI“&åòWí¹õë××˜×øñãsùËŸÔJžçG‘{á…rùДëÙ³gîâ‹/εjÕ*ׯ_¿Ü›o¾™=ΟÔj,ozŸyóæeW®\™Ûwß}k,Káu©Ÿæ³³ëž¦_¼xqõ¸öíÛoõšùóçç~ðƒä:è ÜYgURù/gÿþý«Ç]wÝu¹qãÆeO:é¤Ü½÷Þ[Ò:4´œ}ûö­QžÅåRÊú%/¾øbnŸ}öÉånIëWß<Ú~¥l£ºÆ5´~»s;ÍߟùNî²kûäþñöcsO¿~w®rãšÜu“¿UcšóÉ}ýî±5†óë¶5žo©Úœ÷Û·Ï-Ÿ¾ñàܲŠùÙ㊠+sûã~ÕÓ}òúA¹[§ý0÷ú²¹M[6l5Ïɯߓ½~ñš7ê\ÞÚï›|üûç–®}+{¼d훹O\@é ãRÿ×,©\æÎ}m»º”}m PºÚMµ&íڵˮÐÓ•q±t•|ùå—ÇM7Ý”MS,µ ¹ð c¿ýö+yžéXšþË_þrVkô¥/})¶lÙ’K·"ò'Ûìq¡_n™¤×åÃRv¥öíŽÂô½{÷Îjtvźï½÷ÞY?5®ïvWávTUUUIïY¼œÅ·^Ò-¸‡~8ò¡*ò1N=õÔ’·a}˙ʡ¸<‹ß¯”õ›A¦O#­\¹2{m µ×£ðºÔ/œ„·¥¡ålȽ÷ÞãÆ‹aÆe ¸S[—4¬Å˙ڗ¤¶Pi¹Sããún»¤²ÚžòiþÅåYj¹dU©wÝ•Ý"üíoŸüä'wúoo[Û¯¾¿Ï†ÆíÌúíÌvš¿ó/Ùm¦Ô¶çgOˆëÿva\6âÝÛDõµý©íù“â½Gd÷êØ7»Åuç§+ãÎϬÏúö_=õÆøÝ¥sâkcoÎÚç»zÜÓÙm±™‹žªûb<ÿ/5Ï]Ûï•Yo_॰խC¯ã ãVåûiÚf€R;ŽI“&ÕVYY™ðS0ùþ÷¿_cÜßýÝßŧ>õ©8öØcëœ_jsã7Æ¾ð…¢¡y¦Z€ÔøøÇ?þqö °Ÿþô§ÕãÒ󫮺*V­Z?ùÉOj¼.}@j7²bÅŠ¬ÍÇÇ?þñãÓôéu©QjÀ[І–³!©=˹瞛5šþÑ~Trû˜ÚËY»V%Õ>¤ÆÕ)\ÕW»òì³Ï–ü^cÇŽ­~¿TÞéy)~ö³ŸÅßÿýßg¡î¬³ÎÚ%{ÛÚ~õý}64®”õ«¯áþÎl€mÕþ¤šŸgÞ¸7þç©/ÇyC¿œ ;~ÐyqíäoÄÚ +bÉÚ7ã§|ºzúÿœxIÌ]þ|l®Ú•›VGÇwÚøôî²|yÌuñÿÿb~Þ[_°w͇›ÙK¦ÔvTÿSãÎWgËrÇô«â¨~5k´ ãîšñÓ8ºÿ黯°JmT^»Ûm€n»í¶¬ÝMñkS›‡Þ½{çzôè‘ËŸøjŒkh9Šßyç¹~ô£%ÍóòË/Ï}þóŸ¯sù.\˜=zt®S§N¹+¯¼²Æë***rŸýìgsù«õÜ€r×\sMeÉŸ\³×åO^ÕíP¶µÛZ÷íiCTjÛ“+®¸"[δž‹-ª1þæ›oÎuèÐ!·nݺ:_Ÿ‡¹nݺ•¼œ ,È3&×¹s笟ž—òºúþóáe»Ú˜•ºýúûlh\Cë·­vS;³€–­®¶?ÅmkRwñï{å¾yÏi¹çÞz°zÜúM¹ÿûèçsùC߬ÍÏÄY×V{ìÕ[rŸ¿ypî‚ÿéšûÇÛ˽°à±:Û÷<õúøÜÕ}b«÷½kúOóï¹wi—W,Ì}ëO§ç.º¦gÖOÏ‹çùû§¯Ì]ô»¹oÜ36·rÝâÝÖ¨,ýW|…Z|eš¾w¥øË듾 :µ¹y÷eÓû¾ yóæÅÑGßþö·³Z€ô]@-Ŷna]ýõ‘?ùf·Ÿ°€Æ)â’áßÚæí¯Æ,} ¾øc¥ÚÞß›5ë•· µØŽ„—ý&èÆ$µISãç¯|å+Ù­ôe{©=PS°»Ê?݆ûÍo~SçW °çØÀ¶üàìûÂv(/\yn«k Ž<òÈì‹õÒ§®žþùê+ò¦Ðí.éSS©R£sÞ;¶À®Õº”?øØ¼5´íýÞ•í°§ìÈí¯U®¸€–F @€ @€ @Ø1Õ¿ï߀€r¹œ’Z ·À@€ @€ @€ @€ h­€Ý)—Ë)Zœ²²2… -=ðA´´ðSûo^ €€z ÏëëCs >õõ‹ÿö…!hfá'=.;UUU5ž B4÷àSü¸¼¼¼:ü+6oÞ¼U‚æ€ ¦uëÖѾ}ûèÞ½{ôéÓ':uꔡԇ%!Hšxø)šBøÙ²eKÌ™3'žþù6lX ><;)8ØÓRö‹öçÎ'NŒ#Ž8" ­Zµª®*tB4ƒƒ~ ?›6mŠ^x!V­ZçŸ~†ÒðT-E :ûï¿||ðÁ¬64¡6mÚT‡ ÁvRÀŽžâà“ºtÕ›j~Ò-¯“O>96lØ Kã %)ì7nŒÑ£GÇŠ+²}£°?Ôn‡4Á ”ºTÓ³fÍšì¶W ?éÀö\uJûFÚGÒ¾¢œ4ƒðSh÷3oÞ¼:thv xWÚ'óçϯ¾-, @@ >…~!ü¤ªýTÍß¿u0`@,_¾<ÛWŠCPñ>…4T|û+ÔSCÏôI`ké“i) â}hb!¨¸tjô Ô¯øƒÅ5@@@ ?µo¾è¨[a?ÑHšQJP¿Â~"ü@@ =u…J @µC0$M0 B/<„†ï+B4ÑðS‚ A¨±:þäS²®¾çME)ËÝT×­¥ Ú5>B4ÁT~võ¼¾yc9ÁûðÅÙrÌ~õÕìùºuë⤱§Å‰§žk+*²a/¿òJ6MšŠ÷5@ï=?† ì’ ÔÒ5dHÜwÿĘ2í¹8èÀcò³ÏƦMoîéÉÏĘÑ'ÇÔçþZ=-¥…Þ†<ñðƒ{l9† >2þãûÿÝ»wφ­Z½:¾þíïÄ´ü6Ý™å|  ™„Ÿºïée¸ûO÷Æ-·ß‘ýÔ@ïÞ½ã‚qŠó>tnÉ¿º]•ŸÇíwÞ•u -Œ}zïç{NœÞ¸(¯gCÎÐÔiÓâÜ?ñTìµ×^ٸǟ|2 @Óž{®zÚíy¯º‚@]'Ýô‘êŸÿ÷/㾉cõê5þ w‘Óg<—ÿÓ?ÇϯúIöwôþù+ñÊìÙ±ÿ~û5éý…w¹ìÒ ´§Ý1þîøÿ$>èÀ¸ë¶[bôI'ÆO~ú³¸ëî{JžÇ­·ÝWå_3ò˜1þÖ[bäˆáqõÏ·åCU}†¾S«3í¯Ó³†­O>ýtܱY÷äSOgáä¹é3jL»½ïuÖgÄ„?Ý]oî¿! ~gœvZL¸g|\˜QÍAZßânO»úGÿýûõWç¼–… Ô¥ð³oŸ>qÕÿ£Éî+@@ ?…6?õµý¹õàðÉýmtîÔ).ýðEÙó[n¿}»BT’^Û¹sç¸ôâgÏo¿k|µûG÷nÝbíÚµq×=Šå+VĨcF—Ý.¹3ÀÒ¯wëÚ5Ø¿z¯Ï}æSÙ:ÕçÏ÷M¨s^ìœÞ{ï¿ø¯««CÐìWçDŸ}ö‰Ÿ]õã,5å ÞåÐèkj¢bóæÏÏú]öÑÃß|k^Éï±pÑ¢¬ß³Gwú=³þ¢Å‹|ÝÁƒãÑI“âw¿¿6û­§T›“n—´iÓ&~wíª§)¾·=ïU¸¥VŸ%K—Ö9/v^›Öm¢]»vï>ÏoÓvmÛ)˜fD ФíÝ«WÖ¿ëÖ›kÜ6ytâ„íºâOR-ÎÛýåY?µÏiÈÐ!ƒ«_—wìØ1:tèÃŽ+W®ÌÆ5dð.y¯†Ö½ö¼Ø9Ë–//|é³ÚŸÔæ'uo¾õVv+,CxÏ]tþyYÿçÿý«X¹jUöqô'Ÿž_úÊ%ÏãÌ3NÏú7üïÍÙGØo¸é³çãÎù`ƒ¯6ôݶ=Ç{lõãŽ;®($ Ù%ïU—3N[ç¼¶× £Ç4ØíiÛºí¹»ýóW¯Œ×çÎÍ‚Ï/þ몬Kç¾ñFüÓ_³Ó5nM;]p~ôèÑ#nºå–¸ðÒ˲aCŽ<2.½è¢’çñ‘K.ÎÚe¤65©ñô>½{ÇÿùÂçã‚wÂU}9øà¬Æ§²²2FW€FÊ6·oß.=äà]ò^uùÛË.ËB_š×Í·Þ¶Ãe¨MJMéû›>è ¬Áó^=ß¾­˜BP ?©14ÍCÙ„ rcÇŽU@I'ÊÔ¥O=mÚ´)Ö¯_YcßÇ<.½ôR…õ¸á†â„Nˆ.]ºD§Nò¹}Ö¶¨U«VY;±R¿¶­½ñÆëÛ5ý¬Y¯¸´< @€ @@³çËôÀ>"@‡ßv™ôТ¤€€eÍšU €€–åÞ{ïVPöí»(hŽ>üáËÔã®»Æ+„FħÀ@€ @€ @€ @€@€ @€ @€ @€@€ @€ @€ @€@€ @€ @€ @€@€ @€ @€ @€@€ @€ @€ @€ @€ @€ @€ @€ @€ @€ @€ @€ @€ @€ @€ @€€Ý¥¬¬L!€}F€ @€ @€ @€ @€ @€ @€ @€ @€ @€ @€ @€ @€€–¥¬¬L!€}D€ @€ @€H€Ð0?òöhqóÔw`‡mï/Åû Д"ååÙÁ<õûŠ´ˆ«ÙÔµjÕÊAJ@i_)Þwxï´VÀކŸÂ=u­[·ŽñãïŽÊÊÊX¿~}lܸ16mÚ[¶l‰ªªªìu¹\NáѬ÷‹â Ó¦M›hÛ¶m´oß>:tèu…ý¥P$ @@<ØèGŽë֭˺‚6lØ Í›7gHø¡%íé‚ ííڵ˂OÇŽ³. +@@@:À×®Jût¥[:ix:Ч𣈖´o$µ÷‹‚R-Pzœ†Õ®„   à !¦v Pax!ün¥.~hI…[]…Û`… T_ $Mè _€ à Uÿ…šŸB­DKÛ7Š÷Â~Q; >ЄPaXzœn{¥ƒ|qøI ZʾQ臠­/ w¿t¬YµjuT¬«ÌžwêÔ1ºuí²UY @ÀNè ë->ЫùÁþQ³&¨v'üì>«V¯‰ÕkÖV?_žtïÖUvîÀžBMñÁ»ø Þ ¡GøÁ¾R¶Í®øb‚]£¢b]à `—† â†ÑÅ¡Gøº.FãçÝ+µ?,e˜ìTª}| þ ´­aì9°KêµÃPZBØö¿^@€ @€ @€ @€@€ @€ @€ @€43­Zµ*i˜4:u,iXkE4ݺvÉúëªÃOa˜4Keeeѽ[׬kHyš %…$hq¨uúïþû着ªê.—Ëe@S;YOyyu—>VVQQ‘…ž-[¶¤þ©©Ë‡ŸA©+¼¸ø1@#=sЧ.|&¦.…Ÿ‚Ê*++·ªýI!HðšCJÁ§v-Ðÿ>™×€IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/images/start_macos.png0000664000000000000000000003317515074673150017601 0ustar00rootroot‰PNG  IHDRð*ek•ø pHYsÄÄ•+tIMEá 4Ï U5bKGDÿÿÿ ½§“6 IDATxÚí \×ïÞ’Â0Æ€]Lmˆ_¯c;~äÝ6ù´MÒM“m¼ÛÚm¶›4Ý»×M6IÛ$MÚ¤ÛÆÙÞ6nwoÒÖI·MÛOÒÛÆIc›ÄŽk(~pÚØlƒ ô–î‘„ÍŒF/ÄïûqÈÌèŒæ¡3ßùÏΜ‘LLLx<§Ói³Ùìv;p»Ýt !Äëõ²þr°†ƒá› ‰Dvz`˜5üW*•Êd2…B¡R©Ôj5 S$ãããÔã“““´Pff¦V«…ˆ %N 4"§§ÆÎÈÈ f—ÓœNR*•¹¹¹t*Åž€”€Ææfxx˜jœFèR›ÍFMŸ““È´H ¨´©º©À©Æ©Ì¥v»]§ÓAåºZ§§2—:&oRúçÄ)€… Õ8•¹kn¹Òü7OÙº}D…#šk.™éësËY¹‹suⵌ Y\D:³‰*;7K-¼÷<æáÁ 6ߨgftÛÆz¯ L8Ý*}^Q¡Q%Å•ÂN— ´P¤12µ*ÈÈÈ„~J?ÌGùùù|ñò|Í»p g8Û¤¥ÿ\ã¨éª2ï#tÊ@ÏùÉÑÁ¬ÒõN§+Užº-WêF붯Òù<â¥×b/0â#t¯ÇåôD\8¢¹æ ó•³ýº‚’ÇÕ¶3]C+6Ô”èF/·t Í*¦«ØPWšÅ¿‘ö+Ç:zi¹[ýBw[úêÚ1––)/v4_¼R¶¹®L5¦ìõºÐ- µµª×O`z9O}JƒeZ '''©æ] ?Ý?æ‘/w49Ý’Üò:>Ó·ß²r†»šíçNd¬ôxò˜=–äÛâ_Aû¬*(‘ù·‘ÄiÝ%Ê“Â?¹cä¯ý•Vûd×yèô¹.KqMqÍÎâ@‘Ñ®£';Ë ø/,¼ÖÎÃÇ»ˆ¡À`ê'R îºÐF ×®-UKHyaþé÷Ït®0ª!Çôº\.gÊ]ºtéСCtxçÎË–-£‡ýHXÊyY‹Hè¼ zJë?ßñ¬T·¸péJ©„t^¸H¼¤´tIaeÝ`wûx÷© ™=«`9ëv·uðÜñÇú-«²•ÄcüËñ–’çèø³cÉÆùþ’nóÙúÆ“4èûà‚«t‘ãÌÙ.:j,«®*Ë—Mô9Ñ»vóÚ•_á#]ÇN;>ö±Œ¿ü¥ƒŽ69TPY»ªÐ_Ý6rålù~ßœ¥µUåz…¯¼uäJÛé“ïë +ÖT•äjˆÇÒþ—˹åú‹Íq¬¨YY¢‘±\.'®ñžö†s½¾+ׯ*ÎVùãÔ± M]þض¤jÃòÂ,>Ùs,wvŽˆ®Cþʼ+M;/3”nX]®w„néÆí+´1¤2¬#RTCmN/ª%Òœò­u‹ªY+íè;ÙIJÖä©§ò(vQ)™Ýá´;d*¥”x]NCIÝš²þæþž©¹,CÄX™§ö•DmXl$m}#åÆBÜ~IQ¡K„n·Û©=™Ôæ~­ûNr9s»2ì¼,5'tÞ…i™»Ú{¾USPU´¼F§ÓËe²¾AS߉ÐQ:‘~D XǯÒÂÁójò—–éúO¶÷{ˆ£ëx‹¥¨¦@›aÈÕõ´ 9ül#ö“‚ìŒgièÜ™.²~㦠5C[NuŽHµÙ¥Ätyh‚ÑÍðejŸ\½.meáªõµþ3 ]pϹ¡¼õukkІºÿ6äñe®?Ý¡ª¨ÞxíÆš Õ¹3Ç/ŽÐ àuXz[šGËk7Ö­¯RôŸkë5³WD*³tµMè×lÚT[Uâì8ÙavûÕóÇšºdt!tõzÚšþÚoå>3q/wÖD×áLÓÚÚMukJœ]MGÏÛ38¶4#¶Ä´Ûå :…©§ýБ#G:ÔÒíUk’àþJ'!5Ks˜i¶¡ ÇŽÖ÷[èÖ:ûξwìtŸÛ·7ô+×­ÐI‰Û¨Rzµz¼Ai'ZÃÐ^*M#t¾y°ãæz>“©õòü•ÅËä …L*#jõªå%^_C µL.WK%ô£n§GªÒ3:A¨ÊÖ¬œN'- f^ÒïLâæ]dggçä)U*‰DJ÷B©*YV´‹äôgÊÎɣŸvnîªÊ‚†Žþ’5¥Úé íJ¡e~‘«ÍDVUe…Ú“¦ðkdذm]ÖŒ3¨6 ÙMv.!“î’¬übÒqfÔ¾,küC )3ê¦råþš8}ýAÏXÓsÔz±P¹8Ç-†Â¬iËH³ŒFKÛ¸³Ô@ KÉÔT™\C¬.ÖíT¯‡è Ú©Ú#W‚>j>^´ú.7ÇFñ,·,[Áº øO¡1Ò`ÙåÖqmi,»Ôë[Aã†UÌùJµ¼jUÏñ³f[…Fã[¶}øòEBÖ,É Î6e•uôöZHiM‰^Á_—J×®W^è8{ºË—1ªZUAÎö{âvW$•Ðu:Ýøø8+Õè²eËvïÞ°*sퟙ™)f^V<¡ó.¨¯õz½¯g5ÿ?Óñ“黈†M_¦½’©\Wïc]¾uÏ™ž%;*ü!žÂ¸¼¤ãÌàÜNCÞ\MÐ\2ýº;£XAB†ìžR¥ÿ›l㣄è}ád†UFry`Èfê5VmTÍÎvrÊ'SYºsCfO ÓÌÎk"E…ò\!\ìᜤ[¿µnJÌ^Ûë»kc¹\"ÔR—cˆjÑøòoiT»Té»2ÆÞŒ©M³]>ÓEJ׿-Æë4Ÿ¯±×XQ³ÈÕÜü>©ÙXaä|xÐ;1j’d-­ÛYÁŒö7·‘œ9Ô˜–9t*VzÍîp8¨I}úðà øI’Ëid›wà»7F$æëìôß”ýð<^àî;ÛÔo¨Ú¶cS é:~a˜ùíU†Âr±¹­·¤z‘">+hjüÛ‹Íníïhëו1·Ý¤9K+LçZÎ –äi§OÒÔ–¦±ñ SAuf1µ]ìµ;ìcý—Îö“²Åœ·1Eå~eƒ‘XNv^™p¸Ö‘³‡Ô_4E²\g_{é‹ÃÌÂè™ ³©mÈlsØÌ]çNR”«Spni,¨rŠJˆ©é]g§Ã6v©í,!¥ÙþÛ¬¶¡ž.¢[[2«€sÒ4b\±¹¦ÔXPqíš²±«<»Fb¿zºéÄ{}f»×ãîj9;DªŠr$PcZFèLŒÃÃÓ““r?¾ºât2ÏûЃÏ×¼ ç—›=J&œŠ©Ü…ßéœ?«mèBÛaíæÅ2zɵ¡²§éLÅô‚\ª+®0ôwÊåÆå‰-Ñ•¬P 7¼ïkÁ¢+ª\³,g:e»¨„tö,Éžþ¥9FÒqòĕРu%2úKK%Aq¶ŽÑYy]5ih9ÙåŸVºªv™¯™Ž}va9Q°#Kn1Éô«6Öœ=Ñ|¢—Y½›Êr‚ Kf4ʵ\b³YLº©NIݾ6²æÆ÷ýck6­`R<¡[ÍòÍëÇN2ëLWzíµeþ¦…¶¾æCÅúœÙKQf•ÔÕLŸ–rËÖå²/*ˆbj¿å”o®ržik<Öæ­X³©P‹tK kAÒØØ¸zõjBxô? éïïÏÊžÊ ÿ±QëÛECªìM_f&Žš DŸóJó{Êš+±GgnKOýYéöºb‰ÇíñJd² AÛ‡ŽÉ_¿¥, Ïy½_^É—iŠÏUŽÛí•Hea¿N`¹ó©#‹6n/ÖJÜnT&“ÄeKy×Ämw¸%R‰B¡ˆoíq;éÎ r¥÷CS™ÖÖÖðé2*Ð?Q,`¾æM{4MKóÓaìÆžéx¶gzbee¥ØƒÙß ÝBHõµ¹ñÑ„×E,Rº*¤³:°ôµ7´õ]ÅÚèÇÜŽR‘]#,×ëqúnêø¶5¸£…X·”wMd*UBÂg©ŒþV8ªÒICCCuu5vĽLsL˜Ìv¥6K§ŽÓ1íqXD­V²,蜷}v–2}Â@Íê©Õ¬€9·¤---r´+_è§t¥6'7®ý'K•®GÇÚ¬Ütë§YªæÚÔtÜR Á™p+©$tìH|)—£GbG@J£×ë}B¿ñƱ/ˆñj;aÞIíN’¹øÃþPTT´lÙ2©TÊ´äžœœ¤ÃJ¥R¥R1o‰Édn·{bbâÒ¥K¸) ì¼p¸$?¨Õj…Â×(–Š›ÓÜl6S§«¦¡ŸR¿S¡3½Ò¢Û€ã ¤I°¡è€ðµeÞÿùÏžy[Ç¥ÓÐàýÀ23ÍíÇ?hn=ÝjrE½ÜÈf·™Í&“9†’®îŽnWb÷dŒ;$ÆïtuŸ>Fi<}Áf"à8,`o€”¨KA*Žx g5[¼óÎ;ýªi«^W}Öµ©DÏnk½W"ÑdfæädJ¶?ÙÊouWß‘™’·?Ù1«¤éWßþÕ`<÷§íÈ Oþþ‚9š-JÄ^"®æ?øÆ–-uëþh3°½y?òA¢I¿ 6åa.n½õÖo¼qÇŽ7ÜpÃM7ÝtË-·° p=X¤Pl#Û²£îwÏ?»VÔì¹»íly¸þñ{^:ÍWÎ:ÜŸñÄ+í½#ã½ »ßxü®é’}/×Hò÷Ø[$‘<ôjG¼vèÙïSDµE‰ØKêO>¶ÿOí/ÎNqN„Çã|˜¥bð£ÏËo4Ç?z`YœËå}°(“Ô?¶ëv?ä{Žõ1×ô¶·žd¦HhŒÜ:݃4Uêö©©ÛsÁ˜}ÿ¿ÝëŸxï[ø#Huáö›6/5èõÆÕŸùnu˘“¯ ~õÝû»»²Ð /¬ýʾm-G:|Kruì­ÛuCþÝO4´7ÜXÎÿÖ [Ç#Û·ß{¯ýkjòmQß‘gkî}yj;̧÷Hn«Ïen}µF¢y½»nÙ^#Ùór«ÀÍlûíÏN]4øtû#ˆØvžï4uüž™D×óXßÌK¬“¯Q ȱJ±íâq¨§xU¡„®ö›o¾ù§?ýéðáÃï¼óÎÛo¿}ðàAv„Î7çøê¬Þñ£ûÎo¹ùGÌA^tÝýãV¯×z°êñê~ã—ù7u»jvÑÍìüÞG‚âÍóËv[#¯í>pó«m‚é„îý<ôн5ëö¶¼vG•ˆtHdzÖïþÇMþ4œ~e9HFþŠÊÚ›j ùg›l«¯ïõoÑáÏ5×ÝõßtÆÂ [sì:è? u¿½ÿ'd{m¡\¿òSïw>AÈ?øé›ï|çÓ+y·Ètìæº]7îtZ_Y´wåý¿qM-è†lqÛÎõ×­¼mõaßþlÙ;¹¥è…¡™ˆž3ÌŸ=ʽJ1í”8,c?ž!8¯Š‘ÐuË-·\ýõÛ·oß¹sç 7ÜpóÍ7‹H¹P›ò¿wmWýÆÛî'-¯Ÿó‰S©¼üÜýŸÝ~ûg_l ¤w˜ §3o#Ïï}ôÙ—sѹdu¡zzöêGïݬ–¶Þõ0©o§s·¾¼G2›ý§ý6–gnØù‰m·ýS5!§Ïõ†Ûœ¾gkWØýÚ÷>¹Ô?ïê}G_:X·åÁç¿”#¹ýåÆn9}«ôEßmùôHý¯ÚèÂõµßz˜|"üù?ùêáÏøú—«õúüüj¢ÊÎWë ½œo‹Ì—δ‡ïÙ^.W?õЋäÀñÞ™Í*)´JßIÞzáÑÛo¿ýÙ_Ó½üʬ(›³OÌ ‰|«ÓI#•Çr "U½0îQÏ;/‚@;ôj-ó‰bªCgÛ…—Kë~ðJÃï¯Ê¿ôÛûßøs±¯¿ïõñuÇŽ·žy»nå»_iß7Ó w.3»ÚX@êÇiœ¸òÓOõÞðàhrôþÿÖnß¾–lßxøRþŽßÿ›·Ò/[wÇùq’QZY®Ÿ™£ûÙšÒ½u¯ïÿL`âÒÍ÷½î½mÿžŸ.¿K½£îÁuÖ×W«ù³Ö!S6îy”¾ðÖ'n~œìîÜ2àÓmS³K³·È?¦ *5érq—¸…ò4:~â¥_|5ÃFä/üB®Ú~Ò2F§êYßÁž²Jr¾ýÁI6•'¨0AÓÆ€sNÓ$1x^‘MC_s{Ê%´Ùbp9Oz·å'o´n¾ouû»¯²­LOœç ¹õºÚrƒ«ïׯ ¹×Ny¾u°tóM«7ïÔýõùÛ®Œíçú6º ¹ÞX¨IŸ µ6]μ¦ºHã|ïÿ=O¶½4•³17ïZYWOªÆ›kõSËy¶¶boî¾®ï}œ˜L&¹Æ WÓ‰¯þ®ûúO”Û3ÔÙZ•ðŽ˜Ù¢Æƒ„Ü´Âÿµò¥7¾rÏ7ïxã¶[Êgö„¢°šü¨¾m÷êuróþ;Ž-Ò¬ äæ?¶~å¾Õš?ÿþGdÛCErÿ›ŠCJŠÄÿ4Þ¾ù­ó_Ú³Öè² µ4TÕV2ß /­­&uït|åÎR\=uÖbMä^%ÎýÙIg•Çhpœ’“HÊúÃΑ©ã¥õŸýìgô«BŸ ›CWУûÀ®jºÕŸky­ý«FêŽêOwÛ3Et’¢è ¾šLÝ€t{¬"Ó—AQÜö“ÝGï©áŠõùU;|j˺ÒLºFš¢;žß}ø¥ÏN‰J‘QäŸ3°¦æ¶C{[©°4S“™““sÛÏ|©¹ÆÜôB~féƒÏ?¸®îà+§~*ž“™-ê}£óËÓÉýõ»¦ zàSÁ/áSoýÊKäÁ:Dñ™æÛ"yáMí¯=¼«:G"ÑìØ[}ôÀ=ꈶç;»ŽîûÒº|ßÕä¯û¿§gnëk~øâîÏ­ÌQh>ÛhæžÈ»J!û3Â’J –°Èâ¯ÁÑ %mRá‘þv"KFT ¢«0N§3ðX?¥‡ÕjµÙlv»Ýá‡yU§äÝwßݺu+ñ·f'³›@šM&¢¤‘ýSÌfj{ýluÙlf«•UP<.›ÍE×O¯×GûÛ™^Øó‹¿ßÿ€Q ˆíôvÍß³¾^å4A´¢§_ؾîÈ?X_¿OM¢[{³ÙJü× ñÃe3™F­–'j•¶Cæ10{ˆ&"Ö†ÓÓ#B9—p‘ [,XÅuÎuþüù™Î¹B[³ë ì»bœÚU«õêè~9Õ–Z‹=äkn]£wš«'oL8‰Z´E¶Ö=šêŸòRËêè×^oˆ»ùäjƒ!–*b•¶CæÅæÂ1T‚¾$y„…UÃ&^f“®.¬b—ËÕÙÙ922BãqøÒ©-©Ä cs¦ë.*tZÀ÷Íõõõ×]w]ºÿ¾¶î 9åKgŸŽÌÝ9E…õ«ð)°Cbn¤Ó#r7,Ÿ®Ñº@I¾"i™ììl¦e çìÚh6›}ï ýŠÿüÏÿ ø/ÿò/©ü›ª—–/ ™¨_Z®_¨•<ÙwHÔÎé õ;\ŸäÖøQXs ´cá‹Íù¢r1ÑzØP=š tΩ,}s*€¤²¹È‰šN›:Ãij.ùäÎij­Ï±ÓÑH¥#3jkÇÅì{Ä °ÇCÃs΀="×'Èé:H+›‡7bö¨ò°ÏEäqa‰s ZØÚqt:„RÀæQ¨<¢Qñ¢‡ÖÓCåLÎf-¡rg™=¬è£Õãåt¤žÍ…§ð¹;t R•£#äÌ¢ˆÙùbî[ ‡Û€€ÇÅd`êt¤¶ÍùT¬oÏ4|Z«øH •'‰ÖÖdM V9ýè>…3~æÓtB¡ƒTµyØHœâv»].—ÝÓé h= §ãA¤T7;_Sna›T®P(˜îSär9Ó%Kå"#÷„:B)osÀÜápLLLÐ#P¯×³ú¥ "hp`³ÙÌf³V«U*•Tñ,• x|Μ¡ƒ°¹˜4 k€þ¥!9µ¹Z­¦‡=™NްÛAtW4  A: h¥¢£ÔéBuá2qwºU$¹è#ºÉ°9 Ïív;=ü˜ìUc¤‰†LÊ…©ZL¡óù=ìhì+‰$WxÅ=OÎÓ£N£ÑX­Vìm/襽æcþR¡3Fæ4¸˜TŒ€Ó£s=„RÞæœNgèô×  ¾ÐXV-ZÁX6›~éôø·€µyà/ó*¤ eê‡$ Þ¦3äâßxY¹dÃo]$ßv+<Ö>éÐ!ïÕ÷‰Åÿ‚o]•$ïZq§TþÕ}ýöþ÷Fßmm8gý]¡ùH]vÝÖìë T¨É­T—N0SB%>_N—}þóŸ_¶lYð¤Z.ð+‚y?ÜÿdMdln±X¸_!ÈÐÖA¼šÓp"×ëÊÎÍÎÊÒé'ÌòÖVëÅ.Iž‘ó„Viìé…}†‰?äi­†<}v¶&S:,;a7uz5…µ—ÏZZ÷÷íÓuج·«™ ƒöªl´iòT×XçbeA¾r‘à®p^ø É¢ÎÍšyw¬§§¥éŠ]•Ÿ•Á9ËXOÓ½_ø?›nÝ’ázôïwéên,Î Ó=²Ç5~êý“^âL•<0êÊ42 õ¸&μßäœ&°ôLå¬&FæÞ“÷üÓ·|r«N.MÅ:ét:µZ-Ónгí#« »ðç(ÃÄÄ„F£è>7½h ÉÃsa¿‡æÁxxp÷x~û»Åý½º‚ER–Heô £t"ýÈW€×Äré§‹íúüERM‘Èè?:@GéDú-À7oŸµïçþü¬æ¢!‘F«“Iäô £t"ýˆðáúÓSÏu Zf6Ämû[ß}¹¡[`Çä/é¤ÿ³M7ÆZ†Ãòʾï¿ÛÑÏŒŽvŸyfß÷_=ÔÎŒÚF»¿½ïû½c6(¦–Ξê[ “Ýéö¤&œ/´ã /D qy>BIgù(,|q:’††Ü®‹Š¬,Zøç Љô#_*†éСÏŠÌ,âñÏâñÿó xéDú‘/ÃÃ{£ï~ k×ÑåÒòn/qÿ?ß÷Љô#Z@xÍUYrOÑ,Q•roü*sv®É>ÞtžI+tµž¦[7[üy†‘î6¯÷£eÚ辜IVȤþ$ƒ7µ_Il(ÇšC`ÎÂóxÙœ/Tç\ÉÉ2h`ÎH|¦ ‰—~4|òïÇoåžwø¸V§›±93;½þ•úœ®Õꆇ{‹ï᜷q¬Q­elîõÌ,VBÿ“IÔÚÆÑÆ;Œw ì@æ|´+$²™Ë‘ɯÿìù_¡Ó‹×}ú±ïÈÑÈ8Md7õü÷÷¿Yßá{ÝøÖO?øwþ]†48¶“Wí¼î¿¾{bü‹[ôÄÚøÆ :ËdwC¿ù³e™Šs'g¯¹Õ —ºÝ'^õù_¾MgÐWnûæ×v•4c=MOÿ×ÉÚró/ÿÐtÿÓ/®UÍ,trøÂ÷¿þXó¨S‘]ó…;?BÏM©û¢m¾ÚÈžsfÒÃ&ÖIT5Bè Œ»Í…Bž‹¤%‹§có )û/‘jÔ´ï¼–6i^î”ÿe¼¾©˜¥jéoã›÷œõo‹óý…™¹üR—H™¯RjTç>ü›ðEºR/èÑ»œnÛËdKw÷$³Í§þç™ünø_¿õì²LÛ‹=öà¿Û_|îžP›»Ãÿñůµ—lyúwIÇÎ?ñç;LŽ}_Úlô¼e×x½¿í795Šþ·Mޝ?÷?ýÛ×ÛºG–V©ÿrèÃëöVQ9ô-®çþGŸ^µHö?Ï}ãk_¼üüËßÒyÝÚ¨?ñÔ3ßÍ+Ð{‡ zvÏÞ %[¾ýØî¡–Çžù)!%©+ôàZ¬ï¸8:H“ðòæÅKHð¼é¯Dæñ¤djçdä=žþ ‡+Gì ]íÍ‹ß:Õ®%^|óM:B>²é–¾oþ¹³ö£ÏÇ 2ån«sÒã)ÌÕN­­\•7½Yf…ÖÿíþÕ ÜEœµÐì¢ ç˜À”äT.­ Ø9^OBè IEuŽEL„î^³zòàANç+‘L%^#eɤe½y ï¼Ùuãíz­Ö—F§BöJ¦LˆT21a¡øæ]¯[ß>ùk ]®Ìw*,–ŽÒ¿¶É Z@8B§0‘Ÿê¤J½/Q.Q(õ^ï½ÿþÂ'®YÌ8Çnw+TróÕ–?.»×kuOï»ÙĹ¯*ê>Ñöè¾6BîúúQÖÒ•K¼?}ìÉ+?µW/‘¸J£×;0<á]’éÛ'NÛ€×ëò‰Ãä |ßBÇ?ìJËzÔ˜xV.`î²b¢uá¨\8µ"¾Ù¢sýúÁ%Kcc‰èDßGë×óÍë0\7ä]í£úöKÜÿÏos:‘~D ðÍ»IwíjÇ ].#qñÿó}H?¢¢kHG¤úmÌyùÉ}g{†&-¦7üõ»ï~êªÝh<@“WZìéÿÖó¿îè9ûÜ#ûs6~<_-e}afA¹?è.ÿH‘žþOªÎÛrMØrÍ’ Å=ûÁ¥¾±‘¾7~üD¿§¸þÕ=Lvç±ï?+—ŽùÊÕ qKiH¬Jå…ßüá“Oÿó£_ùÂoi¹¥×ÞýÌ—wÊCö¹4#gÓõÑ%[r”RÿGÊk®¿ág§þ\±8kzqß™ O<ñ¯_a÷Ä { 3ä£t ³¤³#tßÒåŠâ§þãÑÿÚ“þ…æßù÷7üú—™v‹i¡žþ¹Äô ûRÉ‘#G¶mÛ¿€9Ë• ]dšEŒÊívûàà B!ô4£äê°¼©IþÁYi×%Ÿ”K—¹®YåÚ°Á›—~«ìýŠ‘zùX£t²Ã7oF¥+«Ö™³ˆx|Ð9ø¾ùØ©‰Söó¾ä†jù:íºkõ›©ÍcßÛn§Óå!*UøÇ8}oü R•Bãâ<ôC¡w±ïq:ÝD*WÈ$)]¥é®ËÏÏW©T’³†YDÄ¥ÌðÀÀ@vvv𓢬À!c6››››!t0BÂæ|ç Ì¡:­ Ž8>¡ó9ÏæÂN§u8"¡#åæ!<Âþ¬<ƒ°Íƒsèø À|¥\HÈ»F#zuߢÊCè ¹’-¡A:áJ³Ž+ØÌ%¬f‹œN®ºœ]¥ó5U }Ï‘x§Cè IO|wAÃz<`s8$®¢2,lÉÐw\„ÚOŠ‚tÎÆ„Fë*'<­™îînìgw ˜j&•Jò-ZV9,)Ÿ„á Ïù’-œ%C©«CWþ þ\ºÔ%ðô?çƒûD0Ÿ.ðœQDr‡ÐAr)^8o.БiЈ¹Ò†Ö1ÎØ\8ñBâýÚh$W¾…ð÷)H ƒü°¨˜*¬u›ÇžuÐÁ\§VÊ ¼mN8J~s¡‡¦_„M-¾_ÎÆŽœ‹€ÐA Ä鲿ëjB‰«·. ×íÅæ:Hóu]cx¡ƒ9‹Ð9¯)Å(›³/ưõB)©{1wA9csäÐAâ®cLËÅà¶+¬˜/H'qm΀îsÁ¼eW¦Ç×aŸûû ±Gèœýè†ö"'\‡#=4¡ƒ”É·ˆ·§Cè`nR.¡ CÖÛ-X±9ßý̸d]¡ƒ ä#êGûÌ™Ðùjf\Bo‘ BI§r¾v,¡W©x°$ƒÐƒãñÐA9o“†vÇ—d:"t‡ _„NøýO݃äGøEt„«ï *G t0oa8ážHÀï$’§F±ÃÁÜDèQßñ €ÐÁüÔþHÏ÷ bÂs̗мéãÓQG:HŠ˜3cNx:\~/Ý\ØTÚ°7ç‰`§¡|=ÄXi!t0ÿé¾PEàÝFœ·I¡ƒyŒÐC?"ü=ÍEz,@è YLËe&ŸÍ9åÎyDP¡sÆìÕ5¡Ç„æÚæ‘ÎË—=N “x·ð 4=öF¨§ÇñÐÁÜÙ\LÅȨð)>4n"Þ‰ Šð·¬®´‘†â+$Ýi€/Ã(|s 9t0/)—°MܯÔ9„ÒÁþ `s07A:çÕa ¡ƒÔ³3_½ÓTQ nÂs¡ ÂÏŽŠ? tì!¶ÈËOá7`4 ÃÞ‰D„ïÆ‹|y‹ÈƒB©äw¾ö^bfá  °{AB#ô(*'lú‚‹@:ÇéÇ€˜–‹$ÚéÂ]éFÄ›Cè 5\Ñ(‰S.1U4Ò†+qoÖ¡ƒ¹Žbb?r„À#\m{¤ƒ9Ï Ï“É56ö#Bà t,‘xt¢ç{¬6sP{…m›ûCB©݇}ënC!D^8†}tܯ\!t&á<ç@Ü»! Ò³ÉìßÑÐÁ\Yd#¬rá—ðÂé`.#tÎè[Øï$ÂF‹¬Ì:HvÝÑÁà`¾jo|ûØB„ÒÜéâçESt07çÌõÍ}å‡ÐAÊDâaû óÚ‘ÖɈ2-/‰é}õÊÙ1)á¹5 ÀÜx\LŒ¢¶#B "´4r µQ|$ŽV.`¡ØYdñ‡T’¤ÇR™£¨Æ:Hù™$µ4Š‹@ëá‹¡• HhŒ.£’è: ¡ƒÔ“µðAƒ9®À"ƒ‰9>„RÃ鑺;ÌKÕMD}†ÐÁ²? P9!t’‡Mì]^0—˜s#BévÁì`ÁÖ@,ÜC€4«Z:Hù⨷:H·c f ¼îAè Ý®mavÌOhå„Ð M€ÐAÚ†ê,´ ¡¤IÕ…Ð M€Ð¢Ò¤rBè µh NBèéV !t€ƒ €4©r:À•/iR» tH t€Ð@è t:@è t: t:„B„B¡„B¡€ÐB¡€Ð@è t€Ð@è t:@è t: tì€Ð@è t:@è t: t:„B„B¡„B¡€ÐB¡€Ð@è t€Ð@è t:@è t: t:„B„B¡„B¡€Ð@è¡€Ð@è t€Ð@è t:@è t:„:@B‘c@J`µZ»»»ÇÆÆ$IvvöÒ¥KÕj5„)Æäää_ÿúW—ËE‡©ÐM&“Ùl®ªªÊÈÈ”AÊR€žžÆæè(<B€`ll,ìDRÇv"„i„:„B„B $~°À‚ª]:H·# ;,Ø*¡T¤I%„Ю|H“: ¡D¤Iå„Ð M€Ð¢Ò¤êBè‡iR!tH tnq š¾€9«œÑÕOx îAè Ýsx ÞBèGiUµ tžGl` „ÐAêH‡ <’ÇìsŸ[‡ÐA:<ð8@å„ÐA \ºF1;üæ«ê&¢>Cè ­lÎwä°¦3£°9˜ã Zcq},Bé)}4K ­“œÁD¢p,,•Câ`ké¼kBIjêÐ2âh$OÀueŽ¢Cè %ÑÀ0´]Âóèr2ˆÐAº*ÂU?¸ß0læ2ÂY'£¨í:Há«Ô°W¦a#qx̯Ù#Ü£8(„„ޤ„ë# —(R)âhÕ T³¸WàX¾5¤däöê•Ëd2ìXhÕâK¹$´’‡?Óà·ó®lá‹ÐÐËØÀñ#ðl¡ …ÍfÞñ…V*Zµ˜ ð?ÁJ¦ Tì莤Ãù@ÀïÁ£ôxS©TýýØu ¾ÐJE«V ë§ «Ö/ÞæaÛž‹Q9üß]¤Ö£H¼ð…á ]Bs,a{ˆhK)%%%f³Ùår¦Èår:10ê{µB¡°Ùljµ5Äýð ›4ç Ò‰ˆ7 ‡3œᲞ£ÍѾeÞý.2µÓEj=¢ð\ä[¤edd|ô£íéé£S²³³©Í5 SÆétR™ËU*ÕÕ«W‹‹‹QE@Ææâ_÷Ãw„sö¡HøŸï“l‰®ù9ü÷=¢ä[¤‰—¸¼ØH8uiœN^YY¼ J5>>Ne.§±ùää$U~p.€ù2;gN_A¸š6†¾èY¸Ÿ–ØÃs‚¡ó'wñOF¤‹ ØÅßåL¹Ä¥ŸE&CeîK¹¸Ýî:)//¹0÷9ßíPήùæ ]«UKåL£FÎ÷Wð…ç$†:DǨ<¬ÊI¸²L¦›ŽãÂOq®¤ðé„çØ|»Ý><(û¿“Ÿ•U-[eÎÒÖºQûSû s˜½´ÅR¾^¼mIë¶–âå–Ò¶ÙKÝ÷™]äC_L-lêŒSÝí]¥m«f­(m_üÒÂÒö¸ñ@™m]’_Þ^7jj¿içpë=Óä?¼"–º_ÅsXÖVül¼63„̯·Þó¨g_J~©¹ýîiþ9˜÷Ÿ³´Í1fkùºùÕ;‡0¾˜Z´nk$oHíÚº³Mÿýÿþ»´]]Š©¸ñ@Ù­Sž“FóEý•ëFíOí7íT¤íýªíó‹oi0¿8Ž“s›wa|1µ¼­'’EjµéoüÍwºuØoI«µmgñ|*õW}öýÇýÓrÚ¸sLwÈÔõ†?È¿þzVì\êÔ‹yÓ¦d!“ä¿D!³©Î9¨m ÌÛ¢¨±;::,A!ç¼-n,;d\s0·-XSø ºk:‹¶uJƒújÞvÇÔ'\ûsRÛÕí k;­ûªÇسX— ãzçÆS+Ú·G*Å“R- ëK×{Ͳ÷¼©Ö…ë}Ûüc6ÊÝWÞ!†ºÜð”\`EÕ9ríÌí±s`¨»­2ïš/îQT$´µµÅ²b*f,oj¿Î9¨må€ –fqc­õÌÁŽ©…M[¥Á´Ð£°­Ó ¥'}óº~ǽOúÆð²c*îwä‹©•z#© j[ÒêZmr®N©¿î zÛû/ýâÆe*(š7ïˆ}áW°nݺXê~qc©ý©ýÄ9,jî2m“Eë¶Ébëk—eqswêú÷=¸}ñºÂXêëb5Þºâ¸Åñ¼sã‹©UwDRAÔ·c_àûM©σ¶ïëÝ[~ÿ©˜ñ@Ùí÷Î(†Ì¶Hj¥%É9S…™è±ÔþÔ~â–¬ïöè*ê–Ŧ»îûƒk_wš×—lW×Ûc4wŒÛí›C_L­Þ´3R?›/n|P¦^Ì[¶ì2_Ü{êFíOíw ÎaiKÃvÏõ‚e¾íÛË÷m-\_f].~µÓSÚf?Î;‡0¾˜jܼ+Rc*n|P¦ß÷‚´nÝ#ËÛzëFíOíw Îa™  ÖÞ¢íæõ¶í²ÜÞÞÖ[Úæ¾ßö€ÇºÙcxçÆSk:vGêoLÅÊîöŠ,XÑ.»ûêFíOí—9¸çÆSk;ö€bÑÚm2õÑW¬’zQûSûeî9„ñÅTÓ–½HÈS{/¦Öuî@B¥˜Ò4-2¦2™ À ô׿þU¶lÙ"]]]²sçNÙ½{·Ëž={J_öîÝ+ûöí“íÛ·GÆ”ê(b SÄ1@LSÄ ¦ˆ)@LEÅT__Ÿ8pÀúJL¤ˆ)K*¤FŽé *b "¦ìúÄ'>!'œp‚œþù® "¦BbÊ©Ã?\Î<óL™8q¢Lš4In»í¶RPS!1¥‚iüøñrýõ×Ë´iÓäÅ_”×^{Mòù¼¼úê«ÖíÄ@ÌÊTV¦xkbª kÊ;h5þÁå=ôˆ¹äãÇÓ3yÉg´Òuͺž“¬u]+Þ÷)ߦ;ÆÒ\׳’ó6ë +'€˜1å g¤¨8Êy&oG“îxŒ½ddú7fš˜Ê8ö4f¢˜ÊYáSÝ )=qLéVPÅÈÑã„­©@ÒKcÚ+OziŒŒg%*h»?´ ¦ýÊ”æ‰lÈêSÆq»½]wÜßÈôoÌ41¥9®Wxˆ±NºµÊ£Yq£¥ˆ)û±…Ûì˜*„Nت‘Nºu¸Î°V¬ŒÀÃa!tˆbj æË£Ä»Â£;¶iŽó” ÏW=`u)í˜öxù€Õ® s¦²Õˆ)ç!»´1U^A Ž)õXg­Pöe=à<ª°CyéB*kþŒóù"ÇÏ8gðSµ‹)=âÜ(ó •u#b•G–\ÌyN•ŒYiLi!+` c*8’’ÆTù/íÜ' »o/Çš}[á¯ûŒ˜ÒBÇàÉÀÀ<=rò¸÷ò Õ¬|ÄùLiǬ$¦ÂÞ!ÛŸ˜Š{kçc½‡ßüoP!÷_úSðÛÍ…ÐÄÔàyk½²¿–«û˜€˜P1¥œ^ˆªö˜€˜âãdÄ=z4€”;ì01bÿ†Sõ‰©lN—\¶Þ? Mô¼qö ®ˆ:õÔSå7Þ°þáà?þã¿äÿöñóo 1U«˜RA“—¼Í¨çÉÍÄR“'O–ÎÎNyèå•*´zÏ_äÙ¦M1U›˜Êæ 1rYV¦€H­H©zøåUúiî®rØ9çóo 1U›˜ÊëZʘ*F–Ã^ÑҵŸÿAqdÞß^ñÊ:£S@Ī”:´÷ð+«TÉ‹=û9‡Š˜ªÅa>@*nŒ”1å8$hRáñšž]+GSé²[…Çéö{NizÊýÃ+¦Ô?¼º@•<×sÀ:)cˆ©šœ€®"H­©C~éÏ‚¬p¸°pØP…’®ë¥Ëö×|Þó†”ÄSùË_ä÷¯5¨’gºö[Ï-þ!¦jSfäX«IaŸSÖŠ“ &]+ŒW<¼§Ù‡‰) UL©ÿ¦½¾@•<¹˜"¦ªSYÉf+©°Ãu*  1ŒâgÐ…*-ã9ôgŸ¯EL‘1õØkTÉ£[‰)bª+Söá=›®%?Ý0‚W>äW &ÇÛ-Ê>¤˜ce ˆ‰©Çg5¨’;SÄTóñ–À€‹©'ß\×/“ŸÉ÷{ $3õ¹ùrÕ-Ë?ÕëFíOíw Íá‰gÞ’ ¾r¶œö±O×ÚŸÚoÜïèÞV¦ˆ©óq2Ä0ÐcêW“ 9ê„3ä³cþMN<+'w³ ž»üº)òƼ•²±{_ݨý©ý¤9|çˆdÖ#¿—ýKëFíOí—˜"¦øl>¾˜úÃ[Í©L>WÆœu‘>j¼|âäŸÈ¿œ”“cÎ}FFžqŒ›ðsë%í˜HfÂÏî°âbÞš®ºQûSûHsP+E}«KϳÖÚŸÚoÜïèîÍÄ1U‡˜*½µÁX}*Ï…ÿi0|cʘ³>‘G_^.§}ï2ùÜIçɱçþQ>ô‘OÉgN»EŽÿ™cåØñÉ/|Y>öù±òÕë:ä³ß—QÏ’¯\$_þY“|òKäÈSNŽëQ95óE¹ÀHº=ì>Iîïv–‘Sõ˜}êçšÿÀ=šxÌø¹§Ÿg˜‹K!³­nÔþÔ~ÓÎá¶)OÊ~xE,u¿´sPQ³gÉ|Ùö‡Üž**^ð—7¸ö¥®Gm³Õ¤ö§ö÷;úíbŠ˜ªqL©• ò_åÚ˜rϾ1õÇ·Ûÿ£Ëdñ׿&#G&Ÿ9é"ùèá_—Çœ'ÿó“#¾}§d¿{¯|äSŸ‘#îù‚œ~Õ#Æš&§eŽ— ŸNº=ì>IîïqÇ̼¦•¯?}ƒaþ,ޏjviÛ䫎w]O&j.Ì3ÄÅÿq—´›a‘o쪵?µß´sP‘rðàÁXê~iç ¢f÷¹ÒùØéœV°ÅqÙ¦Ævþ§®ÿîú‰Û·¨1<·Æ/Ž«ö§ö÷;º±˜"¦jSÞ• ÿçï¹¹Yï-åk„¡¹\áãf¬Ïü3ß:!ïúL¿˜¹÷U£ôñ5î·apÍU- ‘˜š>·=‘sÆ_,›¾õMÙ6öÛrþ§?+Ÿ=êërÔ¸ûå˜ýQþéè¯Êˆ±Ÿ”QóFÉIÍ'ÉØ+'DŒ5MN7ãbÂ3I·‡Ý'Éý=ž¹QŽ8úF™Z¼>õ'ÇËé?1·=­xŸ92áè”cÆÎ½‚y†¸ä瓬°˜cF½´uõYûM;‡417–ÚŸs*jvΟ-Ý%›.zh’ãráë×^oÿÁ”]W÷ë(>ÖþZ0©t]íOí7îw4±˜"¦jSþó“<Ÿ¿ç|÷rÇgñe<× ñT|÷ó¼ç#fŠïkUÞãÓãΕ*½1¨çÔ}o4öaËÀàŒ©gçµ'rîø‹díé§ÊaúÜqtVž?ñ9ò³ÇÈÇOþŒ|òŸ”“[O–ùaÝ0ZÎùÙO"Æ*ÆÅô˜íÓo´V ó=O&úîuÿŒœ~Wо‹±4ÝyYãß¾5faß§;¾8·ð¹qõ!ßoz…é3£»nì˜rΡÍZ™êŽäŒ© Ã{î•©è±¼s°cjã·ËÆûo·¾nz ðÕyy“yÛýÿy­µ÷ßßGmW·—s¿{œŽq옊ûý¼µ˜"¦jS*|¼ï3å9ÌçŒßÊO9ŠÜ'°îïÞæ~“PÿçÍÅý†ŸÞÐrZñãlø C%¦žŸ¿1‘ ~t©4™15ó¤å˜?{ÄùÞÉ#嘙ÇÈGNýˆŒ¸p„|ú7Ÿ–Q FÉÕ¿1ÖãòÍÐy/M·ïc_6M:ÏŒ’·=Û½—3òÍIÅûO¿ÉŒÇã~9ξŸù˜£o’û¬mÅûšûÉŒ{Ü5Ïà1 ·æ=—û®>Þñ}õÏ¥ÿy·,\Û)Í\éç¿~ ÑùJê~qc©ý©ý¦ƒ¿§§Ç¢.'½-ÉTÔ¬äyý´£ùÍÙg¹öiïWmO:†ÚŸÚoÜïèêbŠ˜ªULÙD\§˜Š<*p.žwO÷ÆRin¬JaèÅÔŒw7%réùWX1µì_“³Fü£¼þå“åÛ'e号ޓ¿ÿØßËßý¯¿“/­ü’ŒœvœÜýäëcÂãâg#¶?{“|Þ;g3rÜõÞÿÇò+Çx¿RÑtwÀþïþqa,û«¹í¾Ÿ/ŸÿéÜÒWë~‘cz¿Ï\T¤Å~¿é© XÔÔ)üײHÞs‚ÂþS÷‹KíOí×7‡?/‹¤Æîèè°…œó¶¸±5muÍÁŽ©7Ï%³ÆŽ’7Ç–¿Œ6om]þí÷ƹö礶«Û­ûª±Š¬Ç-l³Ù1÷;ºr=1ELÕ$¦ ŸŸ§Å½1§3¦bó…ÇTñãkBÏg ›‹3à‚ƒÌZ2CŠU) µ˜z±as"Wüøriþæi2÷+cäü9LŒÓäô/A¾øÖå£ßú¨õÄQòá#>,Ù[Ž“Gÿ¼8b¬'äŒÌ(¹ä¹ˆíÏÝl…Ì ‘¾ÿ ßÍÈ÷ì_ÝwäÍrÃÏF•oWÛ¾{³\2Ò1¯È1½ßƒg.æøÄ~¿é]víݲxÝVyô•‘T$´µµÅR÷‹KíOí×;‡iæmQÒÌ!n¬Å붹栢¦eÚTÉÿà«!¾b}½uü|óº®î>VÚŸÚoìïh1ELÕ"¦BW‚"b*öôð˜ò€žw¢ œ‹ó|­ Òƒ"1õ§…‰\?ñv¹oÌWdûYgÊŒO°bê´oŒ”c_9Ö:Ä7¦{Œœ²ñ9ú²Ñòäk+"ÆzÒŠ‹KgDmW—3òùkÞ‰¹ûþgL.ÞoÆ-f/7îÿ¹t¤ú8çPx|Æõ˜¨1½ßCø\¼f”g_•»üº{dyÛv1æ4GR°nݺXê~qc©ý©ý¤9¨¨iê!™áX™wáY–ùÆZ×¼sP×oÿñyÛç;ǘP¤¶ÇRûSûûMXKLSU©ˆ• ºëß\Ü'¶C'¦f.êLìº[¦Jî¤/Ë.mlaeêÌãä„¥'ÈèE£å˜—Ž•“¯ú¦<0ãí˜qž’o™qqÙ 1Û_¸EŽtÎù{Oyîuÿ ñËR3òyȱíæïÙûpÜ7tLï÷à¹>åüÒ¼¼æ–ï7½+®›,«7í’ïnŒtÃ%:gJÝ/n,µ?µß45›žBýû¹¦9œëØv®Ü9a‚k_꺺-xû¹ž1LW–ÇWûSûûOLSÕŽ©ôã•ÎÅ:l˜ÏóV²1õ_K¶¦rßôÙrÁ×ÏMß>C¾6öXÓ5Æ †‘òs¿/3æ·§ÉýŸ_L‘¦-{ëºOµ?µß45/?/˯½¬Æ./]VûSû›ë×ì#¦ˆ)>›n1õç¥ÛR›¹x‹ÜzÍrÄñŸ’/|g”üû¯ôŠÆA:ÿ6qª4oë“×VöÔÚŸÚï@šƒŠšîÙ¯Èê›*«oú©4š_o*\.¹ùêÂíÖ}®6ïc_¿ºà&Çõ›Êœã8/«ý©ýÆý޾ßHLSÄ0ìbêåeÛ*ö¿*OÍZÙ¯1Ü5¿ù½ÌYÜ,ë»ö×ÚŸÚï@šÃw:IÞzä÷²cÁÛu£ö§ö÷;·š˜"¦ˆ)`ØÅÔ+Ë»0H<5«ÑŒŠGäÊ_Þ[7jj¿i¿üùÎ'X+Eõ¢ö§ö÷;»Šs¦ˆ)b v1õÚŠnUò­•¬LSÄ0ìbêõ•=ªäôÄ1ELÃ.¦ÞXµ@•œJLSÄ0¼DÅTww€aÏ›¯-çõ˜"¦bŠ˜ˆ)Sˆ)€˜1€˜ˆ)Sˆ)€˜1ELÄbŠ˜"¦S1b 1S ¦ÉšòZpy=b.ùøñôL^ò­t]³®ç$k]׊·;éæ}ʷ鎱4×õ¬ä<Õ­m†É;5Vκœ5o/?Æ}_-p ¦xÁˆ)bjðÆTÖ,*¤Œ:Ä”wÿÙâ¾+ˆ9Ý ÃHêºS¶œã>Îr†—3¦ìÒ÷ÏZ÷Ó<V_óÍ­VöøYó±YOXi<‘ˆ)^0bŠ˜1å g¤¨8Êy&oG“îxŒ½ddú7fš˜Ê8ö4f¢˜ÊYáSÝ )=qLéVPÅÈÑã„­©@ÒKcÚ+OziŒŒg%*h»?´@L ¦ˆ©C¿2¥yb'²ú”qÜno×÷72ý3MLiŽëb,„“n­òhVÜh)bÊ~lá6;¦ ¡¶jd‡“n®3¬+#ðð`XHb1€˜"¦Âa¾\1J¼+<ºc›æ8OÉð|ÕV—ÒŽi—Xí :g*[˜r²KSå¤à˜RuÆQ!Ü e_ÖΣ ;”—.¤²æÏ8Ÿ/rüŒsO@b ¦@LÕ.¦ôˆs£ Ï*TÖñ8-àÄï´c¦=Ìç 0½Ò˜rRKSö!;#â0_yüœu(1gÝ®3†Lî'ë8$™ðû32åsºôrX9ž€Ä@L˜ªþa>#b•G–\ÌyN•ŒYiLi!+` c*8’’ÆTù/íÜ' »o/Çš}[á¯ûŒ˜ÒBÇàÉCLS1…yz&ääqï äA«Yùˆó™ÒŽYIL…½5B¶?1÷ÖÎÇz¿ùß¡Bî¿ô ¦à·?š ' SÄ@LSƒç­ôÊþZ®îcÄbŠ˜P1¥œ^ˆªö˜1€˜"¦ø8Ä@LaÇT6§K.ñ9Lšèù¼ä‹Œ'GÄ@LaØÆ”;ŒòFº“›5˜ˆ)€˜Â0Ž©lΰb(ÝÊ1S1bªSy]«jLYc:V»t_:@LĆìa¾¬ä =F•bJ6 {goicj–ùàELñ1ôÜ!¦ˆ©šž€®¢¨’“ɃV¦ì±ÔŠ¿p€˜ˆ) “˜ÒEËæÄH¹ªuΔ}¸sª€~ÄÔêí>Ä ¦ž;Ä1Uƒ˜ÊJ6[å˜ÊfÝ ¨é¬PÄ@Laè®L•ÉUx²¸?¦T9Çäü)€˜ˆ) —Ã|ürb ¦@Lñq2ÀPŠ©7Í/b ˆ© ç1ELSÀ°Œ©^b HSîç1ELÕ ¦Ô{BUòþRQŸÍÇçöÄ0bª—˜"¦rL%{k>j¨BL5öúS@‚˜ xîSÄ1 ØzË|p"¦€d1å}î¼ELS5)­üvîø±?j&üÍSÇ”zß©ÔoÅàŸga.…ùîÃȹßï "1õ1Sh1•/‡‡:å·HpÇP!\¼ñ“*¦¬÷ r¬„y¯Ç£eÏÓù8ߪyöoµ ¦b ÄTe‡ù\aâ>‘<ì„òT1å[1 ´Ð•©¬ûqöØ®ýðŽëb15Û|ð"¦€ø˜ zîSÄÔ!‰©¸Ð9”1Uz\iÞ¬JaÆÔš^b HSÏbŠ˜ªsL?j&æÜ£ªæ³?ŠÆ·²ä ;ëp¤;š¬}™!Ūˆ)Ä15`bÊwzóÅ€S†K'®'>ÿ \15Ç|ð"¦€ø˜ zîSÄÔ0~ôø·pàm0tcj‡1$‰)ÿs‡˜"¦ˆ©lpDåóyÞ C6¦òkwXæ8S@|LÙÏ›¼1ELñÙ|À0Ž)'b HSybŠ˜"¦bêmóÀ‹˜âc*è¹CLSÄ0cªi‡1$ˆ©€ç1ELSÀ0©¹ÄSsž;Ä1ELÃ0¦æS1b @å1õκ>ÄSAÏbŠ˜"¦bŠ˜ˆ)SÒÄÔ<óÀ‹˜âc*è¹CLSÄ0cªy§1$ˆ©€ç1ELSÀ0Œ©ùæ €1ÄÇTÐs‡˜"¦ˆ)`ÆÔ»ëwúS@|L=wˆ)bŠ˜†eLíò!¦€$1åîSÄ1 ØZ`¾xS@|L=wˆ)bŠ˜†aL5´ìò!¦€ø˜ zîSÄÔÀŠ©¬)ï Õø—÷Ð#æ’OÏä%ŸÑJ×5ëzN²Öu­x»“nÞ§|›îKs]ÏJÎóXÝÚf˜¼óPcå¬ËYóöòcÜ÷ÕçbŠL€˜"¦oLe=Á¢BʨCLy÷Ÿ-˜ÓÍ`1\¤®Û1eË9îã gx9cÊ)Íqÿ¬u?Í`åñ5ßÜ aeŸ5›õ„•ÆiÅÔÂÖÝ>ÄSAÏbŠ˜ª~LyCÄ)*ŽržÉÛѤ;c¯™þ™&¦2Ž}™(¦rVøG·BJOSºTF1r4Ç8a+G*ôÒ˜öÊ“^#ãY‰ Úî- ‡˜Zd¾xS@|L=wˆ©¡SK–,‘3fÈÃ?ìóÈ#”¾:=÷Üs²|ùò*¯LižØÉ†¬>e·ÛÛuÇýLÿÆLSšãz…‡ á¤[«<š7ZŠ˜²[¸ÍŽ©Bè„­Ùá¤[‡ë kÅÊ<<RA‡1ôcjqÛnb ˆ© ç15´bJ…Tgg§¼÷Þ{%°¨ÕªÞÞf4õJOÏvÙ¶­K6mÚ,+W®–^x¡‡ùrÅ(ñ®ðèŽmšã<%ÃóUX]J;¦=^>`µ+蜩l5bÊyÈ.mL•W‚cJ=ÖG…p+”}Y8*ìP^ºÊš?ã|¾Èñ3Î<[L-ißíCLñ1ôÜ!¦†VL=øàƒ®ˆÚ·¯OöìÝ+»wï‘-[¶šñÔ!í6IKK»¬Z½FæÍoÆÆµòÀï¨aLéçFžU¨¬ãqZÀ‰ßiÇL{˜Ï`z¥1å<¤–>¦ìCvFÄa¾òø9ëPbκ]+f ;™Ü;NÖqH2á÷gdÊçtéå°2r<_Líñ!¦€$1åîSC/¦ì•¨¾>3¤öì•]»vËŽ;¥½}“¬_ß&MëÖ›Õ$ -•¹sßµV¦ªSÎs–‚Vyô€`ÉÅœçTɘ•Æ”²–0¦‚#)iL•ÿÒÎ}ºûör¬Ù·þºÏ‰)-t ž<Ã1¦–nØãCLñ1ôÜ!¦†fLíß¿_öîÝW ©žž^YßÒ&k×6˪UkdÙ²UÒаDÞ~{¾¬X±ªÊ1¥…œ‹¤…üå\ÐjV>â|¦´cVSaoíOLŽ5‚ó±ÞÃoþ·F(„û/ý‚‚)øí‚æÂ èÃ)¦–™/^ÄSAÏbŠ˜ª~L%¡Wö×ru¢1µ|ãb ˆ© ç1ELÕ7¦ô€“À«QÕâ1µbã^b ˆ© ç1ELš•)‡4¦VnÚëCLñ1ôÜ!¦ˆ©šÆT6§K.{(0šèyãÏ¡¿sQËK¾ÈÈeÞS1…ASîù¼Që“›ÃB¥61¥éŽï-Ÿôsíú?µß°`Šº ðÆÔªÍ{}ˆ) >¦‚ž;Ä1U“˜Êæ ë…½~+SõŒ©¬ùÃȺÃJ׈) ª˜Zm¾xS@|L=wˆ)bªf1¥#]LcCˉa¯úX‘’•œ šn­xå\«DÞÕ"ÿ˜®qÔŽÇéZø\ÂBÅú^­¼ÅYø>ó®ï½Ÿ1úýUÿ÷ÀÛ* ®˜jìØçCLñ1ôÜ!¦ˆ©æ³ÃÀHSŽC‚Yõb^|¼uÙóî݆s쨕)ǘV\ÇqŽï»ñ¸€ñ“GJø˜î*üü¼ã¦Š©Èï¯V¿ –˜Zc¾xS@|L=wˆ)bª¦' Ûç%;üä "÷Jˆ+Tˆ¸VnæsÆ€oEÅ0«(¤âÆôœc²–*¦"¿¿Zý0hbjË>b HSÏbŠ˜ªqL™±"É_ÄK/þ¥q‚VCêSIÃ$]LÅw(c*Ùïƒ%¦ÖšÏW/b ˆ)ûùÒÔÙWºLLS5ˆ©¬d³•Æ”ãEÛ: æ~±¶‚Á0VC*ˆ©ØÃ|á1UÙÉÞñcÆ{TÕÃ|Ùâ9Q?ËJ,1¥^¼ˆ) >¦‚ž;Ä1U“•)ÍsRxšŸ #âqçý¿]AÌ SÜ èIÉ¥9=fµ«j‡ùâN@Œ©Ê1µ®³¯`k_é21ÄÇTé¹ã@LSµ?ÌWÅ7µäÏÿÆ›‹ò{1µµÏ‡˜ÄTÀs‡˜"¦ÐÇÉ„¿ˆ—VøüCSü†NL5›/^ÄSAÏbŠ˜â³ù€aSë·õYšˆ) >¦œÏû21ELU=¦ÔÊ¿` ÇÔ~b HSþç1EL±2 ØjéÚ/-Û܈) >¦¬ç‹çùCLS¬LÃ5¦<ˆ) ALÄSAÏbŠ˜be †1µ e—Kƒ‰˜âc*è¹CLSÄ0 cj–ù¢0kµ1ÄÇTÐs‡˜"¦ˆ)€˜"¦b Äb ¦@L ¦b Äb ¦@LS1€˜"¦ˆ)Ä@L˜@LĈ)Ä@L˜"¦b ¦ˆ)bŠ˜ˆ)b ¦@L ¦b Äb ¦@LS1S ¦ˆ)€˜"¦bŠ˜"¦S1b 1S ¦S1bŠ˜ˆ)Ä1EL ¦b Äb ¦@L ¦b Ä1S1ELSÄ@LS1b 1S ¦S1bŠ˜ˆ)€˜1ELÄbŠ˜"¦S1b 1S ¦S1bŠ˜ˆ)€˜"¦ˆ)b 1S ¦S1b 1S ¦ˆ)€˜ˆ)bŠ˜"¦bŠ˜ˆ)Sˆ)€˜1€˜ˆ)Sˆ)€˜1ELÄbŠ˜"¦S1b 1S81µÿK__ŸV]]=ÒÙ¹M:::eãÆill"¦bŠ˜ˆ)„ÅÔ{ïýE¾|Ê)ré%—È/®¿¾dê”)ò§—^’ÖÖ Ä@LS1…¨˜ºâòËåÉ'ž™3g–Ìž=[/^LLÄ1Sà0b ¦Àa>Ä@LÃ|Ä@LÄ8ÌGLÄbŠ˜â0b ¦P•˜úͯm…Óœ9sJdÕªUÄ@LS1ó ¦b |œ b ¦@LS1S ¦ˆ)€˜@LSÄb ¦@L ¦b Äb ¦@LS1€˜"¦ˆ)Ä@L˜@LĈ)Ä@L˜"¦b ¦ˆ)bŠ˜ˆ)b ¦@L ¦b Äb ¦@Lñ‹ˆ)€˜1ELÄbŠ˜"¦S1b 1S ¦S1bŠ˜ˆ)€˜"¦ˆ)b ¦ˆ)€˜1€˜ˆ)Sˆ)€˜1ELÄ@Lño 1ELÄ1SÄ1€˜ˆ)Sˆ)€˜1€˜ˆ)SÄ@L ¦ˆ)b 1S ¦S1b 1S ¦ˆ)€˜ˆ)bŠ˜"¦bŠ˜ˆ)Sˆ)€˜1€˜ˆ)SÄ@LĈ)b ¦SÄ1€˜ˆ)Sˆ)€˜1€˜ˆ)SÄ@L ¦ˆ)b 1S ¦S1b 1S ¦ˆ)€˜ˆ)bŠ˜"¦bŠ˜ˆ)Sˆ)€˜1€˜ˆ)Sü"b ¦@LS1€˜"¦ˆ)Ä@L˜@LĈ)Ä@L˜"¦b ¦ˆ)bŠ˜ˆ)b ¦@Lè_L©ÕqäŠNþm!¦ˆ)€˜@L˜@LĈ)Ä@L˜@LĈ)b ¦SÄ1ÀCýàºø·…˜"¦1ELSÄ1ELbŠ˜ ¦ˆ)€ÁS}}}²gÏ^+¤¶oï•îîY·®E›ÌxZ-K–,—w,’9ùwˆ)gL©U);¤zz¶KWWlÝÚe†ÔZ+œ–,]. ‹åy döœ¹Ä€SÓ§O—ÎÎNÙ»woñßéíÝa­Nµ·o––6YßÒ*ÍÍ륩©YÖ¬i’E‹–ÈÓO?MLbª¡¡Á *µÒ”” ©7ß|“˜ÄÔ–-[¤««KvîÜ)»wïvÙ³gOé«“ZÅÚ·o1ˆ)b €˜ ¦ˆ)b SÄ1Pï˜R‘¤>^&ŒúØb $¦T0wÜqò¹Ï}Îrä‘Gʘ1cäŠ+®I“&Y·S1+SãÇ— &Èĉ­w<Ïçó¬L$9gʪk¯½Vž}öYYºti)¤8g ÀSÝÝݲk×.×Iæ*œT@͘1ÃRÄ€'¦z{{­)INû÷ï—÷Þ{ÏúêÜ®BJÅ1ˆ)3¦Ôª”II¨"¦1UŒ)uè.,šœñäELbÊŒ©°`R‡÷ì¯Aˆ)@L™1Kqˆ)@L™1¥¢¨RýŽ)SÄ1@LSÄ@µb é”b •ùÿwß{s¥6IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/index.rst0000664000000000000000000001361515074673150015145 0ustar00rootroot.. include:: icons.rst .. title:: Overview .. toctree:: :hidden: :titlesonly: :maxdepth: 1 getting_started tutorials/index guide/index devguide/index contact .. image:: images/pygobject.svg :align: center :width: 400px :height: 98px :class: only-light .. image:: images/pygobject-dark.svg :align: center :width: 400px :height: 98px :class: only-dark | .. include:: ../README.rst :start-after: | :end-before: ---- If you want to write a Python application for `GNOME `__ or a Python GUI application using GTK, then PyGObject is the way to go. To get started, check out the "`GNOME Developer Documentation `__". For more information on specific libraries, check out the `GNOME Python API documentation `__. .. code:: python import sys import gi gi.require_version("Gtk", "4.0") from gi.repository import GLib, Gtk class MyApplication(Gtk.Application): def __init__(self): super().__init__(application_id="com.example.MyGtkApplication") GLib.set_application_name("My Gtk Application") def do_activate(self): window = Gtk.ApplicationWindow(application=self, title="Hello World") window.present() app = MyApplication() exit_status = app.run(sys.argv) sys.exit(exit_status) How does it work? ----------------- .. figure:: images/overview.svg :width: 600px :height: 222px :align: center :class: only-light .. figure:: images/overview-dark.svg :width: 600px :height: 222px :align: center :class: only-dark PyGObject uses `GLib `__, `GObject `__, `GIRepository `__, `libffi `__ and other libraries to access the C library (libgtk-4.so) in combination with the additional metadata from the accompanying typelib file (Gtk-4.0.typelib) and dynamically provides a Python interface based on that information. Who Is Using PyGObject? ----------------------- * `Anaconda `__ - an installation program used by Fedora, RHEL and others * `Apostrophe `__ - a Markdown editor * `Blanket `__ - listen to different sounds * `BleachBit `__ - delete unnecessary files from the system * `Bottles `__ - run Windows software on Linux * `Cambalache `__ - a user interface maker for GTK * `Cozy `__ - the audiobook app for Linux * `D-Feet `__ - an easy to use D-Bus debugger * `Deluge `__ - a BitTorrent client * `Dialect `__ - a translation app * `Drawing `__ - a drawing application * `Feeds `__ - an RSS/Atom feed reader * `Gajim `__ - a fully-featured XMPP client * `Gameeky `__ - a learning tool for making games and learning experiences * `Gaphor `__ - a simple modeling tool * `Getting Things GNOME! `__ - a personal task organizer * `Girens `__ - a Plex client for playing movies, TV shows and music from your Plex library * `GNOME Music `__ - a music player for GNOME * `GNOME Tweaks `__ - a tool to customize advanced GNOME options * `Gramps `__ - a genealogy program * `Komikku `__ - a manga reader * `Lollypop `__ - a modern music player * `Lutris `__ - a video game manager * `Meld `__ - a visual diff and merge tool * `Metadata Cleaner `__ - an application to view and clean metadata in files * `MyPaint `__ - a nimble, distraction-free, and easy tool for digital painters * `Nicotine+ `__ - a graphical client for the Soulseek peer-to-peer network * `Orca `__ - a flexible and extensible screen reader * `Paperwork `__ - a personal document manager * `Pithos `__ - a Pandora Radio client * `Pitivi `__ - a free and open source video editor * `Plots `__ - a graph plotting app * `Quod Libet `__ - a music library manager / player * `Secrets `__ - a password manager * `Setzer `__ - a LaTeX editor * `Terminator `__ - The Robot Future of Terminals * `Wike `__ - a Wikipedia reader The following applications or libraries use PyGObject for optional features, such as plugins or as optional backends: * `beets `__ - a music library manager and MusicBrainz tagger * `gedit `_- a GNOME text editor * `matplotlib `__ - a python 2D plotting library * `Totem `__ - a video player for GNOME Further Resources ----------------- `GNOME Developer Documentation `__ Tutorials for creating a GNOME application using PyGObject, GTK 4, and Libadwaita. `GNOME Python API documentation `__ Auto generated API documentation for many libraries accessible through PyGObject. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/_static/custom.css0000664000000000000000000000073615074673150021004 0ustar00rootroot.toctree-wrapper .reference.external::after { 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"); margin: 0 .25rem; vertical-align: middle; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gobject/basics.rst0000664000000000000000000001600015074673150020734 0ustar00rootroot.. currentmodule:: gi.repository Basics ====== .. hint:: In this example, we will use GTK widgets to demonstrate GObject capabilities. GObject Initialization ---------------------- GObjects are initialized like any other Python class. .. code:: python label = Gtk.Label() .. _basics-properties: Properties ---------- GObject has a powerful properties system. Properties describe the configuration and state of a gobject. Each gobject has its own particular set of properties. For example, a GTK button has the property ``label`` which contains the text of the label widget inside the button. You can specify the name and value of any number of properties as keyword arguments when creating an instance of a gobject. To create a label aligned to the right with the text "Hello World", use: .. code:: python label = Gtk.Label(label='Hello World', halign=Gtk.Align.END) which is equivalent to .. code:: python label = Gtk.Label() label.set_label('Hello World') label.set_halign(Gtk.Align.END) There are various ways of interacting with a gobject properties from Python, we already have seen the two first ways, these are setting them on initialization or using the getters and setters functions that the gobject might provide. Other option is to use :class:`GObject.Object` builtin methods :meth:`GObject.Object.get_property` and :meth:`GObject.Object.set_property`. Using these methods is more common when you have created a :class:`GObject.Object` subclass and you don't have getters and setters functions. .. code:: python label = Gtk.Label() label.set_property('label', 'Hello World') label.set_property('halign', Gtk.Align.END) print(label.get_property('label')) Instead of using getters and setters you can also get and set the gobject properties through the ``props`` property such as ``label.props.label = 'Hello World'``. This is equivalent to the more verbose methods that we saw before, and it's a more pythonic way of interacting with properties. To see which properties are available for a gobject you can ``dir`` the ``props`` property: .. code:: python widget = Gtk.Box() print(dir(widget.props)) This will print to the console the list of properties that a :class:`Gtk.Box` has. Property Bindings ^^^^^^^^^^^^^^^^^ GObject provides a practical way to bind properties of two different gobjects. This is done using the :meth:`GObject.Object.bind_property` method. The behavior of this binding can be controlled by passing a :class:`GObject.BindingFlags` of choice. :attr:`GObject.BindingFlags.DEFAULT` will update the target property every time the source property changes. :attr:`GObject.BindingFlags.BIDIRECTIONAL` creates a bidirectional binding; if either the property of the source or the property of the target changes, the other is updated. :attr:`GObject.BindingFlags.SYNC_CREATE` is similar to ``DEFAULT`` but it will also synchronize the values of the source and target properties when creating the binding. :attr:`GObject.BindingFlags.INVERT_BOOLEAN` works only for boolean properties and setting one property to ``True`` will result in the other being set to ``False`` and vice versa (this flag cannot be used when passing custom transformation functions to :meth:`GObject.Object.bind_property`). .. code:: python entry = Gtk.Entry() label = Gtk.Label() entry.bind_property('text', label, 'label', GObject.BindingFlags.DEFAULT) In this example **entry** is our source object and ``text`` the source property to bind. **label** is the target object and the namesake property ``label`` is the target property. Every time someone changes the ``text`` property of the entry the label ``label`` will be updated as well with the same value. Property Bindings with Transformations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Sometimes you may want to bind two properties that are incompatible, or you simply need to apply some transformation between these values. For these scenarios :meth:`GObject.Object.bind_property` also accepts custom transformation functions that serve to this purpose. The transformation functions take as first argument the :class:`GObject.Binding` instance for this binding and as second argument the property value depending on the direction of the transformation. For ``transform_to`` this will be the value of the source property and for ``transform_from`` the value of the target property. Each function should return the value to be set in the other object's property, with the correct type. In this example we'll do an ``int`` to ``bool`` type conversion between two objects: .. code:: python def transform_to(_binding, value): return bool(value) # Return int converted to a bool def transform_from(_binding, value): return int(value) # Return bool converted to a int source.bind_property( 'int_prop', target, 'bool_prop', GObject.BindingFlags.BIDIRECTIONAL, transform_to, transform_from ) .. _basics-signals: Signals ------- GObject signals are a system for registering callbacks for specific events. A generic example is: .. code:: python handler_id = gobject.connect('event', callback, data) Firstly, *gobject* is an instance of a gobject we created earlier. Next, the event we are interested in. Each gobject has its own particular events which can occur. This means that when the gobject emits the event, the signal is issued. Thirdly, the *callback* argument is the name of the callback function. It contains the code which runs when signals of the specified type are issued. Finally, the *data* argument includes any data which should be passed when the signal is issued. However, this argument is completely optional and can be left out if not required. The function returns a number that identifies this particular signal-callback pair. It is required to disconnect from a signal such that the callback function will not be called during any future or currently ongoing emissions of the signal it has been connected to: .. code:: python gobject.disconnect(handler_id) When creating the callback function for a signal, the arguments it accepts will depend on the specific signal, but for a signal with no arguments it will look like this: .. code:: python def on_event(gobject, data): ... my_object.connect('event', on_event, data) Where ``gobject`` is the object that triggered the signal and ``data`` is the additional data that we previously passed to the :meth:`GObject.Object.connect` method. If the signal had arguments, they will come before the optional data argument. The ``notify`` signal ^^^^^^^^^^^^^^^^^^^^^ When any of a GObject's properties change, it will emit the ``notify`` signal. This is a "detailed" signal, meaning that you can listen to a subset of the signal, in this case a specific property. For example, you can connect to the signal in the form of ``notify::property-name``: .. code:: python def callback(label, _pspec): print(f'The label prop changed to {label.props.label}') label = Gtk.Label() label.connect('notify::label', callback) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gobject/examples/listmodel.py0000664000000000000000000000266015074673150023131 0ustar00rootrootfrom gi.repository import Gio, GObject class Person(GObject.Object): __gtype_name__ = "Person" name = GObject.Property(type=str) def __init__(self, name): super().__init__() self.name = name class PersonsModel(GObject.GObject, Gio.ListModel): __gtype_name__ = "PersonsModel" def __init__(self): super().__init__() # Private list to store the persons self._persons = [] """ Interface Methods """ def do_get_item(self, position): return self._persons[position] def do_get_item_type(self): return Person def do_get_n_items(self): return len(self._persons) """ Our Helper Methods """ def add(self, person): self._persons.append(person) """ We must call Gio.ListModel.items_changed() every time we change the list. It's a helper to emit the "items-changed" signal, so consumer can know that the list changed at some point. We pass the position of the change, the number of removed items and the number of added items. """ self.items_changed(len(self._persons) - 1, 0, 1) def remove(self, position): del self._persons[position] self.items_changed(position, 1, 0) def get_index_by_name(self, name): for i, person in enumerate(self._persons): if person.name == name: return i return None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gobject/interfaces.rst0000664000000000000000000000351415074673150021621 0ustar00rootroot.. currentmodule:: gi.repository Interfaces ========== GObject interfaces are a way of ensuring that objects passed to C code have the right capabilities. When a GObject implements an interface it should implement an expected set of methods, properties and signals. In the Python sense, an interface is another class that is inherited. For example in GTK, :class:`Gtk.Image` supports various sources for the image that it will display. Some of these sources can be a :class:`Gio.Icon` or a :class:`Gdk.Paintable`, both are actually interfaces so you don't pass a direct instance of these, instead you should use some of the gobjects that implement the interface. For :class:`Gio.Icon` those can be :class:`Gio.ThemedIcon` that represents an icon from the icon theme, or :class:`Gio.FileIcon` that represents an icon created from an image file. Another important interface of reference is :class:`Gio.ListModel`. It represents a mutable list of :class:`GObject.Objects `. If you want to implement :class:`Gio.ListModel` you must implement three methods, these are :meth:`Gio.ListModel.get_item_type`, :meth:`Gio.ListModel.get_n_items` and :meth:`Gio.ListModel.get_item`. The interfaces methods that you should implement are exposed as :ref:`virtual methods `. With these methods any consumer can iterate the list and use the objects for any purpose. .. tip:: A generic implementation of :class:`Gio.ListModel` is :class:`Gio.ListStore`. It allows you to set the :class:`GObject.Object` type that it will store and provides methods to append, insert, sort, find and remove gobjects. Example ------- In this examples we'll be implementing a :class:`Gio.ListModel` in Python. It will store a custom :class:`GObject.Object` and provide some helper methods for it. .. literalinclude:: examples/listmodel.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gobject/subclassing.rst0000664000000000000000000002444315074673150022017 0ustar00rootroot.. currentmodule:: gi.repository Subclassing =========== Before entering in detail, you should know some important points about GObject subclassing: 1. It is possible to subclass a :class:`GObject.Object`. Subclassing creates a new :class:`GObject.GType` which is connected to the new Python type. This means you can use it with API which takes :class:`GObject.GType`. 2. :class:`GObject.Object` only supports single inheritance, this means you can only subclass one :class:`GObject.Object`, but multiple Python classes. 3. The Python wrapper instance for a GObject.Object is always the same. For the same C instance you will always get the same Python instance. Inherit from GObject.GObject ---------------------------- A native GObject is accessible via :class:`GObject.Object`. It is rarely instantiated directly, we generally use an inherited classes. A :class:`Gtk.Widget` is an inherited class of a :class:`GObject.Object`. It may be interesting to make an inherited class to create a new widget, like a settings dialog. To inherit from :class:`GObject.Object`, you must call `super().__init__` in your constructor to initialize the gobjects you are inheriting, like in the example below: .. code:: python from gi.repository import GObject class MyObject(GObject.Object): def __init__(self): super().__init__() You can also pass arguments to `super().__init__`, for example to change some property of your parent gobject: .. code:: python class MyWindow(Gtk.Window): def __init__(self): super().__init__(title='Custom title') In case you want to specify the GType name we have to provide a ``__gtype_name__``: .. code:: python class MyWindow(Gtk.Window): __gtype_name__ = 'MyWindow' def __init__(self): super().__init__() Properties ---------- One of the nice features of GObject is its generic get/set mechanism for object properties. Any class that inherits from GObject.Object can define new properties. Each property has a type that never changes (e.g. ``str``, ``float``, ``int``...). Create new properties ^^^^^^^^^^^^^^^^^^^^^ A property is defined with a name and a type. Even if Python itself is dynamically typed, you can't change the type of a property once it is defined. A property can be created using :func:`GObject.Property`. .. code:: python from gi.repository import GObject class MyObject(GObject.Object): foo = GObject.Property(type=str, default='bar') property_float = GObject.Property(type=float) def __init__(self): super().__init__() Properties can also be read-only, if you want some properties to be readable but not writable. To do so, you can add some flags to the property definition, to control read/write access. Flags are :attr:`GObject.ParamFlags.READABLE` (only read access for external code), :attr:`GObject.ParamFlags.WRITABLE` (only write access), :attr:`GObject.ParamFlags.READWRITE` (public): .. there is also construct things, but they .. doesn't seem to be functional in Python .. code:: python foo = GObject.Property(type=str, flags=GObject.ParamFlags.READABLE) # not writable bar = GObject.Property(type=str, flags=GObject.ParamFlags.WRITABLE) # not readable You can also define new read-only properties with a new method decorated with :func:`GObject.Property`: .. code:: python from gi.repository import GObject class MyObject(GObject.Object): def __init__(self): super().__init__() @GObject.Property def readonly(self): return 'This is read-only.' You can get this property using: .. code-block:: python my_object = MyObject() print(my_object.readonly) print(my_object.get_property('readonly')) The API of :func:`GObject.Property` is similar to the builtin :py:class:`property`. You can create property setters in a way similar to Python property: .. code-block:: python class AnotherObject(GObject.Object): value = 0 @GObject.Property def prop(self): """Read only property.""" return 1 @GObject.Property(type=int) def prop_int(self): """Read-write integer property.""" return self.value @prop_int.setter def prop_int(self, value): self.value = value There is also a way to define minimum and maximum values for numbers: .. code-block:: python class AnotherObject(GObject.Object): value = 0 @GObject.Property(type=int, minimum=0, maximum=100) def prop_int(self): """Integer property with min-max.'""" return self.value @prop_int.setter def prop_int(self, value): self.value = value my_object = AnotherObject() my_object.prop_int = 200 # This will fail Alternatively you can use the more verbose `__gproperties__` class attribute to define properties: .. code:: python from gi.repository import GObject class MyObject(GObject.Object): __gproperties__ = { 'int-prop': ( int, # type 'integer prop', # nick 'A property that contains an integer', # blurb 1, # min 5, # max 2, # default GObject.ParamFlags.READWRITE # flags ), } def __init__(self): super().__init__() self.int_prop = 2 def do_get_property(self, prop): if prop.name == 'int-prop': return self.int_prop else: raise AttributeError('unknown property %s' % prop.name) def do_set_property(self, prop, value): if prop.name == 'int-prop': self.int_prop = value else: raise AttributeError('unknown property %s' % prop.name) For this approach properties must be defined in the ``__gproperties__`` class attribute, a dictionary, and handled in :meth:`GObject.Object.do_get_property` and :meth:`GObject.Object.do_set_property` :ref:`virtual methods `. .. hint:: Changes to custom properties are also signaled by the ``notify`` detailed signal. But remember that it will normalize your property name to hyphens instead of underscores, so you will write ``notify::prop-int`` and not ``notify::prop_int``. Signals ------- Each signal is registered in the type system together with the type on which it can be emitted: users of the type are said to connect to the signal on a given type instance when they register a function to be invoked upon the signal emission. Users can also emit the signal by themselves or stop the emission of the signal from within one of the functions connected to the signal. Create new signals ^^^^^^^^^^^^^^^^^^ New signals can be created by using the :func:`GObject.Signal` decorator. The decorated methods are the object method handlers, these will be called when the signal is emitted. The time at which the method handlers are invoked depends on the signal flags. :attr:`GObject.SignalFlags.RUN_FIRST` indicates that this signal will invoke the object method handler in the first emission stage. Alternatives are :attr:`GObject.SignalFlags.RUN_LAST` (the method handler will be invoked in the third emission stage) and :attr:`GObject.SignalFlags.RUN_CLEANUP` (invoke the method handler in the last emission stage). Signals can also have arguments, the number and type of each argument is defined as a tuple of types. Signals can be emitted using :meth:`GObject.Object.emit`. .. code:: python from gi.repository import GObject class MyObject(GObject.Object): def __init__(self): super().__init__() @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(int,)) def arg_signal(self, number): """Called every time the signal is emitted""" print('number:', number) @GObject.Signal def noarg_signal(self): """Called every time the signal is emitted""" print('noarg_signal') my_object = MyObject() def signal_callback(object_, number): """Called every time the signal is emitted until disconnection""" print(object_, number) my_object.connect('arg_signal', signal_callback) my_object.emit('arg_signal', 100) # emit the signal "arg_signal", with the # argument 100 my_object.emit('noarg_signal') Alternatively you can use the more verbose `__gsignals__` class attribute to define signals. When a new signal is created, a method handler can also be defined in the form of ``do_signal_name``, it will be called each time the signal is emitted. .. code:: python class MyObject(GObject.Object): __gsignals__ = { 'my_signal': ( GObject.SignalFlags.RUN_FIRST, # flag None, # return type (int,) # arguments ) } def do_my_signal(self, arg): print("method handler for `my_signal' called with argument", arg) .. _virtual-methods: Virtual Methods --------------- GObject and its based libraries usually have gobjects that expose virtual methods. These methods serve to override functionality of the base gobject or to run code on a specific scenario. In that case you should call the base gobject virtual method to preserve its original behavior. In PyGObject these methods are prefixed with ``do_``. Some examples are :meth:`GObject.Object.do_get_property` or :meth:`Gio.Application.do_activate`. .. important:: The Python :py:class:`super` class only works for the immediate parent. If you want to chain some virtual method from a object that is more up in the hierarchy of the one you are subclassing you must call the method directly from the object class: ``SomeOject.method(self, args)``. .. code:: python class SomeOject(OtherObject): ... class MyObject(SomeOject): def __init__(self): super().__init__() def do_virtual_method(self): # Call the original method to keep its original behavior super().do_virtual_method() # Run some extra code ... """This is a virtual method from SomeOject parent""" def do_other(self): OtherObject.do_other(self) # We can't use super() ... ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gobject.rst0000664000000000000000000000125115074673150017472 0ustar00rootrootGObject ======= GObject is the foundation for object-oriented programming in the GNOME libraries. For example :class:`GObject.Object` is the base providing the common attributes and methods for all object types in GTK and the other libraries in this guide. The :class:`GObject.Object` class provides methods for object construction and destruction, property access methods, and signal support. This chapter will introduce some important aspects about the GObject implementation in Python. .. toctree:: :maxdepth: 3 :caption: Contents gobject/basics gobject/subclassing gobject/interfaces Weak References ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk3.rst0000664000000000000000000000035115074673150016725 0ustar00rootrootGTK3 ==== You can find help about using Python with GTK3 in the following resources. * `The Python GTK+ 3 Tutorial `_ * `PyGObject API Reference `_ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/application.rst0000664000000000000000000000612615074673150021237 0ustar00rootroot.. currentmodule:: gi.repository Application =========== .. seealso:: For more detailed information about ``Gtk.Application`` checkout the :devdocs:`Using GtkApplication ` tutorial. :class:`Gtk.Application` is the foundation for creating GTK apps. It encompasses many repetitive tasks that a modern application needs such as handling multiple instances, D-Bus activation, opening files, command line parsing, startup/shutdown, menu management, window management, and more. In this example we will be also using :class:`Gtk.ApplicationWindow`, it provides some extra features over regular :class:`Gtk.Window` for main application windows. Actions ------- :class:`Gio.Action` is a way to expose any single task your application or widget does by a name. These actions can be disabled/enabled at runtime and they can either be activated or have a state changed (if they contain state). The reason to use actions is to separate out the logic from the UI. For example this allows using a menubar on OSX and a gear menu on GNOME both simply referencing the name of an action. On the main implementation of this, what you will be using is :class:`Gio.SimpleAction`, which will be demonstrated later. Many classes such as :class:`Gio.MenuItem` and :class:`Gtk.Actionable` interface implementations like :class:`Gtk.Button` support properties to set an action name. These actions can be grouped together into a :class:`Gio.ActionGroup` and when these groups are added to a widget with :meth:`Gtk.Widget.insert_action_group()` they will gain a prefix. Such as "win" when added to a :class:`Gtk.ApplicationWindow`. You will use the full action name when referencing it such as "app.about" but when you create the action it will just be "about" until added to the application. You can also very easily make keybindings for actions by setting the `accel` property in the :class:`Gio.Menu` file or by using :meth:`Gtk.Application.set_accels_for_action()`. Menus ----- Your menus should be defined in XML using :class:`Gio.Menu` and would reference the previously mentioned actions you defined. :class:`Gtk.Application` allows you to set a menu via :meth:`Gtk.Application.set_menubar()`. If you make use of :class:`Gio.Resource` this can automatically load the menu, otherwise you can set them manually. A detailed example is shown below. Command Line ------------ When creating your application it takes a flag property of :class:`Gio.ApplicationFlags`. Using this you can let it handle everything itself or have more custom behavior. You can use ``HANDLES_COMMAND_LINE`` to allow custom behavior in :meth:`Gio.Application.do_command_line()`. In combination with :meth:`Gio.Application.add_main_option()` to add custom options. Using ``HANDLES_OPEN`` will do the work of simply taking file arguments for you and let you handle it in :meth:`Gio.Application.do_open()`. If your application is already open these will all be sent to the existing instance unless you use ``NON_UNIQUE`` to allow multiple instances. Example ------- .. image:: images/application.png .. literalinclude:: examples/application.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/basics.rst0000664000000000000000000000252415074673150020176 0ustar00rootroot.. currentmodule:: gi.repository GTK4 Basics =========== Main loop and Signals --------------------- Like most GUI toolkits, GTK uses an event-driven programming model. When the user is doing nothing, GTK+ sits in the main loop and waits for input. If the user performs some action - say, a mouse click - then the main loop "wakes up" and delivers an event to GTK. When widgets receive an event, they frequently emit one or more signals. Signals notify your program that "something interesting happened" by invoking functions you've connected to the signal. Such functions are commonly known as *callbacks*. When your callbacks are invoked, you would typically take some action - for example, when an Open button is clicked you might display a file chooser dialog. After a callback finishes, GTK will return to the main loop and await more user input. :class:`Gtk.Application` will run the main loop for you, so you don't need to worry about it. A :class:`Gtk.Widget` it's also a :class:`GObject.Object`, so to know how to interact with these signals you must read the :ref:`GObject Basics `. .. seealso:: `Library initialization and main loop`_ in GTK documentation. Properties ---------- Read: :ref:`GObject Basics: Properties `. .. _Library initialization and main loop: https://docs.gtk.org/gtk4/initialization.html ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/clipboard.rst0000664000000000000000000000275715074673150020701 0ustar00rootroot.. currentmodule:: gi.repository Clipboard ========= :class:`Gdk.Clipboard` provides a storage area for a variety of data, including text and images. Using a clipboard allows this data to be shared between applications through actions such as copying, cutting, and pasting. There are multiple clipboard selections for different purposes. In most circumstances, the selection named ``CLIPBOARD`` is used for everyday copying and pasting. ``PRIMARY`` is another common selection which stores text selected by the user with the cursor. :class:`Gdk.Display` will allow us to access these different clipboards. You can get the default display with :meth:`Gdk.Display.get_default`, then get the clipboard that you want; :meth:`Gdk.Display.get_clipboard` for ``CLIPBOARD`` and :meth:`Gdk.Display.get_primary_clipboard` for ``PRIMARY``. You can set any simple value like text with :meth:`Gdk.Clipboard.set`. For more complex data you must use the :meth:`Gdk.Clipboard.set_content` method were you have to pass a :class:`Gdk.ContentProvider`. A content provider is usually created using :meth:`Gdk.ContentProvider.new_for_value` where you only pass the value. To read the clipboard values :class:`Gdk.Clipboard` provides three async methods. For textual or image data use :meth:`Gdk.Clipboard.read_text_async` or :meth:`Gdk.Clipboard.read_texture_async`. For other data use :meth:`Gdk.Clipboard.read_value_async`. Example ------- .. image:: images/clipboard.png .. literalinclude:: examples/clipboard.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/buttons.rst0000664000000000000000000000357115074673150022276 0ustar00rootroot.. currentmodule:: gi.repository Buttons ======= Button ------ The Button widget is another commonly used widget. It is generally used to attach a function that is called when the button is pressed. The :class:`Gtk.Button` widget can hold any valid child widget. That is it can hold most any other standard :class:`Gtk.Widget`. The most commonly used child is the :class:`Gtk.Label`. Normally you will use :attr:`Gtk.Button.props.label` to set the button label, or :attr:`Gtk.Button.props.icon_name` if you want an icon instead. Usually, you want to connect to the button's ``clicked`` signal which is emitted when the button has been pressed and released. Example ^^^^^^^ .. image:: images/button.png .. literalinclude:: examples/button.py :linenos: ToggleButton ------------ A :class:`Gtk.ToggleButton` is very similar to a normal :class:`Gtk.Button`, but when clicked they remain activated, or pressed, until clicked again. When the state of the button is changed, the `toggled` signal is emitted. To retrieve the state of the :class:`Gtk.ToggleButton`, you can use :attr:`Gtk.ToggleButton.props.active`. This returns ``True`` if the button is "down". You can also set the toggle button's state, with :attr:`Gtk.ToggleButton.props.active`. Note that, if you do this, and the state actually changes, it causes the "toggled" signal to be emitted. Example ^^^^^^^ .. image:: images/togglebutton.png .. literalinclude:: examples/togglebutton.py :linenos: LinkButton ---------- A :class:`Gtk.LinkButton` is a :class:`Gtk.Button` with a hyperlink, similar to the one used by web browsers, which triggers an action when clicked. It is useful to show quick links to resources. The URI bound to a :class:`Gtk.LinkButton` can be set specifically using :attr:`Gtk.LinkButton.props.uri`. Example ^^^^^^^ .. image:: images/linkbutton.png .. literalinclude:: examples/linkbutton.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/check-radio-buttons.rst0000664000000000000000000000163615074673150024445 0ustar00rootrootCheck & Radio Buttons ===================== A :class:`Gtk.CheckButton` places a label next to an indicator. Check or Radio buttons are created through :class:`Gtk.CheckButton`, you create one or another depending grouping. :class:`Gtk.CheckButton` can be grouped together, to form mutually exclusive groups so only one of the buttons can be toggled at a time, this create what we usually refer to as a radio button. In addition to "on" and "off", :class:`Gtk.CheckButton` can be an "in between" state that is neither on nor off. This can be used e.g. when the user has selected a range of elements (such as some text or spreadsheet cells) that are affected by a check button, and the current values in that range are inconsistent. For this purpose use :attr:`Gtk.CheckButton.props.inconsistent`. Example ------- .. image:: images/check_radio_buttons.png .. literalinclude:: examples/check_radio_buttons.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/dropdown.rst0000664000000000000000000000305015074673150022424 0ustar00rootroot.. currentmodule:: gi.repository DropDown ======== :class:`Gtk.DropDown` allows the user to choose an item from a list of options. They are preferable to having many radio buttons on screen as they take up less room. To populate its options :class:`Gtk.DropDown` uses a :class:`Gio.ListModel`. :class:`Gio.ListModel` it's an interface that represents a mutable list of :class:`GObject.Objects `. For text-only uses cases GTK provides :class:`Gtk.StringList`, a list model that wraps an array of strings wrapped on :class:`Gtk.StringObject` and :class:`Gtk.DropDown` knows how to use it. :class:`Gtk.DropDown` can optionally allow search in the popup, which is useful if the list of options is long. To enable the search entry, use :attr:`Gtk.DropDown.props.enable_search`. .. attention:: If you use custom list models with custom gobjects you must provide a :class:`Gtk.Expression` through :attr:`Gtk.DropDown.props.expression` so :class:`Gtk.DropDown` can know how to filter the gobjects. :class:`Gtk.Expression` has been supported in PyGObject since release 3.48. :class:`Gtk.DropDown` stores the selected item from the list model in :attr:`Gtk.DropDown.props.selected_item`, and the position of that item on :attr:`Gtk.DropDown.props.selected`. To know when the selection has changed just connect to ``notify::selected-item`` or ``notify::selected``. Example ^^^^^^^ We are creating a simple :class:`Gtk.DropDown` using :class:`Gtk.StringList`. .. image:: images/dropdown.png .. literalinclude:: examples/dropdown.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/entries.rst0000664000000000000000000000623415074673150022250 0ustar00rootroot.. currentmodule:: gi.repository Entries ======= Entries allows the user to enter text. GTK provides a few entry widgets for different use cases. Those are the generic :class:`Gtk.Entry`, :class:`Gtk.PasswordEntry` and :class:`Gtk.SearchEntry`. Although none of these widgets derive from each other, they implement the :class:`Gtk.Editable` :doc:`interface `, so they share some properties and methods. You can change and get the contents with the :attr:`Gtk.Editable.props.text` property. You can also limit the number of characters the entry can take with :attr:`Gtk.Editable.props.max_width_chars`. Occasionally you might want to make an Entry widget read-only. This can be done by setting :attr:`Gtk.Editable.props.editable` to ``False``. Generic Entry ------------- :class:`Gtk.Entry` is the standard entry. :class:`Gtk.Entry` can be set to show a invisible character using :attr:`Gtk.Entry.props.visibility` and :attr:`Gtk.Entry.props.invisible_char`, this is useful to hide the text of the entry when it is used for example to retrieve passwords. Though :ref:`password-entry` exist for this specific use case. :class:`Gtk.Entry` has the ability to display progress or activity information behind the text. This is similar to :class:`Gtk.ProgressBar` widget and is commonly found in web browsers to indicate how much of a page download has been completed. To make an entry display such information, use :attr:`Gtk.Entry.props.progress_fraction`, :attr:`Gtk.Entry.props.progress_pulse_step`, or :meth:`Gtk.Entry.progress_pulse`. Additionally, a :class:`Gtk.Entry` can show icons at either side of the entry. These icons can be activatable by clicking, can be set up as drag source and can have tooltips. To add an icon, use :meth:`Gtk.Entry.set_icon_from_icon_name` or one of the various other properties and methods that set an icon from an icon name, :class:`Gio.Icon`, or a :class:`Gdk.Paintable`. To set a tooltip on an icon, use :meth:`Gtk.Entry.set_icon_tooltip_text` or the corresponding function for markup. Entries can have a placeholder text, just use :attr:`Gtk.Entry.props.placeholder_text`. .. _password-entry: Password Entry -------------- :class:`Gtk.PasswordEntry` brings some features for password handing. It can show a button to toggle the visibility of the text if you set :attr:`Gtk.PasswordEntry.props.show_peek_icon` to ``True``. Search Entry ------------ :class:`Gtk.SearchEntry` is an entry specially designed for use as a search entry. :class:`Gtk.SearchEntry` allows you to implement the popular "type to search" feature. You can use :meth:`Gtk.SearchEntry.set_key_capture_widget` to set the parent widget that will redirect its key events to the entry. :class:`Gtk.SearchEntry` has the :func:`search-changed ` signal, it differs from :class:`Gtk.Editable`'s :func:`changed ` in the sense that it gets emitted after a short delay that you can configure with :attr:`Gtk.SearchEntry.props.search_delay`. This way you can get reactive searching without over loading your backend. Example ------- .. image:: images/entries.png .. literalinclude:: examples/entries.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/examples/button.py0000664000000000000000000000221515074673150023543 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class ButtonWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Button Demo") hbox = Gtk.Box(spacing=6) self.set_child(hbox) button = Gtk.Button.new_with_label("Click Me") button.connect("clicked", self.on_click_me_clicked) hbox.append(button) button = Gtk.Button.new_with_mnemonic("_Open") button.connect("clicked", self.on_open_clicked) hbox.append(button) button = Gtk.Button.new_with_mnemonic("_Close") button.connect("clicked", self.on_close_clicked) hbox.append(button) def on_click_me_clicked(self, _button): print("[Click me] button was clicked") def on_open_clicked(self, _button): print("[Open] button was clicked") def on_close_clicked(self, _button): print("Closing application") self.close() def on_activate(app): win = ButtonWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/examples/check_radio_buttons.py0000664000000000000000000000256415074673150026250 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class CheckButtonWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="CheckButton Demo") box = Gtk.Box(spacing=6) self.set_child(box) check = Gtk.CheckButton(label="Checkbox") check.connect("toggled", self.on_check_toggled) box.append(check) radio1 = Gtk.CheckButton(label="Radio 1") radio1.connect("toggled", self.on_radio_toggled, "1") box.append(radio1) radio2 = Gtk.CheckButton(label="Radio 2") radio2.set_group(radio1) radio2.connect("toggled", self.on_radio_toggled, "2") box.append(radio2) radio3 = Gtk.CheckButton.new_with_mnemonic("R_adio 3") radio3.set_group(radio1) radio3.connect("toggled", self.on_radio_toggled, "3") box.append(radio3) def on_check_toggled(self, check): state = "on" if check.props.active else "off" print("Checkbox was turned", state) def on_radio_toggled(self, radio, name): state = "on" if radio.props.active else "off" print("Radio", name, "was turned", state) def on_activate(app): win = CheckButtonWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/examples/dropdown.py0000664000000000000000000000176715074673150024077 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class DropDownWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="DropDown Demo") dropdown = Gtk.DropDown() dropdown.connect("notify::selected-item", self.on_string_selected) self.set_child(dropdown) strings = Gtk.StringList() dropdown.props.model = strings items = "This is a long list of words to populate the dropdown".split() # Populate the list for item in items: strings.append(item) def on_string_selected(self, dropdown, _pspec): # Selected Gtk.StringObject selected = dropdown.props.selected_item if selected is not None: print("Selected", selected.props.string) def on_activate(app): win = DropDownWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/examples/entries.py0000664000000000000000000000610415074673150023702 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk, GLib class EntryWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Entry Demo") self.set_size_request(200, 100) self.timeout_id = None header = Gtk.HeaderBar() self.set_titlebar(header) vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) vbox.props.margin_start = 24 vbox.props.margin_end = 24 vbox.props.margin_top = 24 vbox.props.margin_bottom = 24 self.set_child(vbox) # Gtk.SearchEntry search = Gtk.SearchEntry() search.props.placeholder_text = "Search Entry" search.set_key_capture_widget(self) header.set_title_widget(search) self.set_focus(search) # Gtk.Entry self.entry = Gtk.Entry() self.entry.set_text("Hello World") vbox.append(self.entry) hbox = Gtk.Box(spacing=6) vbox.append(hbox) self.check_editable = Gtk.CheckButton(label="Editable") self.check_editable.connect("toggled", self.on_editable_toggled) self.check_editable.props.active = True hbox.append(self.check_editable) self.check_visible = Gtk.CheckButton(label="Visible") self.check_visible.connect("toggled", self.on_visible_toggled) self.check_visible.props.active = True hbox.append(self.check_visible) self.pulse = Gtk.CheckButton(label="Pulse") self.pulse.connect("toggled", self.on_pulse_toggled) hbox.append(self.pulse) self.icon = Gtk.CheckButton(label="Icon") self.icon.connect("toggled", self.on_icon_toggled) hbox.append(self.icon) # Gtk.PasswordEntry pass_entry = Gtk.PasswordEntry() pass_entry.props.placeholder_text = "Password Entry" pass_entry.props.show_peek_icon = True pass_entry.props.margin_top = 24 vbox.append(pass_entry) def on_editable_toggled(self, button): value = button.get_active() self.entry.set_editable(value) def on_visible_toggled(self, button): self.entry.props.visibility = button.props.active def on_pulse_toggled(self, button): if button.get_active(): self.entry.props.progress_pulse_step = 0.2 # Call self.do_pulse every 100 ms self.timeout_id = GLib.timeout_add(100, self.do_pulse) else: # Don't call self.do_pulse anymore GLib.source_remove(self.timeout_id) self.timeout_id = None self.entry.props.progress_pulse_step = 0 def do_pulse(self): self.entry.progress_pulse() return True def on_icon_toggled(self, button): icon_name = "system-search-symbolic" if button.props.active else None self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, icon_name) def on_activate(app): win = EntryWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/examples/linkbutton.py0000664000000000000000000000102215074673150024414 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class LinkButtonWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="LinkButton Demo") button = Gtk.LinkButton(uri="https://www.gtk.org", label="Visit GTK Homepage") self.set_child(button) def on_activate(app): win = LinkButtonWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/examples/spinbutton.py0000664000000000000000000000277615074673150024451 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class SpinButtonWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="SpinButton Demo") hbox = Gtk.Box(spacing=6) self.set_child(hbox) adjustment = Gtk.Adjustment(upper=100, step_increment=1, page_increment=10) self.spinbutton = Gtk.SpinButton() self.spinbutton.props.adjustment = adjustment self.spinbutton.connect("value-changed", self.on_value_changed) hbox.append(self.spinbutton) check_numeric = Gtk.CheckButton(label="Numeric") check_numeric.connect("toggled", self.on_numeric_toggled) hbox.append(check_numeric) check_ifvalid = Gtk.CheckButton(label="If Valid") check_ifvalid.connect("toggled", self.on_ifvalid_toggled) hbox.append(check_ifvalid) def on_value_changed(self, _scroll): print(self.spinbutton.get_value_as_int()) def on_numeric_toggled(self, button): self.spinbutton.props.numeric = button.props.active def on_ifvalid_toggled(self, button): if button.get_active(): policy = Gtk.SpinButtonUpdatePolicy.IF_VALID else: policy = Gtk.SpinButtonUpdatePolicy.ALWAYS self.spinbutton.props.update_policy = policy def on_activate(app): win = SpinButtonWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/examples/switch.py0000664000000000000000000000214515074673150023533 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class SwitcherWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Switch Demo") hbox = Gtk.Box(spacing=6, homogeneous=True) hbox.props.margin_top = 24 hbox.props.margin_bottom = 24 self.set_child(hbox) switch = Gtk.Switch() switch.connect("notify::active", self.on_switch_activated) switch.props.active = False switch.props.halign = Gtk.Align.CENTER hbox.append(switch) switch = Gtk.Switch() switch.connect("notify::active", self.on_switch_activated) switch.props.active = True switch.props.halign = Gtk.Align.CENTER hbox.append(switch) def on_switch_activated(self, switch, _gparam): state = "on" if switch.props.active else "off" print("Switch was turned", state) def on_activate(app): win = SwitcherWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/examples/togglebutton.py0000664000000000000000000000172015074673150024745 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class ToggleButtonWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="ToggleButton Demo") hbox = Gtk.Box(spacing=6) self.set_child(hbox) button = Gtk.ToggleButton(label="Button 1") button.connect("toggled", self.on_button_toggled, "1") hbox.append(button) button = Gtk.ToggleButton(label="B_utton 2", use_underline=True) button.set_active(True) button.connect("toggled", self.on_button_toggled, "2") hbox.append(button) def on_button_toggled(self, button, name): state = "on" if button.props.active else "off" print("Button", name, "was turned", state) def on_activate(app): win = ToggleButtonWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/images/button.png0000664000000000000000000001600515074673150023330 0ustar00rootroot‰PNG  IHDRdw©Þ-sBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timevie 09 dic 2022 08:40:18Ö@HWeIDATxœíw|SUÿÇßI:èLtQ–@K‘½A–²EÅÊr=¢">è£ ø¨ˆü È,X@¢H)¤”ÝÒ½'m¡Mòû#Mš¤I›¤¥Î;¯ûJrï¹çžóÍ=Ÿ|ϼ @ @ w!’&§@ ¨ªºŒ¬. ¹©8„€ )Á¨•X[¸ Ï“˜yL Ԇ 2ó˜YXZ¨ „¤šÏÖ^G X1‘PUóÙØyÕbI6‰Î&5ønJ@Aý`(º›Òà»aø1·P `Û„x ‡1ÑPšØ EE÷|“ؘ‘S†Lç]xÍWÀ¾"n!Aý£+åÀM ÈrEŦÔy×=WB âQ“pŠ†Æ£Ðˆ… à ´ýySø£={tŸ„wTB(‚Fƒ•J©Ê=sê§G'MÚ\n  •â¡Å£¦nX5Ñ [À£gÏž½6‡oX%‘ ·:c ^PAÞø çÄÆÆžr€2Ô¢ñBŒU]ªPpèzOæb³\{ôèÑë¦ ß©TfUyA#@‚¤|Ì„‡§ž9sæ(PÜB-åè·}€ ñ¨I8Œyv¨Û0:Ç_¹ÂÓš’Üà6ížÎ nш‡1Ï£ RS±|Öˆ‡¦Šâµaýډњ(*÷×~ÿê [Ôe[†~o(˜p.j.®[E±Eíi8í¯]¹¸QîµN¿@ hTJeN«v.%¨=M›‡ac©ÕµMëIш»D¢r«Ûi3 >‘H¥î¨ÿümÑo$•RCÏŠ¹ã8 …Ã¥èrš6* àˆ~UE3€³ZÌñ8 …ðΆ@pG`Ge¹ÖÍfQã¨SÕY$Y 44ºeÚpʈIŒyƦÅЇ´Ž× ƒîôS¢QÅó0gȹ± m2¡Á®h› jSÂa¬/WWÃ…Ë—µß]œ]ð÷¥]ëÖ8::6`ÊVbX®•{‹ºcuOÖDH„Ãa9‘¿àZBB•ýãÇŒbúÓO˜ÏÁÃr-> ãÆàáî@~~[vDÐ2(aƒÕYš 9y:–‘{«ìwuvfÊ““>ä¾ÛvmÁmÁª5tÌi5Œ¨â³±õAÄVó?|ùë¾úŒ9Ï=ÀÎÝ‘Þ(2;Ž“§O³3r/ù…ùÚ}EÅEìŒÜËñ“'ë%³ŸÊꕲxá<8vEÅÅ|þõ·D?Ñl|çmž˜Â‚w—PPPù›²pñ{LxbJ­~KL¯ìg’š„âªR ìlmpuueİ!ø ,WpâïÓ„oÙNZz:eee„oÙÎÞý8CBb2{=Ȧ­;((*â—½¿”œFø–휋»¨½žR©äÄ©XvìŠäHÔ1nÜ(ÖËÍË#|Ëv2³²¹r5ž‘ûøýÈ_”——W›w77ZøzÚ‘iO=άéSX³öÿôÂeeçpà÷?‰Ø³+WãõŽmÙ±‹³qÈÌÊfïþCüvð0yùÄ]¼ÄÎÈ}ŽA©TêWxãG¢Ž±cW$'NÅV9~'àÏù¸‹¼µt9òß%Ëùç\~~µ‰Úª²lé¬ÖÊ‹¨ª %¨ž ±OMË 3+‹°ÐŽÈ]]A'OŲ{ßo´oÓ_oÊn•þó6Zµ bÄÐ!üÍõÄ$öüv©TJÿ>½Ø­Ž”ÂÞ†L*%¤ý=äæå³ä£z…ÖÓÝ·æÏ#8(œì<ÂÞÆG¢HNMÕ†ùõÀï,Y¸ Æ€»›œ­;v±~ÓÏzaŒg¸Ge$œî>¥JÉÑè<ÜÝyü‘ øµðeêSãîæFÜÅK”Þ¼©=¯m›`ºu £{·{éÛ³)iéÕä¢ê= ³Q trvââ•Ëãæ.ç¿¢8ôÇœP($§¤hcrpp`èàtìÐŽÆС};:…v¤Ÿ^t í¨NKz:WâHKO§OÏîôëÓ‹À@fM›ÀßgÎ4øï{»_2™ v¶vZûÛÚØbkk[«8­Ex ÀÄq£™4qÓž~œ—gÏàX̉:¿N^~>7oÞ«¹‡¶ª •JñõñB¥R‘Woô<¹›zµ…BaÑõRRÒJ¥ø·ð¥¸¤€ââb’RRIJIÅ×Ç›}{ãæf|57¹z¿RUÙfá®Ù§T’ž‘€—Wå?l _$ ¹yÆór§›—¯®ª$&àçG€Ÿ)iiüwé ’wëWîmÖ£Ó>Юukò Š@…zÚPPTT¥¡ŠÍ•ªÊ}ï*Uå>'g¤R)i(J¤R) …‚ø„Dd2^žÞ¨’&ô]šªi7òùXÌ Ò33éÚ9 ;[;|½½puqeÞ‹sŒÛÀT¾ŒíS¡nB-PšãW®& R©ðõñ¾£ïÉŬ )9…??-œÀÛK–“”’Ââå³â½Eõšáq4 ¥¥RIn^ž¶nÞ©c{¼==uãdüõDüq¤ÊùrbN¦¬¬ ׊}—®\#?¿…B !Ú“Ÿ_ÈëÃIÏÈ`kÄ/””–Ò»{W¤Rëþ¼‚|2³²¹|í[#v³bÕWØÙÚ2ó™ÉÒÂLJ —.óËÞßP*•ääærþÂ%«¯Ù&8g'G¢Oœäàá?IMËÐÚ¯OEõêNåZ|­Z±há|ÜårÜår-œO«–A\K¸^ïé©ÅZ¡w°¼ßf¦ÌzQï{`€?3¦>¨¸o@?¶DüÂÙóqÌ]ðÎNޏ8;W„TÛ|Pÿ¾ìÙ ›·¾e_¬X†—½ºu!úäßLñ_ êß—Í~Ž™SŸâÝå±g{öÀôÉObÚ¥©É€Õk~ÐûÞ*(fNÇ×Ç P!“IyiÖ³|ø¿U|³îG¾ßNyy9îr9ß®Z©­:™¾FU—ÃÉÉÙÓ§ðéWßñéWk´Gú÷îÅÈaƒM¦õN`Ûúïu¾©óé.weÅ{ïêí«/ŒuÁè/׬¿Ñ õ¼}—Š­Ïå gWÔW"ïöí?Dn~e}ÔÉÉ‘€-èÜ)Dïß?7/¨ã'±³µ¡{×.\ºr•ÜÜ<6X&)%•S±g°·³§W÷®¸É]Q*•>NfVÁ-ƒè ¨ÛNÅž!+;ÿ¾téÜ íµöø@?úõî À¹¸‹œ9wž^=ºÑ*(P/ÇþÃ…Ë•½-Í== ð§M«`£LÑbbÿ9KfV6¾>^´ n©íغs7R©” cG–žÁïGŽÒ¶U0Ý»Þ @ÌÉ¿¹ŸÀýðöò #3“3çâ(-)¥Më`:ÜÓΚŸC´mú …zÑâB (E%°*•V!Á]ŒµÂ!Gň6@`1¢WE XŒÕ‡ð7‚»ÑÆ!,F´q‹mÀb„p‹£ÀbjÑ8*¤C ¸[U@`1V{ÉׯÕe:AÂjáè=pEydgePZ\‚RiÙŠQ‚J¤Rxxùàìj|…,CîfÛ {YŽ563E-Æq@fZ ¹9´ ÆÙEŽL&žEm- …‚¢ÂÒ’(-)¦¹O‹jÃßí¶ö²KmVV GQA¹9´ é¬]ÛA`=2™ ¹›;ÎÎ.\:K3G“ÿ ÂöÂ^Ö`ÌfÖbuãhvV-‚‚ïêâv ³±Á70˜œÌ “a„í+ö²slVV[²´¤'gW³Ÿ"0gW’ã/›<.l¯°—åÔd³š°ÚãP*”we=±>Éd(ªy¬¡°½>Â^–S“ÍjBŒã#„C XŒ@`1µlfM ‡°½e{Õ%µÑHÝpÛ[†°WÝÒhª* …‚sçϳ=bÂ7òÇ‘#ܼu €Ä¤$6lܤ ›ž‘Áöˆ]fÅ»-"‚ /Ö.¯ €o¾ûž¬¬l“aþŠŠbWä³®Û”(**"êX4Â7rèðájm °ì^½SiÂqåêU¦<7“…ï.âØñNÅÆ²ü㕼½h1ׯ'²>|£6ü¡ßóþ‡QXXXcÜÛwDw±æç•æçåñõwß³nãÇoݺŢ÷—ñË/fæªipôØ1~âIV¯ù– —.±æ‡uLxl›¶lmè¤5J,½WïT|(]VV6Ï=ÿ"³ŸÎcLÔ{¦¨Ba|"Ò£æþáÃp©xÐr]²c×.¦?3·Š'£kصg/yyy´4x$bSæÒå+¼¶à?¼³ðM†ªÝÿëþý¼»ô}ä®®Œ¸x¦°qaͽz§Òࣟ~ñC dÒ£«Ä)“IÑúœú=9%™?ŽåÉIjÃ*•J¢¢£‰OH¤]ÛÖt ÁÁÁAç|õ¹¿î?€B¡dä†B}¼[×®lܼ™YÏN׋ûÿÖo`Äða¤edè¥13+‹£Ñǹy³”~½{ãïçW[“˜IímÿÙê/;zÇÑ‹ïþaC‰»x‘ÏVÉýÆ •J9v<wwNž:…››;û÷ÃÑÑA/Îè˜._¾ŠŸŸƒôÓ>OVs~y¹‚ÓgbqttdØÁ89Z?_Â2æ^Õ{ö,gÏžÇÓÃ~}zá¬}8Ü(.æðŸ’™™MP` aBðôðпtù §þþG'' wnCÑàU•Ãaü¸1cè–””0ç_sùjÍw$&%±ê«oØûÛþ*çüý0|¼’Ð&ãž6åi6oÙJqq‰v߯ûâãåŽÃôž<õ7SŸ›Åùóq\¸p‰ÉÏÎ :&Æ¢¼4J¥’˜“'3j¤Ñã<4ôŒ ’SRˆŠŽæ•ù xgé{\K¸ÎšÖ2mÖ ‹´ñ½öæB¾úæ;2³³Xóü<ï5í0ï¨èh^˜û ¬XÁõÄ$6lÜÌÔçfqóæÍúÉp`ͽ °ì£¼ýî®_gíúõ<ù̳¤¤ªíšÍ#O>ÍÎÝ‘dçdóóöí‰:¦=wCø&^{s!Éii8t˜I“Ÿ!;'§Îòd- Ú«’ž‘Áâb‚«KsÌÔûúðMØÛÙóÅ'+õž˜®Òq6ÎÆ]`ÑûËùè½¥øT¹žæ{XH(mÛ¶eÛΞœôkׯçÅÙ³HKK׆U*•,Yþ3§OãÁqc éȪ/¿¡ç7=¬5‰ÙÔÖö)©i”••àçg4.oìíìˆO ÀßTàïïǪ•+J¥”––2uÆL~Úü33¦=CäÞ_9w›7"•J)++ã‘'ŸæÈÑcôïÛTŠeïpãÆ ÷ ‡üÅð!Cj—3h¨{õè±cúãO6ý¸gg /Í{•U_~Í’wþËÁßÿÀM.ç‹OVV‰')9™Ï¿úšðu?ÀÛ‹³þ§¼ôüœÚe¨–4¨ÇQZZ @qII !«gÿ¡C<8n¬žhè’ž‘Á¼ù ø÷ ÏÓ­k—ã›6ùiÖ‡o¤¬¬Œ#E‚„¾½{ë…IIM%1)™ÒÒRvGîawärr󈿞P«¼ÔåååÜ*+3z\"‘ ³‘aßÌ^»Ï«¹—ÖÆÍš5cìèÑœ:}€¨ã1¹w»#÷°ï·ý¸ËåÄ'TÚÃÙ©ÒÅvrr",4””Ô´:ÏÛíÀÚ{õ÷?ðÀÐ!¸TT/d2O=öÑ'Nмys“’Ù´e+yyyzçž<õ7r¹+±gþÑÞcH¤\»~½rT;´q4Àß®\½Š_ ëINI¥¹‡»Éã;FAA:´7+¾^=zàíåÅ/{ö¹‡©“Ÿª¦ Hí¢çæåi?L›2ÅÂÔ7 þ~~H¥R®_OÄÛË«ÊñììlŠ‹Khd2ooíÍ^XTÈ­[e¤¤U AÿþýèÒ¹³Éó›ÌŒUkïÕ´´tºÞ«o???òóóQ*•Ü7ps_|õ7±âÓÏx`ØPžŸ9__ ŠŠ ѳi`€?Á-Mÿ&õEƒ6ŽÊdRºÜÛ™ÚÈÀþý¬¸žú»““#YY&Ó3aìX¢cNðÆÂ·Y·ækœª‰[ýþÌä§Yòþ2\\]6ø>ƒ¸Uø·ð`Р„´7¤ú( µ»†Œ°N¡lˆ G÷®UŽGDFÒ¦u+¼š{b˜w Ù9Ùøúú ±G2©Ì˜6µ†´~VÑìeí½êáîNJZªÞõsssðñöF*•*ž0ž‡'Œç\\Ÿ®ú’EË–ñÅ'+ðkáKIi ÏNlÄ›nXÁmðÆÑW^z‰Øþá£ÿ}J™Û¬ÔLû•Hªíî eçîÝ•á H`á¯akkË;K—šõ/7h@?î½7Œ™Ó§­É]]érogÖ®[ßdþ5 yiöL~;x¨Ê`º'O±öÇ üû…çõºcÏœ!¿bìLyy9‘{ö2 O_ÈѨh³ÆÌ4U¬¹W{vïʯûè ªÛ¶3‚Aú韄tèÀ˜‘ž®nKëÞ­+$lÚ²íveÉj|GÛ6­øäÃå,~9&,4[[[ÎÅ] ¬S(ïügB;’_PÀ§«VóÈêÄ1{ƳÌyùßÌ~ùßt ã\Üî:„uZÀøð½ÅL1›uë70õéªÕ]$ ½ÿ^µa^Ÿ;—¹¯Ïgæ‹/Ó«GwÒÒ3ðpsã…Ù3­3F=Ó9,Œw¾ÉòV°mÇNÚßs‰ÉÉ\¾t™¯Í£w¯žzásrs™<í9úõíÍùóq¸¸¸2nÌ(ztïÆcbÎKÿbÌ葸89uü8/{OÛÛÔ±æ^qÿpö8À”3

½z2ø¾ûÔ‹·H%tlßOOä®r:…„š–FÇöíõ—’“HhfoO·.Õ5žJðòô¤]Û¶€Ú 7znr9ÅÅ%´mÝš1#G`o߬Ö6ÉLOÁËÄb²Yé©Ô•íÛ¶nÍø1cðóóC*‘0°^œ3›ú]ÖÇŽÇàãíÃŒiÏPVVÆÁ÷1ëÙéÈd•6ìÛ»7½zt§´ô&vööŒ5²¢D};øÑ2¨¥6¼ m[·ÆÇÛ§Öù¨/{Yz¯º8»ðÀ°a´jŒ²\AßÞ½yaÖLÕÕåíÛàçB¡ÀÙÑ‘'ŸÄˆá•cŒÚ´n͈áÃJ¤”—+èÕ³'}zõª“…‰2ÓSøúÛï÷IÀ­Š­ (”›QwZbbŸF44‚Ñ p\*¶>'Ž^rïíïv¼[9w:†Ž»=v>ö$õmûO¿XMvN.ï.|³^¯k.Í^Ms§cèÞwÐ+@PX±¥è H•†¨9*°–ú¶}}6dÞšjº' Þ8*š Þ8*h¼ÜÀ# áq‹+€5Q„í-CØ«n±Z8¤R) ¥™‰ù!ëQ*&çÝ€°½!Â^–S“ÍjÂÒ3µMëÍ(.,°úÂÓЬ™éu*„íõö²›YÕ]V“p_•T.rO2Ó’QÞe+ÝnŠrÒS“qq÷0Fؾa/Ë1°™ñ `5‰9‡nDÚÑd.r9N.r®^&tEXtCreation Timemié 14 dic 2022 21:54:11ǹ§ IDATxœíÝyXTeûÀñïÌ00Ã&"*‹¢‚¸ä–ZZýêõM­,³,s/ÑRs)—Ì0×7µzµLË4MsÍ}·Ò5wsÃ]Q3d×Td‡™ùý1Ì030 ¯ÜŸë:×À9sžóœ¸yæ>Ïœ!„B!„B!„B!„°CQ†í•vÛBQÞ øúžÜK2UØ<Ún“D-„¨h ØOЛÇb)I2µM–ß[~­,I‡„â˜>ïÑ2aÛ&ï‚’yŠ“¨mGÐJ‹G{ ZUœŽ!Ä@—÷h›°õvÖ[>ÊÉÁƒÛ5+m¾VÚ¬—µ¢¢Q‘Ÿ˜MzŒ9± ä\d²vdDm;Z¶MÆ*òµeÂV;жBìÝÆÔæ­ã2žBˆb²¼õ†½ ˆvëÔ•>lߨÎ[œÍ‹äi!„(.g‹Åò]Š*ìßi'=°öì?Àîý‡¸CzF:~ÕªóÔ­éòr'º÷€V£aÉ7³ËäØEµ?bÌ"£¢P*•Tòô¤a½ºôêö5ü>NVV6:].¥RYäú²`y. …‚*ÞÞøùñÌÓÿâ©'+Óc‹Š£Ä‰ZÔå“^¯çÓ_r4üjÖ¼¹Ã՘زù@·ÕþKÏ?GN®Ž§ÏpðÈ1.þù fáprýíBöüƒ™Ó¦R'0°ÈõeéÿkR© þÚ5Μ?Ï©³gÙÿÇƼ7ì¾_<ØîaD-©º<Úôã6ކŸ eó¦ ò6žîî€1gç˜n•kòO¥jãú¯uÆÕՕ̬,Þ2‚[‰‰Ü¸u“êU«³}{Ÿtdo}Y0¶?t@_\]]¸|å Ÿ|þ=ÆÎ½{i÷¯§Ê¸¢´uîJÃõøpä»xz߀’šÊô™³9{>‚Í«–Þ×þHéã¢×ëY·q Z­–ƒâ‘—¤ÁXbи¸˜¿ÏÉÍaþ¢e8|•RÁs힦Çk¯˜·gfeñýêõ9NZF:Õ¯Oÿ¾½ÍIT¯×³qëOìÙ›·©X“]:ópÓÆV}ÊÍÍeô¸ˆŒŽæƒïðDëGïê·ÆÅo//ô:U«TŒ} ¥~H0Ó&O`ѲlÝþ+ŽÎþC°ïàaF†M@©T²qÅbfÌžkw½©Ï¶üÈÞ‡¸që5èÙåZ6ojîK~y¢õ£h5>†Þ §C»§éÙõU‡!ÁÁ„öêά¹óùmÇns¢.*¦=ú äñV qÑðÇÑã(•J^x¶­iÁwK¿çÒ•H|ªxóö›}hÔ ¾Ãç$Нf.D\bÂÇÓ˜2. …BÁ¤§M ÇËs¥¥ä<ƒ,åm‰‹¿FfVuƒêàáîQðsÔÔtÂOž¦VÍ$§Üaõ†Í?e~Îg³¾fÛ¯;¨_¯.­Z4'üÔi>ùlz ðí’ïù~Ízru:mÙœÌÌL4Í]Ûå«×ÍóÏ´ã‰VZmߺí6lù‰¯¾Y@l|<¯w ¥Bi€lóý­ZX³Ú·¥Ç« ]oêóеP©T4oÚ„¿"¯2eú Î_¸duŒ]{ös,ü5ü¹s'•5·püÄéciÕǼ¥uËæÄÄÇ;S€ß÷àÄé³ÔðçvRËW¯cDØx²sr¨RÙ‹è˜X>ÿrÙÙ9ŽŸ“,Å^þ3æ}ü|«Ë„©Ó˜0u‘QÑTóñaâ˜Q%o»„dDý¹vý:žîE<<Üܘýù§8«Õ¬Þ°‰Õ6söB-›7#2:šã'OÓ²y3F½3€¬ìl>Jüµkh5~Ýù;þ¾¾|9m*jµý»Üž:{Ž­Û~¦N` ý^ïy×öÕ6[}¿éÇí4¨W—ºAAEöÿñVpðð¢cby®ýÓæZtAëoÞJä׿S³F3>þ•JÅo¿ïa΂Elúq5¨gnÛÍÍ•93þ‹““·üȲ5ë8{þ-v|”ªÕjÑjµddd¢Ó鈎‹+4¦¦Qš››+sgü¥RÉÊõY»q íþõCôàÝÑO\|î(ž*ÞÞLÿ!ã§~JTL,U}ª0y|Õ||î{îábâ=ü{e¢Šwe®_/òçã¤vB­v€zuƒHMKÀظxŽŸ8Eç^¡VûÝIMåúèõznÖ§¼6leeçðå7 0 êß×|,K+ÎÅÕÕ•ŒÌL–¯ZÇößv²zãƽ?Ëá‡i?ël~k¬í­¿ƒ^¯§yÓ&(UJ xòñÖÌY°ˆ˜¸8«ý•J*' „Ô3Æ&9åN¡15Xõ²³³ÉÌÌÄ·zU”*e‘15í«TªP(R/ØøK¡R˜·‡OJênݾíð9‰âS©œpV;›¿W;©Q«ÕÿH\eDý ð÷C©Tr5*†¨˜Xj啊¢rRY}ïžWÛnÙ¼ý^ïaµ­šGއ¿Ñü ë¬v"¨N-oßfûo;¨Ww`ÏÕj4ty¹#ÛÛÉ…‹—¬¶étE~J‘C23³ŒíéuæuYYÙ( «Ú½-'Uɪƒ§ÏÇ`0P«¦qD_TLí±7ûEeÑŸ’ž“(Úí¤d&~<ظxó«Øøx&}<Éãèìu?ÐJjÔÐâ¬væ…gÚ¡×ë™ùõ<®]·ÚnY ½k‹Ÿk`€?J¥’K—þÄÓ݃_?ó¢vRã_Ý€ã'O›k¥¶m)P0¨_´Z-»÷äÈñ“veZR’ïàãí pqvA¡Po>FNN®Õ¾N*ã?˜´;©VmÙ[_3À€cá§Ìí…Ÿ<…Á` v`ÍBûfw]!ÛþfѲU(•Jº½ú²C1µÛ…¬+Î9ÉRìeÊô/ÌIzòø0&£†¿?±ññL™6£äm—Œ¨0½ºuáÂ¥Ë\‰¼Ê°ÆQ;°&îîDÅÄÒ¢Y†x³È6¼+Wæ¹¶O³}ÇNÆLšÊ¿Ÿ|‚›·IËÈàýwS§v-5¨Ï¹ˆ‹Œÿ7mLtL Ý»t¦AHˆ¹*ÞÞ„öèÆ¼ÅK™·p1 ?û77óöu›·¢vv&99…c'OÐéyãmÎÕj‚k׿ÏÈHÂ&N¦²—§Îž³êgíÀš,\¶‚G[ùÈjÝýbïnM–wÉ3ÝãC›·¸î@ë?/žûâ~uR!uë7z8 ¤é@FÞ’Cþç(šîùa&·+Bˆr®ä¥yU%„÷…Ô¨…¢œ“Ò‡B”sr›S!„(ç¤F-„åœÔ¨…¢œ“µB”s’¨…¢œ“‹‰BQÎÝÃÅDIÕBq?HéC!ʹ¨ã¢#K³B! PâDÝú©v¥Ù!„Ò‡B”s’¨…¢œ“D-„åœ$j!„(çJõÃm¯^¹ÈõøØbíSÝ¿µƒë—f7š’Äë×HIN$3#V‹g%oªV÷ÅÝÓëîaù&ñ+ÇÒQj‰úê•‹ zþõÌ‹(•Ž Ôõz=gùzå¢$ëRy9‚”äDüü©‚›‡'iwR¸y=+—ÎãYÉ›:! þáž–O¿Ò!q,=%þpÛô´T«·=¼og±’´‰^¯gïo?Êt¿RqæZWW4iQÄóÂÉHO§A“æ÷©gÿ$~¥CâhŸ«›û?ÿá¶ÅMÒŽî³k÷^Þ ûN¯u£]‡Ž„x›Í[ ßÀÁlýi[±ëˆÂÚ.Ëã–Täå‡þ84iÖÕ•ÈË>gÂä)<Ö¦-µiËãÿnÇK¯uç“Ïf””Tâ>fggóX›¶ÄÆÅÐ3ôM–­XYâööìÛO×Þo°~Ó–·aR‘â§×ëY½nýÞBÛç_ kï×Y³~c‰ûe©"Å1-=¥+V:àmÚuèÈ‹]ºñß3IKK+qßì)÷§~:ÙßÌã™vmùjÆçÌ›ó¯½Ò//©mYJMI"%9Ñ¡?“MZ’œHjJÁ¿ð¯v~‰Û~àç­›˜2q".2qòÇ¥ÑeÚ<ùÔ¯W¯ØûE\¼Äá#™9{YYÙ÷ÜŠ¿»vs,üï ÈŠÅ‹èݽ;_ΙËÎßwßS*Z333‰‹O`øÐ!¬ù~OšÈ¹sç™þŬRë”òÅÄÒöëŽ];y‚‹¿ÃÍÕÕ¼>$8øìUùtãú5üü‹½ŸŸ 7®_+𢎳Z››Íš6æ½aï0døHÒÒÓ­~&%5hÀ[%Úï‡mÛyºM:wêȨ°±÷ÜŠ¿ömÿͳíÛš¿ïüR'ÂObßC´{úß%îOE‹cooÆŽeþÞǧ £Ggäcî¹O–Êu¢^¸d úõ-ò~’Í?üDäÕ«Ôð÷çýÃiÖ´1999Ì[ð;wï!3+‹6O>Éð¡CpuÕ˜÷_½n[~ø[‰·iܸ£G ÃÏ××êiiiôüíÛ=Í[¡}8pè0«Ö¬åï¿oðPÆŒ~o5kÆ—–ËW­æ§í?“x;‰¦M›Û]¸d)»÷îcé‚ù¨T*ÒÓ3éÑ'”ýûñb‡%ŠUJr"µ‚BнŸOu?Nvøù …'''rrr˜ûíö<Èß7nQ½ZUúõyƒçŸ}Æü|NÇ·ß-æ—;IOKç‰Ç³j¯ßÀÁ¼òr'^êøPxÜ,9¼ØçZ˜Š?{%ÇÊ^^ÜJ¼]œÓ¿KE‹£=YY8|.Ž(·¥ÌÌLbbãhÜè¡"Ÿ—Àè‘ÃØ¸j=ÄØIÿ!''€_}MTL,‹çò…ó‰gÎüùæ}M?ŒIãÆ²bÉwth߯J•¬Ú×étŒô!!Áæ$ pãæM¦þgË/ÄÛ»2ƒ‡$33€…K–±k÷>üKÌÃY­fèˆQäääÚ»ºÜ\ÖnØÀ‚Å‹¨Tâ$ ™‘a¾ª^nžæiS…1 ÄÅÇóÍü…¼òR'\œQ«ÕÔ`ÚÔ)¬\òŸïÀ”O§cÞoîü:r”Ï>™ÊÒ…óÑh5…¥ð¸•%‰œ>sއÜÛ쫊G½^Ojj*‡eÖW³éÕ£kñP„r›¨ãâ0 Tv Ý©ãó4¬_ŸÊ•½íÝ“[‰‰ÄÆÅ‘–žÎÖ¢ß>T®ìEµªUØ¿{öŒ xÉò„Iƒúõ¨êãóíÛ¢Õjó7˜ñÕlÒÒÓöÕq;wêHpPüýü6…BÁÎÝ{ÈÎÎfåšµŒ5’à :øû3iìÒÒÒØwàjµš°Q£X¸x ýÁ¶_~cìè÷K5~¥eõº æ‹8]z¾nYXŒf»t~™ :Æs íÝ ?_Î_0^ÊÊÎfý¦Í|8ú=B‚ƒñóõeä»C :ŒjU«Ò¨AÃR=ÿr[úð©â @\\ž Ÿgéçë‹V«%==ƒè˜ôz=c&NB‘71W—Kzz*ñ ×ÈÈÈ a!£ˆ·ÿÌ…‹—Ø´z%.ÎÎ>ÏÙÙ™fMM\Â5rss­.NhµZ5zˆ«ÑQ<ܬ Ï´kËûcÇ3ql>>U>G{\4ZÒî¤{4“v'¶Àí]_íÌ»ƒ¡×ëéݯ? ¥õŒÎ¤¤$~ݱ‹SgÏ’œœLâíD²ò^UÄ'$ Óë©’ÿRØÞ|PGâVV*rün޼Ŵ39ìs¸¤*jû÷ åÍ>opí«×o oÿ¬X²_ßêœ}ÑÊ툺R¥JxW®Ì¡#G‹½¯Baüôw7͛˦5+Ù´f%?¬_Ë®íÆiu©©wãË–‚<Ò¢®Z-k7=uÉY­F­V““…^¯G§ÓݵÝÅÅÅü}@€?z½çÂ_†9³’7¯'{¿›×ð¬Tð«•J…³³3†7zõ`õºõ¤¥§žžÉ[ƒßáÆÍ›ôïÛ‡iŸL¥np]ó¾9ÙÙèõúBãkÉѸ•…Š¿¬ìlÂ&LäÑ–-yñù’—ÞL*jÁX÷ð÷gÔ°wñà×]»:ž#Êm¢èÙ½++V®&.>¾DûûùVÃM«eÿƒv·ûûå…‹ lÃ×·:“'ŒãûÕkسo¿õF‹#3 œ¿APÚÔ0^P‚^¯gê§óz¯ôêÞ† ðÕÜy÷+J^¸{xq&Üá}"΄ãîá…G!#KÎÎÎôîÖ•UkÖ‘žžI•*Þ¤¥¥±qóV’’’øeÇNþ¼|Åü|7­–ŽžcÚŒ/8á·o'±xÙ÷¶_TÜÊRE‹Ÿ^¯ç?B|B‹N§###ƒŒŒ ÷ðy¨-ŽÇOœä«¹ó?yŠk×®süÄI>Ÿõ%±±q´ùדÇ (¥š¨}iáè>NNN|=súõeÇï»0týeã–-¤:øÎŸ~o¼NhïžÌür6í^èÄáïqñâ%óöña£ ®S›·ßÎK]º±rÍ:RR’í¶Ó¼Y3ÆL˜`žÙñH‹‡ ?‘®¯÷!:&–9³fâäd,û¿7ü¬5ŒŸHï~oq'%•YŸOC¡P°bÍZÒÓ3èÕÍxeøýï²ã÷] ?áhØî¢R©¨DZZšC$gÂIKK# V*•Êáã¼Ü©ë7m¤VÍš 4o/¡ëë}Ø»?­ZYÿ"þ.-›7ç½1ãè3` 5køØ~aq+K-~ûâ·¿óWd$_íÊÓ:š—ë×ÿvø|lU´8V«Zœœl¦Ï˜IÐ~Lœò1·™7{ÕªVuø|ŠRj÷úøëò hиE±oÊd0@PHé^%­¨222ˆŽ$õN~þøT÷»ëf8 ñѸ{xáXÇz†‹ø•‰£}%½×G©%ꬬ,â¢ÿâÆµâÕ“«úúTæ‹*’ÌÌLRï$“œx‹;)Ide秺h´xxzQÉ» î•ÐhJ¯†ö ‘ø•‰ãÝJš¨Kmzž‹‹ ATõ«Y¬ýîÇýŠF£Ñ V«q÷¨„N§CŸWsT*¨T*Ôju±^fV4¿Ò!q,=Ž&jÛ« v Ë...’tË •J%÷@âW:$Žw±Í]¹-ª˜l°ùÚ`ç@B!§'?Ÿšš° KÔö’´å"„¢x Ë¥æUG¦g˜²¿ÞbѺ‡B{tXçR‡ªE%j½Å£©ARþBˆ’°Ì¡–IºÐœjïb¢íܲ6­Ã8}$×ÕÍý]À9oQçµ¥"z_Ù¾CA!ÊËêƒ)_æÙyKnÞb™¬msí]%¢f}Ø&iÓš¼Å”¬ÈOÖ ÊùÛÓ…¢ ˜’¯yPK~’ÎÌ[L‰Ú^²¶« Dm™Ùíýw0𱨮BFÔBˆŠÍ6gêÈOÔ¦ÅôÆËzu¡5 Q”¨-“°åzËD­@µ¢â±W…0½ëБDmWA5j…Åצ*°NÀ¦m–£l•ç !DEa926%bS $Çf±­U[¶a¥°µé*¤ëdmjÈ´Î^ÉC’´¢¢²W°¬YÛKÒwÝßÃRa5jËò†Âf›e±Ü²Üaª[Ë…D!DEUдfË„my1Ñ2A»Fm:ÒNC¦Dm9жM˨ZQÑØ›Ölï ƒÅzÓKa#jÈ/{X®75n[ê’‡Bä³}«¸mr¶-yxA±¨Äj™|-Ëö’³m¢–¤-„¨hìÝ#ÉòkÛ›Û™¤Á±dj›€•vÖK‚Bˆ|öfqX&c{åä9šT ª;K=Z! g°y,jý]Jš`e-„ŽsøÞÓB!„B!„B!DyòÿÆÃƒ~´Dz"IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/images/dropdown.png0000664000000000000000000026326615074673150023666 0ustar00rootroot‰PNG  IHDR8/bÜsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timevie 09 dic 2022 10:18:03ª˜Iø IDATxœì½wÜvgU&z­{?ßÒ !"„RPÆŠŠÎOõ¨ã9þ,sz@QŠbÁsFgœù©Ã¨3Ç‚‚±  ‚e¡$„fH# $¤Bò½{­óǺ®µîçK)ŸæÙ!ä}Ÿw?{ße­kõuÛ=äE €ÁÂÀ† òs˜ÁÃÌ à ‡à6àø˜ ¸ˆÈ10b„€çûÍaXb0¸9G`0``‘¿Vð˜åË" ˆˆÁ—, ˆ X¾88@DÎÃúùÖ³8%,>`†Æ÷æ¸×¸9–ÐèsŒˆC®k˜±p^η0bá¬ù—ÓãߎC°7úiÃ×g«µÁà÷€‘oÓ^›!"×B#"× |ŽrªÁ .Ö0CøŠ0ãûµb€‡60¸WáZפ7‹°¼'ø=·Ü°ÁÈuÑ^™aDîSÒ-wГ¦ÌßëXôÓ €i¸n¤S³iOsNn@X` `p°È½Ì9®€†à¸„ÍF­éØsÃb8¼Á8#"©À87ϱM†(äña`ˆÌ´ì–kˆ07˜Ü뺇XW˜€5髨~aXÉ †€cY`#ø ˜{X ’®#½yX \Ãü¢f¢/ÑK®÷™ü:"ñb^ƒ\ÁÜU¾ÏcÔL6¹åIØa·üas|Nð~²V‘/3'ˆqâK¢Gɨ¡±E@˜Ä0Ü€aü¾áGhƒ [;üÕàdD.‘(!¸.ˆ(†x'QÕ—ÐPª¹qÎÄÀ|žñ)DfÀF´À6çËÍ/áQ0 hÄœK/‰,$R2VH~[ ÖóppQ,œs4´f7ôM‰(ê­¡Qq{íF«õ³shý¼”¶ÇéäŒ$|ÑÄ’_ ä»ÈfZÙš·žfH†Àô~GX¯fÓ rÜl«M7=IޱµvIŽ%,wHd`Nyªõãò[äÎÛ\TYÿ/Ñœ8H`¶À‡!Ö±Æ4O¿›†kïZä9Æõ0ã,Lo…(%y†ünäC œ ]̤c$¿“çB¼Ì9NÜÚÇ%„5"€V(pù¹Œ>ƒ–?K‹ˆ”Ä B%IŒZ̘Ü@XjÒ¤ŠP€—„‘{2×gÞö@,À ´vÁ‡ÖZÒ#µ%1on‘´&«…³Æ;*L$œ`”[>spôÔ0ŠE8«ûE<0AHj®N@̽¢äaÖO(̓Ÿç»“¹’ɸÖa^) vã\0iÐ?#Œà,9RŠr s\„‘%{=Àƒ„<™Ö˜SˆÐ0G`Í‘™£xgç"¹·ÜDÐ’Ð×u»v“÷×ßÂ,+Ô¦€ˆÔ Ss5j=HáÆõ“k#¨aMB¾4åHa#ùhpOŤú„‘à[Š'íYÈí ÈÜ»œ³DVQojžÔ%Æf¯q`Áº®8ÜE»A9RÃNЖ–·”R@š[U)¢+ÖQƒÀáE 9æQ´™k!àKa@$Qm-Gßf%Ѧ&PÃàaØC2ý(k*A óRìG5—H푱r¡¨­ˆ¾¹ i.%1„€lÀà|ç€aP½Ý3GËwa·¤fE™Àõ<W ©ñˆ1ELIÐB£”æbŠd„àF#¬„µ&Ž €˜EëM#µ3±EI`:#xšQ’4øPGÀ†¹KîFiV dJÀH H¢º9š”ˆ–«_ia·ÃjSÄHAf\O›‘Ð…I*¹§"{‘­9¦=Ÿc–‚HÚ-ÌB|h†8È €šM F0Dîa0º\<'Çê;6 ‹ˆÖ@Amµ„£è²N ‹5m¸†y­Ù(:0”?gpü0ÈXIT¥C…§àõ\» ÆãõNÃf\.ƒcMˆo³ÀlÁ&Ö½X¾Âœ÷U˜XHQ 0kí¶4á\[¯ß[Q¨šxL$º"¨ÄxRͬľmD*C„{ è\¥Æª¦®¤õÕ€ˆ1Ib) B΃Eª‘® ¹8Ìé¯%2}“Íœ¦%YÙRæÃW>ŸòÅ¢47ù 1ŠT‹h`H_R©–¹ðÁ ;ýn6½Ÿbò…ɘ. ähC¦Å6n‹³á$`äS¨38}RˆZŸˆ(ÿƒÖ8•YªûƒB ²ÀܹÞÉ@cŒ"`pí+—3jŽè–WNüi^‘ðÌFi ¥i–€Ë-p2É(C¹jýC²#ýU5?¤/µá©¡¹QãàšÃ­aþ»æn$]ñÎa"ÀͨpþX8P—)ÁÒþMÊ~Å]šs ²Éã4 ½dÒê¹vDϳ©–À?’@¤^–FDÚÎ禵a<iåØA¦·Üi® jç¨5—VYÚt½:Ò‹€}ØŒu݃XsCéœÐ[PôkmžÔÌ0Ý›ÏÔoiapýõµ›µ_˜‚@"“"ªx͵r Vk’ä‘ôµYĸÖlG• Å€ò/ ÏBtíkÆè“fƒ”0Xœ„Á§B$‰=oF:DÃÒÄtJæQ*ROPž»oYx¬ƒ_£i`šXI\a¥gr¡“øÒt˜a«8®f.G¯Æ“[±R­S@ †•Œî5M‰$ùÙ$1‡‚.@¾'4Ç”jØ–rÍNA ´ð¸âòY ý ?Ôô¤ZšÊÈŸ™j…$©qm„Úžø®´Ì¿þ¥µÛ(ÁV+ àÒØŒ¢+’å‰>M¥ ñÕXô3Š‘óë2õ ZøO@ ²¿4&K •‰˜tε†¼šAðJ3é_l+ÍYÚš'ïÑt•#À*'-õùËf#E%ßKÐÑ©F¦¥ø¦ÌkeaMô˜GjS§TéÇÏ’n2/Åù¿öí…‡|1Á蘅g„ŒÄa%{«œBFà&¬‹’Σ€®1qïo 4i"ZÑÁæÉlÖÓxÛí›ç•,+³Ÿ d­©€÷i<²&Ê'g‚(›îë¥nØ›Œ×i|V1ùÚsˆŽI1š䟜…¢`£z¹@ElOIÁ?“±¬™Vë\“áÑB»>$5$©P0]B Ê×|ieyi( \6,cof0ß`ŒÀfo`ÏW¸ïAJ=&iY!M•·Rlrö²‚l^‘RÓ4.:ÛŽµ™.+÷½FœþI=3ƒ #æ Ing©ô€"a1EÿÂ$c¨"Š€DQc¤V1ù¨DMÐ?80‰rI”´¬0šzzt/˜>ý¹qíK«yÀT9ét Äù›Æ- ä·Ð–Ži#@%éÕgiÂjãAߊîA®œg‘tCÐþT®Ì¥0NY)šgÐW5ŠŒä÷ ™Æ‚ežÖŽPÒÇDLFB§9^„gÈñq¤Qk~ÉO‚ÃÖˆk•*=„¯«ÀLƒoI¤%J¨Ìó·hï[°ñ=ì­@¸§ßR›§±“—"²´äT8]+A(NS´´k˜Ðé3a†Í‚FmÃrÄ[d:†3>éK׉‚æÈ}Ý ÃØìúçX×øÚ‚]ÂCÁ‹°À §kE‘lµøës\{°ØÀ½V΄s+=L˜f$"ƒ‰\¯뢄(cð"°‰Zà€G`!"‹âƒ iæJ–¢ÔIÙà܈«1´¹üž£Ð?„ JGÏ\VÃ:({R!ÜKVÒ§äöÌ6®„ŒZÛ"5 †¥¿ü(šW“Vƒ‘P©Ý-]LQ|E_Ÿ@'eŰCBѰˆ(~$‹L=qþ^à:Öv…ÞѾE …’Fs‡Ì{€5ÇAàË15h‹ÄD>(j½…L !®ô{‚ÚJ0@eŒ‚P:€èuh9Ph ò$”Í|š¯'(*é/•Ý8µF)½6i|ÒÚÊg®WTˆ#)mÉÜ5ÃH-òc+Ê^ÞhZ¢Ÿ°g©À,•ö!÷&ј`8€±&¯Ú€Ù‚u±\Ú±îØK­´ŒtÙIÏ^>LÒ,5âr5Uв-Á_æÚBî3É Î[7úƒÁºŒ"w¸õeIÅúRN@Djš€L”hm.¦2ˆœsb üý;AI¦@ͰIiÀ:iµlðöþHgª\82Xhß'Ç&$øNÑ x_‘ ¿Ó‚'¸ð¨9R¦µn;ïÐ4º&ÌÖnDÆÂi%˜ÚÄß2ÎS‚Ú2}ªµS©5ìÖí(¾¢½MšA‘µŽ $¡‰Hï°y@@í™Ì ˆè­ç/D5Ñš)s±WÉ`YfÄÑ&ÝO£T9mƒ1UÅ:GKƒ¢mŽ”æ˜ ³ˆ•Ù˜t-à1À}J) ÆËÇW¤K -× ƒ9rgôZç¤ñj÷lkôå·3½2Há6=±µ~Q–W s2ùO-”OH&)í˘% Œa°½ýðu±¦®Ö¯h¬_•–;ÜãB J1 h*O4_k+ X <Êy;• ¼ ȹ'ßR.‚c(Z_WF/ -6©^׿&K(Ÿ9hªˆáÅè>i`’.Ók¨)Lùw"‘@©ë±Ö°IS»úþ-†%YiåDÌ»€AÉžZjðÒ]+¿‰†{WP]’É‹½Na 1@éQ"C3dbuEÛ”—?G•{1…BÛ?-4´}bÌ9“v\™66 ¤}ƒE”¯¤aÁ*2[rÜÃà0µÎ>9„µI­òå–pI$+¡—îQ¥J8]ôM€¥êŽV ™’bÐÏ¥¼*Š?m–VAðú<`òI»aȧÇwÕ·mlÕØ€ðÖ(‚–H7Ú%åoö˜¤HÍjµ]Ì/g9×(jW@"jÎÉeåØÌëóÙ¤•Ë@ ¡ú[ ­¤+ Ñ*µÐÍ€}ˆ±—~9Љ—Õ7C+°ÄÊ% Äü-ùÖ€lù1ƒ¤¡­üU|_È‹6ÂP™û–÷' JCâ̘§“fw^Á!­Ã™F1õ, ”Ë¥•‡Ö`ò©KùŸ»ÈŠßÇè“€¥3ËZàL†¸/å6LÆuóì(LJ¹ÀÈá÷ÖŠîËüàž¬É=X]‚…ÿð2|MÙ@æ–÷1Í2éÕ„ %SXψl-µf¹‰“Ï ñ(UR€w7X`1cƒ±1øº•ÄdI+'«­0Sçã¥òÝœ…ŽY¡£àb°à`* ,¶GÎ9³úÊœ!Í%§>d”p ÂZ*:bÁâ} AIPù](êÈÚêIþèX»‡W(¬µ Ùf‰ JX>‚ã·–F[© ˜LfxEÇÄY‡§)R³)sÅ€1&çñÄ4eÚG°ä¥ÿnÀôþy>ô†dé°–”s›;SNEÞc[9tñ-S½ÞÂ÷‘É`lP{“oRɤ GLÐÊ|D2’l°»WiâDîy䇯Ѭ“+p@ÄZ­Ãm‚#«(ù¤mMÏöaVûôÃŽ‚g>ÇdîP6je'ÿŸ‰nKC³å3Yœ±?@m¢¢Íu./VËά\,å æ¾¸Kø’ƒ|T0,¬È ip,”Óâ½…RkG>5唉bÒ–,…yÔŒäi“zÂVvB&/ƒópµ @©?˜m°X`,ÛX÷î@Z#âÍ*7ª\ÅÖç¶óÖ*à8ÑÙÂW'm0IE= d¶)˜`R!ÅŽ˜IQÏÁVp¡61rÀP¿ j:ów ¬[#án˜œî)N ÇÀ¹°ìõí´Ö%ÊËù¤ä”&ZÍýª•ƒA&J›Èt¼#%tš Zei¨šÂ‘B“N(Φ>Ç-Ƕ|‹U¡ºÜÁõY¸7nL# 4^ä¤ƒÕæ¶¸‰Ú½1å3ɇV¦ð,V¨·XPs ªP;¢ "ÔØ5oƒ1ßJD‡rWXÍ>1lCAæU6—4°€E7 š”áÚŽžG!”A¦$À¦Á"xíì ¦—HGIMCu O¨«,(L‹¯Ô% ÙÂ.Ò–IŒéé´Î´ü¥vòÃ:‰Äa ú`¥F»n pæeÖ"º¬’s^$ñ+ê(Ech¦Þ !\*%Èc,—JãHÚd”Åçy[ ~ž‘¥¨¤×ЋbIþÛ‹-ãy>„¯wÒ"—m ·;L{™ëÉ6jˆâ_xË41…I#jÁëqÚþmFÏvÑÔÌ…, Uþ -¤TlvÛŸ?I@ž¼ ŽJÄìÀ $ŠF)lF`«CK*šePçØàçù÷üâ*¶y^’ò©ÁŒ¤%›L M q}J Ò•V$Rñ0j¬ F 3èRävÈÊ,.™W&YŽ}á;$€-×+¡ukŽ? ‚–¦J†.À„è&÷2J{ÐØúÑŠÁÎr¹Á½Í¦þ«LGªÈ¹/ç3ZëX_œ“Ú-2€Rß6)¢ù—%ïúS^ŸÞVë‰2éJÙ–{§Lè, öÏÓ^[Ñš8E¾í¦ï~s Ì5ZÃvÀË%órñ»ƒsõ(—Ô¶«dÚÐ(j@D6ÈîW[{ƒL{AÅ'´¦–lØ7ÜWøÞšµË¡ÜǶ´ô(c«™-w¾y@C ¶Kªé2BBG¡MÀ$ˆ)‡ß,UõÈYƒä ædܦ.ûDxUwiÈ &')f–Ä¡gI{õAyb9ÕQÄÉ :hGƒ›înéniÁåØGM•ªÁ väÚ,}Cs”ôÑûsPäµ¶¡´«–ðÁÜY}5¦û«É éyÍd¹EÔ Eô‹A-Só;ëË ¨O°>°Z IDATç£Ë‹°Bó´~’R|t€Lt¸U¢ùy1zÁëv¢ê˜„^¦$!-C‰ÐÚI.2T] Já1BýXß–0EšLj.ë>¹~U†”À¤’ƒ£¡j¨ 2ý–@®5Öj½í£ç™Û<ä£òVÊ¢™ ÝßeªÎ«V´¹«ÜTå’RÙZI±[8j'9wCJ`cäIzëc]åוƒd›ÖÊ{gµ?ʳ“›,'³Éÿfr+\E°¹Õª¦nšxHeÚÿ%IB‰C‘h ¦ddZDÑDüi)es"Ýö':"HÉÜ‘7áoð…ùœ$~Sêiô³''xHêlOÎM’'§6&óO’¤S:´¥IÔ¹Ønêð(Ó1Ï9P×ÒþF?C‚h3ÂFp¾{&œ„yΟ~ÅPËWÓ‘ˆ$ú¬ÖuhÅvñ°JÄ÷X‹Èrï0åµGý F“œÌAï0éYƒ´ž’‚œª0*MÅÒŸ”~´®!î•&Ù[¶<¯@ÓöGØÔ€Ù°šò¼rçVD÷ü—CÞ‚À6(:Yô†°¥*´ÝUlÊ¢õù ŽÒ·P7‘Õ=¶2ªQó©3@ɤNmù0‡Ç@ø2Em9È‘ëYê{ ÈüqÁt@ꦦ(÷ŠUš–jQËÚJ~WôÖ'© š.R!Œ¡±ˆ‚…ác`Ù ØÞß»X½üì‰)òHv‚1ò.›Š¼$9ÖbÀ”}¥äŠÑfñ–£Ku0Ú“—43ˆ‘¸ÞÑPzˆaTËëüžœúD{Ïn$yx‡2ûL‘›\ƒ@¨ýJi* LZ ›èÀAPÌm‡§§u ¶´dÏ΋Z›œ7“E+Ø@Id)ñ“ç‡,—¤½Pg¬<<ˆ•&BÎsÈÄ,‰N¢Alo ç"£ (ˈk…Cù3˜ ì©íf+ Å&d1°5Ž4zýAt2( ÙD³#û…é»!ÏV ¾Œë]£!´NfË9¾HãA ’Þ)À¸18(.ó á.ým¤ãܤ‚Î,ÏÛú~·Ó¤ĭ÷Y¾jâõĘÄiÀ8çîh¹R fâѮF UB Ѐ¸!Ëü´?é§Z4^º„“‰FEOâ/x) àþ‰Ï«å’ÍkÜ´° Ì´§ÎG«]— È¢Í>–À½ëÞ _³‰„´æ6ìÔ†éÜÄ#ßµQÒRÔ M%7ª0¹Ö&øˆÂá¦VD•$+xéfF¨¾cêVí‘YAî•Gk”Âê ’êj;ÕZ–†'ÿýC uW •¸`e:h~’Š*\*ŸA{‹€£žËtjUƒ„ºœMFÎ/¸â2²9,{ØG/J%–°^%SÔ¯ PÜoêYh ô}IH>ëPeCq4?5$È¡RW3Ày¦ƒ× €T޵ܓ¤1iPØ2FjÎ)  \B­XÊs\§‚|Xµfìqgšôú[€ÌÚé,‡PÜØºwú|H°p¤M&y’=ÒÑ;×f«—ƒ%( ¦V6Ê$r ­XtâqµÈ²ö¸Un›i7iõò©¢è× | Ò±ÌC»Jg-W”¡ÎÑ€p8i©ö—k2 ÀfÆ€¯{ð=ö/ ¢Ñùv‰Mm3­”€º‰Lw›BÏ1-vIý)ÅoôE./£¥jn8K(ë)7—Li´ÛïÎvÐJAHRƒlúLDR¾)LFܬ–Ë¿i:ù<ù#Ä#m!6°F}GC&ãP%*““óÖÛMŒ Ô30˜6l­UVÆv¿ƒ#ãC´,»ÃI+Èg/ó\, ¶çbJ-P&•öS³¥VPâ˜õ¼Êç¨qP³ª¨^®UÖ 'ð¥ Ú©Í¢“ (`.5w¡@ž˜4†°Òh\|ù_·š…¯ ^»â€@–ÖM $¬UÙD˱u»±‰ÄË;ûL[k1®r1_ãQÛ>9ÉËA µ ËÀÖጨF®1H‰‹£h&€êÜ.‘á¢õùÔ:€¼ã&Ì_ª+ø½jÇ6ÿ™€#ý‰—šoåôf°ØŒ Öð=Ö=À'^!{tY_ës€a“±6%¢¦T¯˜.9 £Ç–Ÿ—Mfñ)‚"  ¶³Ö"ÕkuãÔæU˜xü="󞘭õ6bb8 .oT»p˜ ™dž¹°êT[e_pZ®\*kbm‡®‚–v!¶I]¯ý’’¬ddk&i}k2‹BLªg,µN2‡kü©‹Úc^ª-–æ†㤿Bæ‘ös”o»Ø™¼©À“É”3±N/ê”…LmÑÇH&s0J«ÕË”g% R»f‡ >y˜4ƒº˜$v¨ªà®®˜Ö«}8QëÐt[†?µ¨¶P»ïŸ\2—1 ³3Á3Ê´€Ù2 KIÞÌ'“_»Æ+õ  %¿rÌPÅëb›dCHOK‰ÖQ¾Jj‚â«™v$ç@à3¥N׷ꥂ™ius]¸§s9¥—`Z˜ü·šÿX cA¬–ݺæ˜Éeݘ7{ÀbûáÖ"JFLeBY½;J"w×ÙtÊäSÕ¢eUªÔ^„¤Ó†•Ï’ÀÌ)UíP¤I8¢žH'´¤¸ºû.Ip@›ÜªªÀ¶MpÐŒa2æ AYkºoŒLzUE”ü~µ½ùž*c¥0Þ+zPïàÔfä ÏÑ¥ÀOI‘7Gki*›·¾€¦wƒ2Ñk`;(r‰ÑAod5-MÅ­ÓŽÅr™àŒ2çÅ1޵л³c®ÎÚ튙O ²$Xý’}æƒô®ŒÖ±“eõI÷㸩3skkŽ´þ¼ ó¹ûHûÓ’™ÒD5dôfiÛwšÝ`ÐHÍÆ¬3ûCHk³{ ´^‰›×¶ É•@lHÓÍjmüA'Ù‚ŠÌ·'5YÓ¹˜kd"wušË"c¡FOúŠ †™ã^-Ÿ”n" 8Yr9.c¢œË<›f·‹&Ä\‹¥|eøÀØ»#™u’Ka @°¤©6XGtŽ+Y¼Ø°$dYöÂ"æ»$Vð>«A¤ÚZl˜„èiFåbŸ491Eevq¼&â·~VUoK‚Ç,‡f“3¨DN™R–£l_ZžSC±’® Úe(+ø…ÖŠ²_^K[ó€×ùÜDJk¥„À´ÉVɤ–%µÊ4¯éÞ27F‰[íQõÔ?$&™#Œ‰Ðý¯2üKF; ŠP¥ÂÖZ§RþÇ–ÆúsMšgbÈÌ­ÑŸ[å–$MS PTm®s®>ʖ쬦‘ja5ƒ²´O ¯|r[* Ê¤åËŸJF-M- óKJÓTwŸEj¢©Åõ@FHEù|å~´ZÏI?²L6dQ»…³xNË—˜„+)Ük{Ë–n&*&¼Iû,±±¤º§¡´í ŠYªÅXohõ†È£>˜#º´6'ó¯‚Iá9®Lâ·}‡›q‡§6§Ã¨(¬$ 6-½ŒNíËA–©©…VLQ´ÈiMEhÞÆ—òØB‘‡´ xšGˆÒrÎÝ~F¥6d†Ù÷‚é½ ÆÙ?¾- (ž“ï­mðàhÐÇòI‹YÐ~ p㌥,2׌fP‡-‡ÌÁ±m"8ADD†ä! M+¿WóJ:M¹Ô~´2‚ì–úõíP&¯îOaÁ,|(jGB‘&ÕDùó¢ù¡ÁJø$@uÕ­7(UwYÔúV x,EØ :üW{Ó{_£ÃU¯*ä iá2ûÒzØàå[mN È¬xI•Þ/ˆX°gªfŒFI( -É8èü¶ äØäãj@—PV'° ®¿16û¥C¥-ƒ}ü„b–¹vZëÐ@Èk ʉ®S쇤<”-! }¥­òH:£T ÇRIÊ@I fо£\aRˆÀó6äã±#àûŒedÙßž+]i¤MwÖ×åcKês1†Œµ¢3ÞO˜ËY*1˜&STÀ™’š«¹esˆðJíÓT•)°åï‘ÆÔÝrÏ¢ÔªÖ6ÁèSk)Q;ÙxŠ£ï›¡Þe¹>Cë%€`¿´ƒúç h À[ÖÆ—Q­Ž¸fb¦Y{+ñ1¦lú6Ѐ×f3²%& è`jD%ØEm}fC¯»>‡©´GCÈÃlÖKÞ­r£r5Ç€´·òÅ jNM[žž2¿°×’è_?JûFôú‰$Tn—E/Š‹vuJ>Ó¡úlH „mH'|Õ>H¬eP@G(¶¹´ £©-@&ӡܵöä>C>`ù Q9µFC+qOà[VS%® }`x§jtZÈLƒóGñ—„NX¢ylkM–{S™|†Íê é3Œ³ † ¸­pVE¨ÿ¦Ta.€KúÕƒš1øº-ç§6qŠd×—h¦ä•¯"¤úëÞhuRx…ú+AÓ* •bB@Sò'·%7<Ðïìµ™‘Ëâw1PdªJú^ŠLkÃËÓæÏ&Wi½9•¨mÀ†oØÌ3%dçUzÞQë¢Èj±‰\þ°$C-·FRZIsz›¶Që(½CWÉ{ë¼Ç¯|¶Õ³õÜn{c6%¹½ÈôMþµ¬Eä½í€ÌÖ›(Ñ `Ú?wõàËgU©çAÎÚSÇ÷L1¨ó†NzR®GÏß³* |4€: ;PîˆJÑbZÓp¨š$?MáÒUÒ2%r3 [Â$jO±Î}Â2`ž#|ZŸ\÷dÓÎ:p) “r£æIbÈódµßM×i} Öôg[W#…³}”Œ¢†É6Ÿ£h#Ùa°òC‹DØdÓGì š­kvÙÓð„Ì ’O ˜´'ßC­z&ª“b¶Å€Ê×)STÍ"íÿƒžW;`4›21pÌ6I-ù‡Ô+EðŽÈ2ÃL´•ÚœcôN~¯ô•sˆß¸³ù—~E9¯s-VI“VÎõÝÊ ™ö<÷¾|„Jɱ d¹±Ô€·LMïꜵ½ÉÛXé:ajœ}½*Ó+ÈHCšsºêKøÑoHr¡ È$ì\õjQåe­r&caó'ê#}‘*¾HÓ.[gËDÔ¶ó?ÙÉe¸ÃF¶øòÊgóSsv¤íã$’žy8õ#(ÈÕ î ¤äÙ!ùº)TóK¦zc€µ‚ ^n‚“]Q`£×J£KŸV1VÄV‡ˆþdÎOŠà`¢9_k ν ¨Óµ¤frï¸Y%þý‡Xî{¶Ü’‚ ¥Å(ôj›˜£pX\–Œüƒ©ƒOÏË)}ÏÂ`ËÀf,ðuïíaÓfŸ|$„ù f íèK¢–¶‘w®ÅwüÔõ Õáaò;´LÐ ËRМ›ŒÅÊ_+­en¬ØZJ9'KVwBn:>£º“˜Þáùù"È ý‡”iX|’˜õÝ&Yi<Õ]• Ï¸¬KÙ¶”°åý‡ùl_rΤ?"AÌåX (z€nOÕ¾KéãƒfC¾zE¦)1÷:C 2»•¨kÓ¼´ÆÔ|”`¹–'9™Î0€ 2àqÃ6¼Ë˜šˆÀ¢–褽Ü;jãî9¿ˆ¾ ú[S;êE¹×l;U (¬aˆuü³¤¬ÈDfÝKd*% |Žt@• VÔ2,ýš•M‚í6Êå»US íqÒ½@jM_€Ÿ„šæï(ˤhˆ–©jq>û½=<é¨4M›™|4Êu£ª‰lPÙ ]>å+pe;'3¡däâki‡rã‰3ò_Æ*ŧ}Òm¦s7"32 À² ˜íÃ&¼0´¥~è—r“È©IL‹“$’Ža-€@²vsèú"%»YE@¡0B&òV\ÌNF•M1“=òÞTô)Aœ!èa”°±ÁäÄCgTÏRF gíüQcEùjtš»Ê+”®ÍEµÕ%Qn°¼g]v’o^¡ž÷]mÒyyDpKòª(IéÅ(u6™ßTMa¹ziN:*//ÖÞÑÞ|î ¤=ÒDÁvNfdê\/c|‡+i.É#Ïj3 §æm®}•¬]³Æ Ò4VŽ+Y¹ŽY ¾æª/Ô CÒ} ¸Öíîn—A2a·üAý-…\Àb`‘ÀàŸË9kiØÒ¸š1×-^Éfž˜Ü.é§4Íìb-¹ïxhúÊG,U@îœIF§“§ÌxÔÞæ^¾äÁEC¿óðlHhÅìKûÐþqV‘Ä„Áu€’ªBDÂGJN¶“p-ôÿò4¶ÓÄÕJðóVk´Õ`PZ€¤(S3:v$ ˜u„è£?->$)U«$®hÈÀ¦IÈ€3‡r|²æ°ýQÌâKÐÚBÞªèKJxç{òðàc•«”SVR°O÷šËyÇJ¿”ÈÌ”)•sRý¯}‰™xÓLrú ûüÙ™@iR#_:¯qMºôMc”t/B]ÒRZù\ ccš»Þ?GnÙµ :\9£g^ô ”†u&Fù‰Ö…õŽÞݼ$l r• ³NÚ‹ü=z®¶”+%W+`Ï?´Ÿ1ô&ÈÔÐ<ÓÐÎ{ˆG=W‘È|º ³@¨ûéS™—gAà.¯A–ÑìíÌs.Q&ZJ”t2Âîà£ö/¦ü{%lô{Ø¢h1m,‘â6|EÕ‘J…x¥•¦eç[ô¥«­ƒºË8…§ è ãµ3½~ZƒÐ§ÆZ *…MDùµôõm”Ó£öHâ‡eÅò)L{ŠŽ²H†kpÒšêŒI>3˜›léˆW«œ5§æ‘ˆžzc3oV&{*£ÛÑe@-gÙô!£ð=ò)z˜º¿Š±Tt^jp>Y„¿RëÏFrÞ®•c4ŠëVÍ '^4!ºS…ˆ:úÀÑFŽ%Ï\?åN‘Ï”dP“ËAÒ"[DS¸YÏ5@¦NR6Ÿª÷a+™=Ó@bÖ¤ƒÂ‡ø«6WÝ=&:Kih>âÐd㻨INyçŸbfâbXiÎI£Q·¨¡Ì»ò­FO^PµxjnÝI£ûÄ5 èÃ"áòº[=¯Zc¹ö ùa¨ÍF6A¶£‡M؉Šêš0F¬éË i=äAG~îèyD&ÿÂ奤pÖÁ”/ ©]+0Ë®Jƒ“G¹×µŽ¿4•yÊŽÒªG­­î›ÉQ]½¡U¦¢´AI›$T°V-Ts í Vg@òŒÌR±W¾L&¨^g¾Ö$óC]IX…£•Tk”ºî9½}½ w¬·àŽø(+ÜNHTÓæ*;¡ú,¹[‡ÏznÀp• ¥“;¬á»êJRI.³Ð‚$[7kÓ¨R«¹§ˆ±aùéójÀBmT;C/(éVÚT¯·Æ*3_Ò°ºóÉå níF)iÔ¢&‘ `!’Èé¬7EêT³f­px ‰­ç^Wí¤ó{ZÓ8‡C¦"޹îÌ…DL¦Ùä‚Ý1:*¾¤• Ñ;­LÂ)¿Ñ|%è¨WË1ã Tž7‹œò¿LKR.¢µ5Udm±KHSµ«Ak¬ï•8,š* ÝPv о03 Û`‡aÿæžØ¿‘ ï `lÿÄ€›’¡gA¥âø|jF€Õ½M‘XΖ® Gæ¯Êk”ƒô¢ ¸±F·;ƒë|_wîå.m¢fÙD¦ p™ˆÒFjeÞE-Ž|í’ì ßB ;ojÔroýN3TÒÌ”L¹{{Å->Œ/ûšÇ⫾á‰8â¨ýÛ„²»v×îú”_à–›îÀoüÚñû¿ù×8rßIXÆa™¤jz }¥VcbLCvNv‹êÒPÅþbs P©‘bF­]-Ü™(Žm!žÀ™H]Oð‹ˆAzlÿQvéÕ‘¥¦§NºEÝöÈié“‘†Ö:íc¹'QúêMp8ÖXáëmØqþý¯~7Ž8rß§vw×îÚ]×uë-ðÿüß!î8û—Ã1 اSQ˜Íc(u¬ñ¢ýÈA d0ŠÙjÄ [©ÔfΡ,ÊRøP5I%³ÓýÐÁ ‡=ýA?…Àüÿ)¼ÀPqT]¢",é˜I·m{½!O§EÀ(gjåíœ Š^:„ÊVQÓù¥Ö&À‘m®÷pûz ¾ì9Åá÷Ü™¥»kw*×Gî×|å£qûz V[qŽÕØöLõ,à‚uv€0¥'Äž‘?&®©Þ4m ´¿~9ÓaS`6‡Ô(5p6Rç”07ê¶ ˜²×TúªŽPJc%ÞV_Ó°…¢¥ ‹~ó9Ì ¬¢+[;úb¦¶»kwí®Cìb­ Á}FvQ¶Tt6¦f =Y»o­É1çv¨*; ÏùJ ÑÙC.¬Ý^ÙÀÝKè6S±€š‹š›¶,(žüy+œj¥4°¼úÐEbe?£†áùh"³¾×ñ ùøªæÕø!#ªÛ0þi_ôš?Åõ7Ü ×á„ãÇi§Üg?às0Æø{¾ý©¹8€ßzåïÕïc,8åä{áÌÓOÇYgžþÃÇ{ýcë?Õ+h± 6rHM*áIÇyNúÌÔܲT±)À… Æj¦a:Fanõ/<‘—.ñBO ˜›¨Šfv$¢j¾Æ)ž‡Wzžu¢ ŸžŽœŠey°m¢ dnœ V3TþòÝâúƒ?~-.¹ôÒ;}~æ§ãÿøß¾ :ûŸö1Üqà~ý7_q—;ÿQÄ·ó7âÄNø´ãã¹þ1õŸî5ûÚåNrX,•*ÒY¤ài¦ Sq¾ YoØ£NïªÎ1S” •%5íè3X6‚‘£XÙŒøƒ@`a1k‡2Ôk Š ¬TKÖQE]ݳEP ê N™zWyܳý²’ï>—óü™!;l?®ºê¼úµ¯Ã_¿ù-ø‘—þþÝO¿'žpügd gœv*ž÷ýß‹Ûo?€K/¿¿ñŠWâ¯ßü\wýõø©½à3¦Q~ìëÓX?»×³¾î_àÁz ~ð_}Ž>úhÀM7ߌŸü7?‡w\t1~ç×å“|2w‘å– ¬,´RQºzþ‰7©…|ekX¶pW;w5µd!oXª`Uîŧ6ð¥Â¶IðËôºa“¢§§Ð @ê×½Œ7›­µŽŠ"Fcb°½6ŠS)X-‘ÑÓÈl•‰A t÷ºî}¯“pÄGà´SNÁ£Ï{^ös?׿ñ/ñòÿö›øWßùí¸þ†ðG¯yžð¹ç#ÜñÖ /Âýïs<äA©á]uõqÑÅ㣽|Àýð€ûß¿žýú7þ%6› ÎyðÙøë·üO¸ãuî¹8é¤mMg³ÙàÞ'Ÿ 8ëÌÓñ¹y¾ûûŸ‡÷ýÝûñÚ?{žö”®.y×{Þ‡÷¾ïœù» IDATïp{†sú`œ|ÒI€ßûÃWãæ[nÅ3žö8ö˜dª þèO°wà¾ø‹ž†}ûö!"ð¯x%Ž>ú(<ãi_€ßúÝßÃÎ~îuâ‰øÛ·¾á+>÷üÇÔ÷ïêúxÇxë;.Âe—]Žc=ç?ú<Üã°Ãj]ööV<îüGã¯Þüf|ä#7ã܇ƒ3N;W]} ÞúŽ ±Y6xüc#Ž8bëýÿ«ùJ×§Ÿ†w^ünüÐK~/zÞsafxÁK~—\zN?õÔOú¹¾­`d»š”U¦„~¦ŒAÿÙ.ßÐÈRªèÇSßBÞè^w†lç¶}RËf¡­êD¸¹w¼ŠBR“mœ"ûíoy:‘¼|zfkˆ@6©£ŠÈH`–oînud—ÍW<¯ã_âÝï}À‡¯»ÿí7_w\ôN\tñ»áîøš¯|&röñüüç—ÿöööêû_ò…O÷}Ó7þì/Þ„w¿û½X6›ò÷~øáø¡ïÿ? ã qðÚ¿o?žõ%ÏÀ/üÒÁ»Þó^<í󟄈ÀÏþÂÄë^ÿÆé¾}øÎoÿ<ù ÇûþîýøÓ×ÿN=ùd<é ソøË/Üï>gáa}.»üJüÚoü6žñô§üÆï¼Gy$núÈGpûíw~ý·~ÿÏK_‚c¹O`¬w8€ýäËðö ßY} O:éüÔ Çs4þì/Þ„·_xþëÿM\÷áöíÛ‡§}þ“ðÇúgµž¿õÊWág_úìß¿ÿïÿ¡týÈük<ÿÅ?ŽK/»?ô⟀™áý—]Ž{x"~ø¾ï“æ1é912ÜPñˈÄ:ûÃÖ¦£ìbL­ÌM­ØxÞÃ@Ýiè&¦zž:8§¹›fëèn¨ä+ÖeMVuEU°? lY\Ï© „ž!÷Ÿ© oSªƒ ìJ’¹pz`F[îî×i§Ü›Í×|ðZ¬kð|á;ß…/}Æâ¹ßû]xÊŸˆ+¯º ÿé¿ü*N<þxüÄþ0^üüÄ Ç‡ ^ý'xÛ…Õ÷nºùf<íóŸ„ÿ÷e/Å×|å3qÛm·áååï8Î:ó À•W]x퟽¯{ýñ¨G<?÷S?Žïú—ߊ½uÅø¥—ã#·Ü‚Ç>ú<À;ßýÀ[ß~a »ÿùöwä.~à1|D½çúnÄ·~ã×ãÇ_ð<<äAÄ7Þ„×üù>¡5;x¬¿ýÊ ðö ߉¯~Ö—ã×þó/àŸóÕøÐ‡®Ão¿ê‚úÎí·ß'>î±øé¿O}òçáÀxý›Þ„ïùŽoËž÷\œyÆé¸êêâMó?þÞùj× Ç?ÿqʽï…K/¿ï¿ìrœtâ xáóŸ‹{xâ?ìá´&óˆä{žGDJ»¢»«ÏŒÈûtPPD Ôñ˜ É(…0ÝZS®>ëäïà‡´ª4ÓŒ¬CYq0õ©ø!ÀISäð´SO|øúîòÙf†“î•üÆ›>ò1ÇñjCgœzZ¾ïš;¿ïÔSø¾nÄ=; ;ç!¸ôŠ+që­·âí]„óq.Î?ï‘xÿe—ã†oÂE¿ çžóPìß¿wuwlš¥{“æúñ\õÖ[o\}Í5¸âWáÚ_'>î±8÷œ‡Þå÷å{'ƱÇ Xó„é9ÿCíºþ†ÓD½ü œ~ê©8ýÔSñ«¯Æ ^ò“¸þ†ÿOnm&»¬ˆ:øf¤Ë+:Ȱñ¡ãgÔZMžˆ%Ú`Á<»yÀ‚>¾¹zŠ-Ñ}d½|æâ­Ø03jþ[`¤S{LG•ùžÅV7^ã=Ýà¡d«ÌWåÊLÝð †…'ê¤%œôÊ‹t7÷Áýîïÿ!àüóqg¿Óô»|TW]u ùð‡Þû¾K§ž|¯;¯cîŽ÷_zÆ8áøã±wàÀöóy¹;^õ‡¯†™á1Ç1Ç…\}5>pÕ58ëŒÓ·Þwʽò}ç?ê‘xó[ÞŠW¿öÏqãÁy?×ßp#.xõŸà^ý\Ãxô#Ͻ˱<†ÿå=ÇXO>ùd\~åUxÆS¿xø9û9qŸ|ý=ó?ÔhöE?ù3¸âÊàôSOÅ Ÿÿ\À¿ø'pÅ>€ýÄËð3?öÂOúÙ¥ÏXÁ´`@àÖþ{s™ªù­ P¡"ZÌSGXñéÓH<,ŠUW&מU/9uæ¡`:Æ“ÊéTí¬& ˜{楄ñˆ:¦€DÝÑ߉nƒ"ÚÉÚSSÜÃ’%_¡s05àè0ÍÝèúÐuƯ½ïxçÅøùÿô˸àÿ§Ÿv*žù%ÿìc~ïá}à·^u.ºøÝ¸äý—â5¯{=ÆxÌ£ÎÛº÷ÿ{Åïâªk®Á+ÿpË-·¦µ¯›ŠØÛÇ®½W]ýA¼ù-oŽ䥸»K.ÅÓ?ÿÉ8ûŸxÄÃ(~ñWþ+.¿ò*üÍß¾¾óbœtâ øœûÝð˜ó 3Ãï\pN8þ8œyúé8çÁÂGWýÁõˆsÿAëõñŒõñy4àW~ý¿ãC×^wÇE¿ùÈÇÖZ?Öõ±æ¨]—¼ÿRÜ÷¬3ñÂç?Çs Ž;æ¼ðùÏÅ}Ï:—\zÙ'ýÜ@úëuzºŒA‚˜ÌK6ä° oxÓ_á¾÷9 ',î¼Çwõû]ßóñŒõó?ïñxÛ…áuox#¾ý{¾ûöíÃðßüø¢§=ezöÁ|pðÏýî5ÿCf_ñ«¿4ý–c;ñ3?ö£[Ÿ}âW*!ª ¦¦éØPÈOtÀazp( sV÷ŒœéÈËœÙ1¥èn¥Ï¹±’R-MT3™ª¬0jj5ºLjÆÛ ìZš©£&Ü/W˜×±¸©›/¨’¶Öww¸¾è©OÁõ7¦?d§Üû^8ëŒ3qúié×Ñ:wܱxγŸ…3N;õNkóÍßðuø¼'|.Þýž÷aÿþ}xðƒˆÓN9åN÷½àþ5.½â yÄxÔ#ÏÅQG‰°Ù·Ïyö³ê¾ÃöïÇé§žŠûß÷,wܱ[ãØØ~¼ø‡~oyÛ;på•ÀqLJsÏy0Ž>úè­÷=çÙ_w½ç½xÌ#QŸùN;õ|Î}ï³uïW=óË0Fr 'à9Ï~î{Ö™wšÃ'2V˜á»ÿ÷oÃ?û§â}—¼@à~gÝgyÀç=îq¸ÿ}ï‹£>*eø²à9Ï~Ž>ê¨zÆYgœç<ûYxèƒÎF|óÿ§|E)HiÉèú#?È P5Ƶú›€ ²øŒGCË’ÓóÓ–®1>/tÒ»¡AW[,c ØÓÏ~a„1ÄçÖ—4n¡#ÀˆÃ–ç08U9Ì›wzý$ã[¨Ìƒ½ò``DõoÏ.Âlg+Ö8;°úG±®pÃm—ã‚׿ìÓ¾Qw—ëÇ^öoñ?þö­ø?ûÓ‡¤)µ»þq]_ò”çâ¸#Îİ{`û±±ýË‚ 6i>Ž4_µ©#¬@P‰hSjÿ³ÂÝ„Õê„g”<Z®ð‘xâȃ³v&ßäó•¿¢sQó õt#X ‡ì©NËV'ÝWou$,º°P§£VúES4' [uTR‘½ºÜmÄágâº+Ëkwí®Oò2¦uØÐá‰]Q *„ÉŸ^t—†h¦z0%-Ú}•¿b `¤_Íyï°´Aå§—j¦Ž¿Î\»4Q]/ïèEŒ_ÒÉX`”” &åW‹Ìm ˺ëH/Ó õ=?k–WzI›èU~:e<ï®OõµC¸Ýõ©¸‚fevçÀyør9ÖÛª±²i$>8‹óÍ䣕ù¬€ñ°ç`ŸÉ€B#Û‚òägžÂ‰S™¢ ø ÓøÔó¼¬OD >X¡Þ1›³hŸ^/†Z#%úªÚ£Ìï-Wßîú”]ÿ÷÷}Ïg{»ëŸØ¥0ˆa…ÃFššÃ2‰Áhë¬$ÑÏ®ö¿ê"R…ô ®«­–ìT˜Aêe v'*j›|¼Ìеöê§žcè`mÀãÀêÑ‚²ä5û°Î(«Eu-Ùn·í Ü]»kw¢—šY’aÊV#{tDhJ*ÏÍØÀC§D§¢“?»)‹ú›Ž# 6R .(;C%ž¸ƒ>¸üî`(€Ž<ÓAÁ†:Ð!º¥¥!%ŠÓ®&üÖó :A¨­NÂ+Á»Ð´Y ¹»v×î:ô®4WØØW¾´ÅS“Ó y•.ÁnD páÙ7`¶…¥ææÒÎXÂésÙV¡B9aYwj1*--ÓN„›ÒDr¨AJ¦d°ÇÛ@µ2)«fððŒ’ª=Š`+<vÈyµBjËIûàä´ß6½uwí®Ýuˆ]Ù| ØÜÖ̰ZúÜâ}ùÖd/ƒ“V¾7þkøA% G–>ᓪò“î犈f±ýdvê+ ¨žl±^~µ¾ú{¨†w RD8²œ4µôµ¥cС³R30ѶtÖ® Fn5¹Ý©Z»kw²W0hÈt1P몃ÁãüÌ–B›·¯?Ï\‰V|FÀ­OØ«t4Eb3Påt¨4ÍÚ:#&t£†Dé›]úi–Êy¨¶ÂŠkÊ€Í÷-È.NŒŒ=Û§Öš_/Š*¶×ªúÅ¥Þ¹ÓÝv×î:„¯ªEbÀQÚJÂOÒb—a£À/3+:­D^5)[ uªÑ®aiÓ–o® §ñøçòÛ3hjžÇްj6—ÑÑQ¡‚˜šSfÄ‚¡Š©Éxi]Š&ðÞŠT`:Q‡ÑRÚèéXPÛ%cà!Çj;Û]»ë½Z)‘—^G<Ó?65ýæ¸ö1qp]VctËòÝ#µE±jô :Q#˜¡‘Õoà£#%EM-°F`‰ìµn0¬–N<+½I!ÃØu„]Í6·bhv&a«*2”œ“pNJ4Þ]»kwz&,Ù-ÝSê\è@,ythº¿¦Bûh@̶i ŽèwÈçV¥¡t…±4 è¾–Â6Ý(.D`!Å#o¥üUÂïÖ£ª4"êEôÃY§” t ‚ÀK®Ni³Æf­Éí®Ýµ»¹+X²Ë7dÍ­eŽÊÂX²kï„ÛW¤æ•Š29œæ¦â±Ù­Cii¸p ”/ ÀÕSÁL¤ –bùR¹%™gÒg v:É` à2Ç¥ËõórÔ8§>êF^ÃÓä.ó:ÑíÊË.ùÔìÆîÚ]»ëSzeˆÒ32™`†²Ò2—Í*0ˆrg™­P)T­ Ê( ™P7”$L?½©*Pp)Kب ¹Úþ:TSÆèƤ¯É–N`S;ó6! ÁÛZ"dZœ‰ç06Ò´ Üô†l,ý¼§n¾é\wíñÑ[oƒû'Öáuwí®Ýõ»ÆXpøá‡ãø“NÆ‘G“Ú/Â1ôJ׬ÍÏ-€Å”ÁÊ™gú.Pù²õVB­ôÕ ÊO_ŠÌ©­ ©çï›Y]Ì÷ƒ“B²<¢B´Ó Y•·fÕõ-‚ “) ³*€í6*Þþ? #!̹à ª¸ü’÷âÖ›oÆa‡Ž#ŽK—™a³o–Í·Ütn¾éF”!ÎT2ᇲ0èó2áh®Ê×–Å¥éÕË:€i1²)‘¥º¥"`ÞMb‹Ç^Ry' ®õ"uä…OÅð³Z ðV}@¬‘„.×`0ƒU ‹MåpÄð©£Hàºk?ˆÃ?|n»kw—™aÿá‡ãÃú`¢±LAÆÈHjY{Œ~º¡Ê5ê:ädDtÙdB¯ ÀWjnÄ Û*1j€ÛŠ>pÚ86ÒªRµDED£ÌG£é*V€ef&;ˆ Z LÖ4:ñ7ßcžu¶“LäËæ—¬y…᣷݊#îyÔ§w×v×îÚ]÷µÙlpÛÍ)¬ÈzÎô«çÑV:✲Ӯï=œû~žûzöpík#Î\fìU%FˆjštÃð ''—Qñ1ZBÈDb§á´iòxÊ¡µÎÕä¸ BêŠè^(àÀXkN¯z&† ¶:­‘)(a„‚ ;¢ª°”«†R j¤ú/,Nü©t29Sb–p^L-T&R0Ö5‚L5`î \'8NWb‘RÊšÞU=ûÌ›h Ùpïds!™þS-—ÿ­2lذÕg 9Ûƒ=C“Yb L!Ƕ¯u(ͽû›gZJÎMÉ}Cv©I,…7ÇíUŒÐ‘.z'1Д4ë:ô - Ö C \…JÃmI Í)~'D%ª;*&ëX#,dd?šy“¦Û %‘‹?üQ|ïÖÛîòï?uÆiøço]‡­[ïÀÉO<ñN·ù·›oÆÿ×Õ8ýßÿÄ.Ÿwذû³EëfƒÛ„$6d¸c—ªFñoÆw]x—¹ü,L8ÕE8K5õ‚åiŸ„QíÃjª6Â^a l<°Òeun¸SÜ1Xã NÕjVm3w,(0'—=e¨ÙÞ…:Å…»š7z²ðÝÛ–ÛïÀ–-[°eË|ñê/㣗~*ß²e ju|ñÊ«ñ??{Å]ãŸ>w9Þüÿ¾ ·mÙ²Ëç6ìþktiÔni*ç³x÷躩8T+¨VÚó¯f{QÌò¸¬ÎZèDÖé.qgÅ“wCz–®±Žh¶6.ª¤>bÁÍyŠ ivÉ6–w}a@×oj ¥IDeÈíẠ¥ìºg9lؾ²¿~ïð×ïýÀ.mûœsž‰çœóÌÝ:~¤°¬õœ"Õ Ì§da¤˜¸·–N’H²¹=h1ò9öŠÿ²Cky´BqΫ6T1c"9€"õŽà¬É© à§–7o:O*HÄq*4¿ëcÿi4æu¤oäçYM¹[÷y·ì³W|oþÓwâ;›6áÂK>ŒßzõǶmÛ×_ÿ\xñ‡rÛ¿~ïðü\÷¯ßÆ×ÿù›x×_ýÍèªöc» Z{n@Ãp~Z Uê½AT…°¶¼À~M¹V µŒm Ì­åשEŽNEŽ™Ý®ØàEsQ š,/a:ÍfP…B t´–$’R€®‰¯‡„9*¬–|}QÙ*Ü&$—–q6$µYkÚËö¨G‹WýƯÂÌpûí·ã—þ˯ás_øžròI;mûÁ~/záóñcOzâ^_ǰa÷… ¸îÊ“ÛSp“:U­É]€µÃì™'N1÷j¿nêaÏÝ: ŽˆJ%‹Bn)¥×@î­2øÕ€™ZMÆHe ÄœI˜·™6òãjòS¤ùTaXACbaÔ¼D;ëÆ„U潿O{Ù:ð ôÂÖ­[‡G÷ÜpãMwºíy>ô±Oà+×|µŽ²a?˜öœsž‰_xÎÏÞéë߸)—æÞ)BPJáV‰€RoøA1¤Ø%¥¼£81[¶0 nû Ð 1dºÌÁ‰+ê'Õ,rrÏJM«¢m€b… CºÆ \IÄõ,6XmÕÖ<ŽY$uᨠ/Âd^"gz }?åÞ·ý×íÏ2÷Îö/{1ÞpþÛÿøðÒW¼ûä§ï“5 ¶·íœ³j ä¾op(ŽAÊGú+Î9/-߯0]øhškŠ ÷9Ta(Õ1U ºŠMË)+F“f+0—8N¥Ã¥t ÑÉ p3ó}Æá lƒ0ë¢Æ4ù©±·j*Ë¥ÁsË’…<<ƒUÁcg¾²jÙª› _^ïC;êˆÃñÿ+øå_üy|ê3—áÍú.uÄøÑG=rß.lذ=°sÎþ)lßùæïÜ€FA——6ýjLUÕpbrÖ©g¡BTÌ«”ù(ýÜ‚$3dé Ÿ9ÛÏâZ8CY˜ R RA%ihœÎšw§ø±9¢‘vÙhå5%ËÓ×ã¬BQH4Ü9\מ‘¼”wܧ¦°ô€õëñOû÷8ô‡àÆ›ï<œ6ìÁö†ç& KÎ ¢HêQç +cËɽP(·Fd²Yi²”PŠÃeÚ <Õ)ÕÓÎ-%ñëо}'ƒ–*V±<;@qv“#Y“Љ9<3!tWEÍjI†ž%VÝBêšH[óRMâ+ÍÅÝV«ã¿üÆÿG÷qøƒðÍk¯Å<ÏxÂc³W5lØ*3gž>;–8J°…t0+èÝ(4–£b"‘¯. (¹r"É™˜•yyB ÏýáDßØÈ€2A²âpU<=\†R4†mr¯óMJá®s]M×ÓÝQUÔûU¢ÕÛ·@qBÅÞóGpðÁ;½þøÇ=[·Þ±ôÚO<ùÇpØ8ê¨#qöO=PŠá÷^õ›¸òË_Áw7?þc'ã×_r"Ö¯_·‡«6ì‡Ë"ÚŠJ¦½…ÝIî+ìaªÂ‘(OLñ6ˬA«”U^/ IDATüX›SŒ›…LRÀEÌ4$Z#œ%4ù) /‰’Ñí0'pEìÛæ¨Ò ~±a)Ф‘"ßæ¦ŒÙÇÊ´eÒË{,0Ìé¾î™=êøGâQÇïœ'{üc½Ók§žrrþ|Ô‡/‘|{ÐqÚOüø®bذró(´‘:HMº ‰Ú%Š PªF1Òø Äs+äÀIɨyiá^EÑS=¯áTEñ""ÔŠE*mrÑ@’÷¡_»¨9›¯²íÕf@­sŒÿ²Â(ÙzÚÖT§TK7Ní[ ‡ ¶M)(€Ï·MígDBM"˜KIu+(î®Rõ¶æß+Ìg„â‡Ñ's?Äq¹I‘—ÇÂa9•ÞàéXYzX‚¥JÝ·ÒåÕtúMc¾´ÈXN€yÓ“[$·ÔtŠVPP(š·Ïk Æ »[cϹRatÜU:è°@¡«rq¦Y~U£Vý6ϼ¼ó$f–P o5,PKV5#¹O58zý67V4<´ MF®•lÕy ö±QÌã™hz‰EûRU@íyãÀ ¶šÍK°#"ÕT‰€}eׂɳŠâ‚¤Óô”0öõU€åƬwö=óñw¯¢¬¨Ø/Œ®#CéägTñã”7s Èyñ`]ó+j„¹U ÂJ6ñÔo ••Y0`Ž2³óï6'+º´+6lØ*4©öæ\e4J˜#ЇR ÷ XéFšúÕKóº’râ R± [­)½Ô¹ s…¾cjÂ…GrIÊÿIòHk墛?vªTÏΠ–6ÃÔèBÊm4´ò°åm®`Zvòó¶94tfذa«ÕLåÌnìAq¥µ{BúF•zR,*JþÃ’¨;±J}¦V#L5¦²sæú²f€ù”øµˆÔx“'×UI)öª¨`1K!{ÏD Fr£î)ŽÎ8–®,GÖ0¬Kj”QCÏ5‘¶e*¼À°¶ÌÝ1Ñ‹Jç CeîÜP¼©‰¸ÂFù=5ÒQE¡(¢©ËÝXXª¸PQCoR©2M´'†Z‘(&q¬äî%XÕ³,|¤;—Q5/R?*ïÖS=âõ¥^‡8!‰ì%wWZ’院4¬Û=æ•,Ö¬Ù[ïϰaþ[YÙŽý×À–)h $¾ §zyUÚåϼ•a…^;A¯IAD…ë0A5 ï VÃ,+N¨nY4ˆÖ-BPVCýeáñÉ õ\¤[‰\œÉ EÄÙV)ŠWR\DÀWªGSmVMu;,OxèaG`ëÖÛï²!~ذa÷¹Wl½ýzøá-ŠS‡“Q Òjt&åœCÓžÔö…y3 "ƒßJ ÊïSZ×È®È këÁrHk&@´U­*ÜÊ‚âjšRUu¹ìëªÀ*'g¡´é¾Üæ„a‘øâFq«J¿°°›äzpàAã€Âm·Ü‚ýÖ­Ãb±áê°a÷±¹;VV¶cëíwàÀ áÀ g¤g™‚js“Õô^ tNbZ_%@™SÁH¢XñÈËE +@S’•‘¦™§®dRÒ2÷ï™j³âX8Ý@ÍŒ®¬ˆÆl˜YÚzÂŒ1î’_ÈcMïN2Æ ]ÆÑ›ëºÃÂô 3âu©ý>ä˜cqë-ßÅÍ7Þ€-·}uˆaÃîK+SÁºýÀCöð7Pʨ‹¶Àç? Œ¯ùÌ΄ªAÞI«µ½8¬D+ªg$ZÅfn̽I IJšajÀ±-+(ejü6¨¡•ˆÈƒ˜Eÿi8[‘ôÒ-˜ÈÝÂM q:,&r™Rpª¶€ &4ZÁƇÿj]Aõîsª”Hl3´§Ú¹Z§‹ÿ[ÔŸ¯`§}Ú:F¿‡ú}S¾OIzû‘7â¶{‡äö·¦å;ùå*û•9š4Š=;^yžGû.gMw¶ô±ó–·Ô{¾ãb}§‹v¥?ДôåÈÏEÞ?k»õ×´ãõô§ÎTñ[¿¿×ú»Hž|¹;f Æû_þ|Ýû“‡n׸ãWj¾§àúÒêyÒ^ÌBÚi9‰ï®î»q^I÷>j|'rk cñn’UûlÛï¡îcöªw¢ý– ¹ŒnvB B-ÔÚ`¥ÀlB±ý0•ET:LÔûPc=S¸,.ÂYíøm-̫횒Ƴ>ïw\w¡ã—®1¨á .ª~hL¾SM»i¥Ë[!ZˆÞ) ÕÝ2±óÍT¿)ŸøÊ‰®á­˜0™aŶ…&´öh̾sÝ÷í9®3γ¯¥_VrM¾a~$Èîz½‡ÉØŽ¾ØÚy®|(ŒÊPKaPÓÃoù.AN¤._‡ˆÐWP{Pú­ÿ‚jk‰- š*K«mëhíè*üè®uŒ­/Þí¥”ÆÒu,?,[úBÈ#›¡ziûv9š%Ü7g?´ç—ŸŽ‡îê´{ª÷Ú<')ÝÉÛ—ŸCç§ ¾•eº¥¿[í=Ðqôgy=Á¡ŽKOqŠXwÜ_ïîú2ê=×—jÓ[¬¨Lß8–æðu÷=Ä.xöÝõyÓ}1ä-[rH‚»ü…j®h‹ó¨h– Å&”²@±5X”ýP0Á°†ŸÜôåÞ>}º&ý·\”·÷^ïßï¸ݳj —VÙ'`@™©UÜ»îÍ^`ç½}y5n˜Ú'Ò£á»nAôŠñ éÔ@éé…`]{€œç*j&Å<¼Ê_1±x ¦üàà+ü!o˜ÖÞÎß-ßgÐpX½eÉëë]kÿ1è™ï°tठȫé> ¢KŒ¹÷à, ´ê>GÉg†·¯0¥©®:ÓÍâ\X2OsPâE:÷S¡68yæ€/¿†nxé8I>% âá­üêKÉ*ÍôºbœI87ë!?>Îf™(¼|*0a~™9¼,Pª¡ú„ɦh<ŸÉ•5]hƒN$#žu±q ‚Ž8ñÌ›Q\^f|Ý’®È®‡D»ÚL„Îݪp©&á9–7¡:íé&¯hòtÑ-Ã;'¿ÏH\Ž›ä{§ÿê°=ž‹Ñƒ邸›óƒÙ|³)LÞ:ƒ/±Ú”#òýè?ÕíAnß#ͧÓÝžðÉïŤ_4°9ÞC+‰7m,¥¶Ëo>$¿~òlYt¬v}èÀyëB$ƒ«èÞ8}ÈÌ»´é+ýùaüü¡T|ž¬=÷çÌûÁÏ_¼Õâ>5ÏÉ&:!í-ÜzA~ÙNz'D¸ç}lï‘HËIòFÎ ŠM€BÔ"”/Ìás(<Á –8F©º›|‹>S­CÝÒ{1VGu à+Qd°ã2ëÞMäã9f«á°ˆ[lG ûtã—¿‰½Z^´ó+^¯zX d¶ü€¨åËÝù¡NãcÙæåÅ1Õ˜³ZøI2) ù~|"–¶žvx ´AWe²•¾€ÎЭîÙ°úãæqÿ ,0ÚP]CóÌ':-ãtÑMwŽâ ÈÛ#o–ßín¸@‘ßþօΙ€Óg &€UzX6òÞÿ$…ØÌ@%cu½½çh‚7Ÿ:6rw§×]Õmßïˆââ,S1ŸÅ"ïPŸT§h£*TDø¨-½û(èóˆhWBGŒÏó{~”›ë¼®½,åË4}*ޤ9u \¯ç^"µ)ƒÉç–»ËUÝY†Úº+Wú*‚Qó S­ ææ¬ Ýf7À'‚-˜j ·¨b@q6 0?§;T¬ kÚµ·¦µ¯¢IÏ{+=8Æ®U¾iƒ–cò ]œ9…ø’³ü»nsBh—¯Ñ·kè5Åm-0‚[ñ8g5÷ÝçûÚYdh®©@«ä,ßßLúoéZâ-ôJäº'Y1?háå5¯6Ÿ[È»“• (̉TkÁYñ¾µ0I¯õ§m©©Ò¼FzOŽð„[Tø¸ Øøe`+ÎèâIj "D’V9 m [åkÅj«¦““4› ‰'¾§RTuà­>À‘§š  Ýá%$ÁŠ># »ez#~|Mny÷'c~*óQÛÅ!Ĉp±¤gV¸HÇÒ;$J<Ï_ó]=PX¬CmC—Š>l¼¼÷â<Åíc‘1X%Èü²âjÝL€Íèy§!0YÑrrJ/µ/]±LyŸ9á>¼^>Ñ™‡½”}Iék¢…£Ã¨ôàè@´tˆTÕ®i¨Å*о¨âöFêÁZÞ®¸'ÐægÏâÓ0“w Ý]wÖâÅ…r0¦7D‹.f郙o‡µº-ÞWøÒci PiIZ{0…´üÆA‰Äád(ÎÆ}z"+u+æ•-Xñmp_Aª,?ãÝGSŸ¾óLJ•7ßZØŸuçG%«Tú§Á'ŸÞ¬ ™1nLKþòeJš,&ph®ò:\ ÃN¡ÌiäEùÒÞ¦<^"tm-ÐzŸÚµ9]¾Ò.=¿È°¼Ÿ~×7v·ï‚†éôý}Ò—%!®ÃÏÚ§ëσ{»7Œ%@È×»÷¤Û­¿(âèÝÉþGïvñ¶–þ8 û¯¬ØXi ãufý³Ë5êxЬô°ëm3>3ÖY˜ƒ{—ÇUò½ÝçuÆ&µ[k|‘kž¨¾nÚÙÚm|x™Ã,SÙkÊ:,¦ýùzkÍ-xJ©Y<Ãî­pY2wµ”üˆué³âÖ1úçÖòÞ何³¤7ª{³2'[ ‹ôhzoÃúM-O®†xÏØ Ý öìðÞ€/ÝÊxøó–ßýòé­âaPa Ú ¶lÿ.|ÌðŒgŸÿÉðЇ2âÆíM»íÖÛqÝ77á?~%.ü»OãÛÿòpÀ~‡Ø°¼,CÁD¨0[° ¬è-\µ† *Y5¿¡'ô4À×—pa®Ï²&NmíB};㑯v%¯›ç«©h®ž¡£\8C ç°U¶ezÕU 'Ây üê0º¿ê„¨p,èΠüÊì ç8>*ê¼ [ý»xñËŸ…ÿüâ3ª 6ìÞ¶yeÆ»Þúa¼åuïÇþÓ¡(Ó~^ÅPjÁäšle^™†`+V:(L¦;$^¹\4ƒbÕ [ÎI­–ÁÃìÍ“+à|ã¼ÑwÙ”ûÙžàšÔ:‚¹ ¹‡´ õ`(¥À<´šTåÒ¿ ómj]fÆÍ©PV¢ºWlÇ-xí[_†?ý„½úæ 6ìîmZLxáùgâ¸ãŒÿzþ±®†E‰ÊefLºM'ÈIrC-u)Ò ~a;HpSú!Å,Š3aV}9í…ñ*9ΑoKþ¨ÈfVsë ¨’Öl¤u憪-wD"’¯^bn¡q’s燗ZPêpi¹;&x) +‡VpÛöÍ8ï?;Àmذ}h§žþ8œû«ÏÄ–mÿ'òÈž²Q-tk|«¥s¼ä†R•ņ€VUÅGT1&@3j´D#B•ÛÌcÎé Õ…ó‰ÃhTóq‡±©>h6gtÅàbjóòœ‰>Ï€]‚˜+Íü¼0š<ªŽí\hŸL +u+|Ì¡xþ‹ž¾÷ß±aÆí–=ÿ¼§ãÈ9µnÇDzH5N[ä‹#}G8©‹,¤œôƒâ‘ÿ™É¶T´RÝ ÍwcªXD‚ŒâߊÂy…Y‰% [Þ­z­ô@¦ H U­ ONd\¬G¥É”—¼Å·Í·ã¬Ÿ{Êȹ ¶ lš ~úœöù¶`_XAåô«¬ ;RÕC¸¤êhüÒWÇÑXA°6±ž;AǬ«p*‡ÈRCÔÄù§ÀÅÉ“«¨‰»9Á§2‰”މ^˜¸VÖåÖà—gº Ã’ŸØJ%ºàÖNâ0¬øV<å'{o½_Æ ÛMûñŸ|æyk+$8;€ÀêçáêlÎ>K¾¥ªžé¯[`Ž Lkq;¯³Í,Ì€×$öVCd@­[nÑ$P‹Ã‹±ÈÀ(ÑQ¢' û¼‚ã,õ‚^fP@Ä ï(x™pŒUW#‹w^z YýðèíõÝr¦Ñ{®+xð1‡Ý«oذaÃvÝrÌa¨¾+ž¼H Enh¨@ù|mÁ¢f Ϭzã°Î%õº;[YxesT'öÀ.‡G/«W’Ê#ü]„W¥ÊDœ¸2UgA°'ý%ÚXm›m<†EV4Æ´%ºÖMãRÓ{U€’ÅJò•8ÞÏmذÕb´Ž }ñY[›d%K»0l¹z6Ú€WV8‘-w‘¯“O$ìñÀŒv:MÙ_è|±M ÑÁ  ‹&lÑç¥Ä˰"×i†t¸˜•ai6?¡5”ÿkÝÁÿ@J¢$A°‹ßK…ˆaÆ­S~=hg¹h…€hYœµÕ{É=ê:yr„·†11ÀÒ» = •¬’òlñï…])Õ‚LRñÑ÷6+ùïmS<¸˜‹Vì™r‹0ybóûèœúêòR»ÖsyzH_Ô-ÊÌ%oΰaÃV‹=–^h …«,>²§ÙjÉjiX_ÿ4dïi–)H+QYTý ÊHíÂUcÞ¾v¢ÒÜXÈ£Ê!ËDÄ"!•R v¼ “¨Ô°RAhÒH†éûµ¼==áqeÏffù¡Ó[_.6l5˜údC´A zþ‘Ú|ú_(€‹)‘5ÒH…AÚ ÁÍr J* ¨[ÔW§;ÐÑC,j æÑËÊò­%{¸QE ¹.,®>¥÷Õ7ËK‹EIÎÐÐÙrá€QÙ‚Â ¨€‡A7lت4ɰwâAŒòØGÚ F;;+R‘ˆK@×dzž(þ[î6•#ëÅ%X@.šTÇök vX ÏDbžbߤªº¨¹s`w6ñ{*ß@ÉD#tº·`2²5tKÀ ¶êÌÊÁµ5‘"¼ªØ  $6cCÅ ÔƒšŽa¿¿D/Ý¢Ð4ð‚ÛV] @äñ£ú x ¤®@ÐDàÒ»’ú­`‘×PZ‰Z¨{!pµb°@­iÁªË”Ði¡Õjœ¡2ƶ¶PPn@›a0nذUgôÔ‚áz‰yô†‚&ÀìÒ Øe|ë(Ž€¨OinϽkŠÂ‘êÐUúmæ¡Ù×/$a^Ù/j ]rÜ,±¥¦ÒªHÀqÐFømÕ’eiJ]üÄEo où9 6lµ™šç‰RI¸“sR󙎇Z2KlÑBÄPÂVN ô©V›rHQ;о:_(U~«W,+§¼œÕn'ÇÔ ‚p° Âgd=$CR Aê 5ã°.¤’ë½Ã† [U&…! ÀºÐ@ eV‘˜Q;*Xk„—ÄGŸ‡UÍIz£¯G÷C2Q8ODŽx¼ cݰ¨Å—€Ê¨Ñ>9[ªŠˆ¸ºUY‘ (oË©7µÈXjpÚ\¿^Þ¬úÚWÞ¹¬ìÎê°a«Ï¢{¡Í=HùfÁ̰n¼¡X$æˆ9%}—Oö±ºcæ°3±.*©!Ìãc”eœ¿ ±Ñ@+`‘Y2R32zæN9]‰àS( à¶à¤dFT¼‚x8Ât,¥ä´Òtßã®ìŠÿö†7¼7ß|ó]þý¥/}).¿ürÜzë­8çœsît›ù—Á?øAüʯüÊ.œqذû·€É'Ω-ßžÔË®%Ï}¡7 ©œÝK Ó–>E£}é”}ã8Æ)í ­@ZZ…6_w³à˜Ä-ÉB6qUІ«h]q@"™âÆU ^ÂÈž£´R‹Æ=ÎPH~J6uç¿'»å–[°yóflÞ¼þð‡ñ¶·½-ß¼y3æyƇ>ô!¼ç=ï¹Ëc¼÷½ïÅyç‡Í›7ßãùvÇ6oÞŒ“N: §žzê^=î°aûÜäÇIˆèµ’Ò*Hæå¬:h¦±¤x"ÕC<†_¹̦ÍJ+l¸…À¦MxÎE¶G•¨:(DkÏãNp¶l;©DQù—¢™‰¤Y&GE%ˆš+VJu¶cy㯴rÄ®‘D^õªWåÏø‡ˆK.¹¯ýëwë½zéK_Šç>÷¹8äCvk¿»³mÛ¶áYÏz>÷¹ÏáÄOÜkÇ6l_[…cE’^ÏÔ$­ÈÀØ)f!¯æ•ÃߺœÇÈK©‡k°k yºƒžÇ¨2fDxUZ± 2TTa QXA­ /O6%#O/›/\?Gü\‚‡­(p›³¨P4>OÁ1²%Û·ÀÞ²Ë/¿Ÿüä'qÐAáÙÏ~66lØøÆ7¾ /¼¿ök¿–Û~ö³ŸÅg>ó¬Y³7nÄÉ'ŸŒRv-+èî8÷ÜsññGuÔÝzÆý ™™Åd+÷¬z*w®ÜšK Ñ¾‘³­ YW¾ÎR¥DQ_¤°Èï°‚êŽÄð€&†g¡!F›zau#¦ã´¾ÐÊrnÅÄ&VXiòåfæ(VbX±£^SŸ+G1·˜sA ]¸d>/°*-¨æåíMxûÀ>€óÎ;_ÿú×ñú׿'tn¿ývÀ5×\ƒ×½îu¹íïþîïâÏx®ºê*üÓ?ý~ó7sI·îžì·û·ñÎw¾6lÀE]„cŽ9f/^ɰaûÖB˪9òR<¼ËÁ[—ÊBĤ•¬ ˜2wÌí3ú+$‡j¸a9“W`°ÊʬE!"ê˜ ?8Ùž±nÀ.=aÉ-q´JÁ®ÅÙ$ûõÔ‘nh[Wx€}ÚÍóxRi¨/ÞËÞ´SN9_|1Ì ·Ür ;ì0üýßÿ=žóœçì´í\€7¾ñxÖ³žµÛçyûÛߎ׼æ5˜¦ ï~÷»±qãÆ½±üaÃV©M3š˜JŽókù3Ró™{ï† [-f5žSx ,‹ƒÒy늆lÀ⯠“bŸÄùOz­lýbz4GÈ;Ͷb¤†²N©õ†R©¾iídXc³ÍTøh±sœ²(™TÔ‰¯ÝÔRØ`0»PÞœ³jËõÞ´ 6¤ÆûŽö7ó78üðÃqúé§ã¸ãŽÃ;ÞñŽ¶Ùºu+>÷¹ÏáôÓOÇ 7Ü€+®¸Ï}îs±²²‚W½êU8÷ÜsïÕõ¶¯¬é¶Å?Ñ]PÃc«‚·‚Ù …>ú&ú(`ZÊ’=±µ„ÄRüøäœÍ0¶A®Iè’ëÉü`I±‚b‰» ¥¨ÐéE-gÁbn©F ¢“/ÑaMºŸ!þ\\D±&ÕîÃA®™ÿCŠÖuïÜÝÙqLJw¿ûÝØ´i^þò—ãÅ/~1>õ©O-msÑEá±},®ºê*œvÚi8묳ð½ï}Ïþóñû¿ÿûûhåÆÝûϺ°£U4Í=ç"ä–Ô”Mâp+8JϽÍê+K M·|ÉaRkŒ¡q‚cÉs¹¶3<Š îê$­ 'B›>£Ô «À„ Í@ùn#ÃJaŒZ›.ºrŒ_3ogÝÂ…ôŒ›ÃÕõ¬Œ¤»¹Laé!‡‚óÏ?G}4®»îº¥m?üp|ìcÃã÷8\}õÕ¸þúëñ´§= o{ÛÛv« 1lØœ¹…Ȥ3Ü ÇÛœbä°yžqì±Çâ”SNÁ±Ç‹Ë/¿+++xúÓw>}Øa‡á#ùÎ:ë,˜Þ÷¾÷aíÚµû`ÕÆ݇¦öÊ²ØØžó~Ê‚Dnc߬=&/85 $ætÂz,`%Uû]¬ëžÀ±PÝ“ù2—¯Wé=Ƀ$ kôÉÞ«V&.Þ@²tŽVMÕå;¬¯Fúr †»a§žz*Ž<òÈ^úÓŸŽ[o½u鵟ÿùŸÇCúPÀñÇ_ÿõ¡¶Y IDAT_LÓ„O|âøøÇ?ŽM›6áyÏ{Î9ç|ðÁwzÎÃ?Ÿýìgwo¡Ã†ý›IÒm…@¥ Ø›ª'Ÿ³X4@*ùo®b¦Óû#d‡Ä”L…©¡u82퓇žœý‡G¼Ú³²Y‚ˆË£‹œ § \´±VÊÍû¿ ®Z Vñ/[¶_t|QR<šúuáÙçJœûîÿŠËþå­{ý 6lØžÛ=üE8䀇òy5”ʈ”BÍ6X⨔_ l¥úP‘—gʸ3JDplSüÒ[,m¥"ùJÒ-ûª NªR,Ê  $;ÞzÉ8ëÐsÌj²“ÕVÑ™ñclj^‘ dèë-ÆVŽ­–N ÓC¥y¾–‚6lØ*²&¢>ºMËÍæðT<¤„š3ÂtÊžŒ#Z6;å7n]Rl7>ë|Ô›érãGÕ‹j­–¡ðÐc*–¥Ï×BÑ Qrr}JmY¸¨&wŽ;Тh‰ ÏÆd9; ¨,'—œd1lذÕdMû'º }å@* å$b0ŽIpO`ŸÖ1§ªˆÃ€j-ͧ×Ý0ù'ÓXÞD)ẎER …¨˜: ŽèªîФ{ bàTõÍþ³&S΃C<·¾›Ó•X¬,Vx –Ãɯ6lØê²ÀKn[æß¬5Ö»#ç%Hð*Þ9TD‘Àê‚è*X&®0TÍy1.‹ºAA‹£È@Lòà‘ +¦ Q2£¸dÕ“3SKaÅ3òy,£vºpN4Ï’†…š@çÖqwc£¾ÐÆ [mV€.Läs”£Í5î„rõo#Màç,BZæô4ÇA‘]8TSÓfx©KX ù :¶¼Å…rƒÕŽ‹„ PY úbÅ„aá¿qÀCQ–ª"˜›4 ÿÓ¨9yËj å¶lè|šŽÓˆt÷Êû3lذïÓ4нÊùñhbÈdyp^*f¯Ô…$n:PD†»0zdá@…ŸÞ8ÑÚ4E™­İHðb>Ð*aŠ“êZ љӴbÆÆ%Ô½ÖÊb&¨%¤ˆ³Zâ¼ nàó˜ª5lتµÐ ’çæ¢iÈ¢AiÆx9œªVX §ÐT^Ž©± A B.©ÎAï®5á†Eï@"AHTt ØóÊâj‹µ=ÃÎŽÓâÅ&¨2j‰ÜÔðþ‚2Ãf\¶péÚÒѵø6B·~·aÆ­&›ÝPkTD-“R =Ä—HúỦ-åÔ,¥ÍMJ E-ìhòÖ%-Xô•ÇK­²€àçæXòڈìtF ¶DbD^XWòíBHBÀVå£T¬î1œÂˋݬj«åžÃ† [mfHîšùœù·œŽÇgÛ³èh1LÆf ¢RÚSÂô—’Qª5-Óg•…EôA»¨ÄÆø/oò'Àº¤È DìœÁ&Q6¯¼ÈÚ•k;É#qã¬óØ0IÄ×6e‡›0lذÕeÙÑäÈB¤e 94)ÿ!bI'ÉF¦fú0cB-öeXêìM5¶ƒcT™u4æE üc„ƒµP[EêœeR¯ZrÃud¡|Nï«oÇðœ8-Î[tDˆ§Ê‰s[·¨ÝŽ¡ÏÆ­V£oå…Ïz8E+¥µi)ÿîTñ]ÀÒ‘I߉MèF.[¸Wµõ­ ĉõæZE§Tì7 l‰;ߡՀ•!¤¹.ùœ$¶UUélyºLþ![_ÃÅ$q8‡ËÉ8žž›ÇW]‘ݺ† ¶š,ªŸ -re6k `¸,щÀ"ƒ¼ž4‡RdñkÈ(¡hŽžC]TÊ¢cY°í+…9@lª-X\˜À‰;/B™.ºNm¾BßUP»„¡¹¡T4­7™0Øé!b % «¹½'¢g‹Æýœ·¼[ngŒ§Q Mõâ–]y“† ¶ºŒ„ ïµrxCÃÌ*ŠUÀ'äÌûÃUa‘y·ÔZÑž˜R_\NäógX Ìrw,`QÉŒ4 šp“ÕÓü&´™ Öɘ‡£%~œ±RcøM± ,gƒÁE'×ÎÁ®´±‘6l5šYô…¶R •Àώ–Pª© ÖBS°—UMüæùYBIxv *U(°Úæ6€mÖÈs&oÊÙ7ÊJ­И-ƒ›6Bû³…pÎ8­TS ¹6OÍu•y ª¦êØr{OöWõWøÒ—¾ôý½kÆ Û%sDûe<øzŒOW˜U ˆâ"Ì»T’öá®Ô–òt`Aë¢ ”PÈi] M´‘IÕXPÉI¶dgŒIÀ Æv.:”\µ@I-ÆCƒIbuˆØºfI-áì†èB-láê’Ž.w¶Uv5 ÷’—¼o{ÛÛöôý6lØnY´fY-(>¡Ô¢ŽªÖÚIkSìܪ…rxåø?‰r¨D*æE–¬6þ›[3`dvpNàªIà`³½šôÕ*6EžÌTThn¨ïàSE°Ér0—ÕO¸ÖV½úf†«Ði­Ç<µnì ŒyvÍ5×à ƒÚ¥m‡ ö}Y¤"¯ ­wÝ,ÀHQ+%ØÀ:¥‘)žY!YrŠð2×Ê‘L"••!ràU„¸€­$Òzíøh.@‡®Îž©aÊ›! ´1ÎKb)ž9gK—sqá¦Î¹8ÕYàºQ»–‡{Ï{Þƒ'=éIظq#àºë®ÃÅ_ŒÛn» 'œpN9åpÀ»þ6ì.Í­bfºÉ¨"ÔÂIK/ÊXu3xl)NTAÀòRW"Dƒa,)'%È$Sõ,R€apDÌ>¥ÅÀ¬dŸè õ¦¶‚@Aõ’] €êêlh”‘â¡'¨dÌx;‡Á äâR%o’ºRrWw£„ú–·¼—_~9à#ùó˜Çàcû¾ùÍoâw~çwpíµ×~ïè°aÚ±´Y­¢R Î à(˜Õ¢É¤—î iæ1Û³Øtl8kÙ¢•ˆŠlvJ;®ÃåÛªW ±ŽEˆZªüŠl›¯TrÝtA¦Q‚D#€½ª Q™S3‚î\,=Ä X]:$êþ]vÕZHÚŠ»ko}ë[ñK¿ôKø“?ù“Ýßyذa÷lÊ•;PKt&œX„5ónMGäí@@* N#´-|Þ§‚ }g 1Â\sc ĦŠÔ¤ÌP¶xâð­r)npAWEà˜”˜ìz©áJŒá¤UÔÒÍ<ÍL]«‹zsÙ¢“£¶FÚœ”m»žƒëíè£ÆE]„÷¼ç=¸ýöÛw{ÿaÆݽEOhðX5—4\–Šâ•ì ¼ÐŠb$DeKW‰‘š8#`EÕ Ü'þ ¨JÈ1²®u´g^¸£XÎQM לúÖä*×2J)šsÖŒt6mFµæÛ„0SE””\ï+©š ±'L¸ßû½ßÃsžóœ{î¹8òÈ#ñÊW¾wÜqÇiذawm+íŽq‘gS~½Vü\Y¼L19…±äБi^:Ç=X#]æJ,|Q+ƒFz¤Á†(ÍF¬ €DLxx}®,`J”0‡—$8¾®8ŒÓÉ}ËòñÔ€Óðéš•ݵ 6àþàpýõ×ãÏÿüÏñÎw¾¯}ík÷àHÆ »s šÇl3Ì“ULŒà* Õ+si‘‹†|°€ÝO3ęӸ?cîß³é5«t¼ˆ[Æ&…êô“°¸ÈdÌUv/ÄmÖ¡²p G½- >¥çÏ!ÙǨ–‚t¦Ë6$K9*« i»–Íö-O·û>\­¥ì·ß~8ûì³qÚi§áºë®Ûíã 6ìÎM4x<½E`*Vê)'ؘ;殕~Uš¨áƱpÐŽiéXÅkéü¥D׎]ìŒ \v1€ /ï2fNó6 ˜4œÍ3éW’2Òùˆé¹ñrÝ`s,¶&¨Uª°$¬3Š«ì ÷s?÷sزe N8álÚ´ ï}ï{qÑEíþ† vׯ"e±šÑ #7‹°UýåK|7 Üp«Y@pvA(äI˜B+˜yì”"cúËÁHÖQ]Ô:XÙª…V`0Öœd xqÎ}Ú¹EVQAÇ çÉéŒ-´, ¤J¦Äãâj–rã„->Vi6"L–[üTgíÛ¸Ê)p*$ÔH¼eE†)0­{¢—4lذ{Õ¤ŸeºÌ]-ŒÊª°–ù8(~‹.¬•£ä‹7úÓ«& u /4xÆÓÄ—îÞ§Æ ÀlÀä¥ ²£´Û$™Ô[6ç•X/Eí¦· M_ΓõÜ'Û)’··Þ‘aÆí=cšªºwž™þÃ.'„¤lj϶×&‚ˆþä8!µÞàÜ 3ºáÏĪhÇj:‡*´ÖÂax´É·FÕák—]“Ô®£°¢Òá%“{. ^+g™¢…¡±rcEÕ Õ`á·±;Õò,rÞb¶´.tE† [Æ®CëêƒÀFeåæS³³×hµêŠœÊÇÉùòÚêQ·ÈmBµ[³ä=…/U†…%€Ù2Ðò¤it%Å/{ºœE$=žÜË묕¹¼¸Hs_n=3 ‰rj¨·ûU[°ø1ü·aÃV£9 æ°ˆÂ, éñõ ô£¹T^Q0E^λ(P8Àä _è;B™|0Ê´@ÛÒù†E ƒ`=¤nSPÐÔ6Ø9×Z š@!øUT€1q¡'W=´¢"6âÎ(•9¾RRÓ©æñ‡ ¶ÚÌ¡¡ït,„Ï¢o=òj•E…¢>t œŸÌø§hyÛM}JŽ*˜ÞÑCTãdç ãL˜Ëtæå(xYËr_é²K^‰¤Éc}š`,ÇÆŽÒÚèA›Ûi¼ë.Q£Á¤dÀyŠïýwgذaß—&„¨;ø,›Sù@«uÊU‰¨/ÚªÒé’–d¶cAóôˆ;”mcܘþŽ,‡HÞ£XK+Äà©­¤œšê f¥BYH”®h`àÔARM`lÎ) ¶²±RŠ®‚Ú“Ž=™k?lذ{Û‚¤;ea@=™Y÷ìx¬ÕôlÇž• Ørv–Gmì26¤iÅIÏ}µ+¯É)QE•>àAÄÓt¥G«¨†×Ua(°j •“§í¯>ÖJ÷‘á(«' A©R-æªÂ÷† ¶ÊL©(sê½ GÂq‰Ñ èrjHª™|>Er/­œ˜a++ ªS¨TÀ­ÀÉã ü -J¹™5'¬$ˆt!§.ØÜ «¬@h@Ei±Ô*L­.ô­‰«yêš É'@&ùx‰±’Ýú÷î+cb™c欼*OÏ [ŽÌâe‹¦·Q KêÁÄc´ Û¯-¶/Ρ §–äëjYaˆ!+…´Ë1¸TÎqpÊ*Ug÷BáÉEá‚+JÒCÂu%gêbàÐ×]@¸íÛ·ãégž…‹/¾_ùÊWñêÿö»8ó§ÏƶmÛöä½v?¶g<ã8êè£qÛ–;°yóæáÉÝ…Eç‚Ãj…W’D¬¢b†ú Ü³FÇdçÀ xpn£7½’O‹H[Áà%ÂaW1Ò9îÔ[*m2‡f@({·0S¥[8¨`šß`‰ I 1 whîe‚ž©4@ÿ0îûª›ÔÎ-õsê´ËcÜ…/Ð5kÖà³—ýc~ÛnÞ¼'<á‰øÔ§>ÓO?mß²aÀ뮻ÿé?ƒ|àýøßÿú¯0û.>øàáÉíhzpå~qK?k¹'pT*íoy»j*>Êò•^I®°ÉèÑ›#k£ñá@JÈ*%Q$xmâ¤IE¤‰i!À4whLª[Ù„©j*×àUK¢;ÀWV9ä×¶âƒ$O4þK+µôÜvµÆPJÁ<ÏøÚ׾ޝ~õ<ô¡Åÿþö·wë=6lûöí¸öÚkñ ¿ð|<ìáÇæï~·ÜrËðäv2Gá äš”uõ#· ÈjÙwgZ*öŸà>Åû  :IÃŒl‹3¸3ªýæÙ!\¦Ì2ïE¢o£ËuUÝ>åÕÔßÕîô7Ób“ÎÑH/OíÕçÞĉa±cD,–xSKdÞ³½éÍoÅŸýÙ;ñ˜Ç>yðÑØ²eË.í7lXoÛ¶mÃöíÛñµ¯} ¿ø‹/Ä»ÞõN|ýk×ÀJÁ†žMáb:%0ý‡—¦"/3þn¢OêGe̩pÓÓÓ³À*+q¼®%¢˜c! Æ” ¾V äXµ y¶UM—ï Ãà–Ôª@ß8µ*œ³³’Šæ&V©Q,L1̳ÉY]‚.VDæZQ½•Žê.|[nÜøvØa8û™ç࿾òUøgž…n¸qOß»a÷s¸É“û¾€W¾òUxÌcOÀ¿Ýtn»m€œ›FüñÂÝL$çJË<ôâJ -P¦>«…É %ó÷ᕱ zÖkÔe½óÕ0ŸP{ ¢ ,Tƒ¨æÔkšuÉvk`Ô*ô»ÌQ ±(¿Ö0^ork IDAT5ÃP‹þ1 ÜP°âáC˜òå Æ<¶Ã”cwgëׯLJ?øøÀ.Äʼ‚¾à¸ùæ›qàîö7l€7Ýå—_Ž×¼æ5xå+_‰«®ü"Ž88à€î¿áj”i@ãÆ/n)!žyw›™ºR!¢ËÜsÜAÐÖÀY jœáóÕc jôª—àÚºh@Ì‹!™â0~¬<è2a¤Y ~@ÚO¼F¾ WÚ¨AkH½Ô ƒ5vÛÒ¡÷y¾ÈÍ•]ü¢<ôÐCñ¾`×66ì¬7ý÷²Ë.Ãk_ûZ¼â¯ÀUW~GY°nݺû%ÈõYô(Ð¥±ˆÔÌc) Ƭt–Ú8Ñ#Ì;lØñ,1,;DåµF¼èd–`¨ü\$ÐÝã$l`íÃÍ 1a0«Ùd¥b€«*´ ÷‘׿ ¡‰~®p·ÅåѦjQ¡ò–ã0ô’†í«µbûöí¨µâ’K.ÁÃö°¥¿?aãñÕ¯| kÖì‡5kûf‘ûØX…Z¨j‡¡y+/.k«@:DñênãÀDúH" Â¤¶ðÖ¢g€ÊÁâ­I¥(+»À¢rY•àKÂN fp©¥» V1-”E ìjH³*ÞmÏ.•wU&Ž9©Î¥Y‹F-t£¢ro¼5ÆݽsÌ18묳ðñxÓ›Þ„ç=ïyøÐ/Æø@, ì·f Ž:ê(<ðиÿ\5Ç € 5úнÁ˜ÂJ@0¡º°‚Ô_«“C½nÝœõ"m(V/Ÿ|&1¢v1`xp{}°džÒµNywÎVŠX(ú.¬L:+V2±XÝ1™aFóôâü¥a?/ÈÝéKvß۱NjO|âذaÞÿþ÷ã/ÿò/ñò—¿xÄqxıÃn,Ö¬Y³W»oL=ïmºRJ2ü-¶T ðèyµh†´‘¦<( GCÜ2êËr†LUù7ºFUcµ˜™SLkÞËZð …Tפú™lbgÍE­r'=zÄ&wþwQ‘žÅÊ¢€Å •xH –®:b<Ö°a÷•üñøô§?ËþçgpÍ5×à%/y n½õV¼ýíoDZxVVf¬_¿6ˆuëÖÝo‰¿áö(MUò' úÐW˜Ud°y8ˆ¿æ€ÍðL{…<›g¥´‚ôëŒ*Ý¢S ¦çmŠFäÎUƒ{ÐMŠú½¢Mk‚’sÙ"!ù"ñY:‚]Ô,÷Aw*¥¡)„°–»äñ9šäŠ,Î¥ ¿ëÂǰa÷†}ò“ŸÄ§>ù l½ãv¬l»/yÉùØÿýñ§ú§xÄ#ŽÃ 7Þˆ­[·îëe®St'aZïã¦ôíÝßV ¥ªÃIo R×Ï! I¾jpèº*ó ­T†Á5"Gbg4‹Šƒ™¸se#’xZFüN€cÀÜ÷Ÿ9 ÜJò` í\X´ÜÔŸÖÊÊŽv^¿~AÛæîøÇÿïÓ¨uÆÆOÀᇆo¼çwnºé&|æ3ÿˆZ·ß~ûýžW{µ†ñÂÐÔPq›Zå…¸‰ü.¢³¦*Fp´î5‹×¼„^\ü­ U9†@êXLë‡yÏ󄕨lÅ)díªÃwñ*Ukgcî$L¼)Ç&ã&L7ì¾°išpåÿúÖî·Oxü 8äC°~ýz¬lÛŠ—½ìeø»¿û;<ñ‰O·¿ýíû%-d'3o%ƒ.ÿ®'{"†8'Š’F1¥ÚmI‡FOês÷JY¤Þ à4dZý­3ØyÔ ud‘¦´ÜxR kØ©ÇL bËe°æ¤VTX —.öŒe’›¯°­`¹¼LŸÔ­¹ŸÃ†ÝÛ¶ß~ûaýºuøÑýwØÿý3·¶~ý:|éê+±iÓõøÊ—¯Æñ|äý›àK‹"äÔM±"Ëœzþ_„TQÕ4id‚M5ç»ÌQ}f¾?VÀ…iØÜD»p Ñ=]ÁWSb0/Ã4|:_é'× †T°Uõ³’6R9Ì&õÝä¢N¹09Åœž]¼”Ôñýûc4ì¾²R <ðX¯µk×âGò`ú€CPJÁúõëï·•ÓeSe´ïbb릃!£låHqÕH ¨¦†ÑŒra_ðÝìŒR P˜Në²ö„–šÍ ê[ÄôïŠÇ„Tg+EIÉq!¬p‘óL3$u*°š²C1Br)¹ kþ!\“¸âBµYáͱûy®cØ}cwå‘™Ö®];äïw0óBG'hÊhznv!¹¸ 1jÔ=0L ¾òôÒ\Ôþê-®œ2”íFpÓh\€3÷W`XxI®d¸Ž•6"eÔ)«$>œwC›óª³ëÊ©¸Äƒ `¬­½+ÏxSû ‰¥Š#ŽzÈ^xK† ¶·,"9 S6]páˆ*†©Ú-QLd°²ê%¥Ô¶ Rª3_oë•-efXdί""ÑX€@Ü"Rù¹!Ñ+2jr´j†*®.uNgHo‹UÖNÓõ”Jš ;–x'ÆòQÌ`‰8Arذa«É4ÒO&_'ç"›H·@áÀw×V½ˆö×¶MÍê|sñ,B´-›Xf@ZÂ&ÐmS¥{¹ßs† [­Ö÷“ŸÐx¢†™‰dl4Y£… œx—´R÷ƒŠ™Ê2äLfÕ¬E|†][dÿ¨Ç z`â³ôšN1—A•ïòh/kóo¼­0.›^^4á{¨sÖO{ ž)'7ší‡ [u£ JòU£ÉÑp‹FÁ ¥åVLÎ[@kßÝPZäç–ºr5}´À&—d[RÐI)™E>ŠÅ)'±‚Í’ÀIX¡ÂÒô>5uËòä5‰¿qCfãá†i¹Ò™«K~â°aÃV¥v'_¥;cœRŸ43VÑÄ’Ø·`Ê\]ÀG4gÉ »R\€uš”}$Ù^AŒ\@ ç‰/.àR4ïùgÀÌöˆQRFÐá…¾_*Æ9[¥¢ÖI3ëbîš’å3]ÈR‰¸áé99oG®ÁÔr1ÂÔaÃV9‹…•i±–6g'R`![.:G*€gþ=˜ °°œ7˼}5`&'W9ýàÊš¡4q!uM§X3_˜<èw*}¨qv‡K¥ëŽZ©ÕRò$^aÞMùÂÜw¢hž¡Û4lذÕhI'óŒ½R¥;sò+ïÆ´ÜÿqKàó ÷ò,]v>þ¦ áªÎfŽŽŽÛµB!$ˆµ\„ÜJã›.tÔš2¹Ç_ÍKÂZ¯í¤ø´¶ô B¬=¶+,·â1‡Íˆv—j 6l_ØNÅÒ †‰P¥{–u èŸÈ¼Uî8±ÞºC‹Ò‚_S䈮0*P±„¥\`ÁÌ(LU S}^æd«9~¦b¯ÁªÚà-¸dT^ƒÐë¡‘!­%Äeñ€JæËÝN°ÍZí.¦áÞúÖ·âŠ+®ØÍwiذa{bAçp©b ùq²šÿžÍ°‚–V“DšQ¹×‘£F¥Òa*Pàá€UC«DäY Rq„pÇlÀ¢‰PÆØ·ä%gõS±u¤ÂBŽ$ûB‹#™²&’m–~ ?T³«‰­Y-ÍûÂwà‡§–e;o´„É# ¬’ŠIäãŽE8jF0 D;Qm“ °Å ÞGô¡á†nÀSžòœtÒIù·¯}íkøò—¿Œ7â’K.ÁwܳÏ>øÃ—Žqå•WâÒK/ņ ð3?ó3ø³?û3üê¯þêž/jذ ÇÛ3ÊÍ2&„é„o3Ò›ÛQ`µÛ–ÉýÎH6:ŠëñšRfÁ‘+Ái zwŒ¦9öÅjVY[ÈM(Ôœº•Q¨¸3¯«ËÒsËÙܘÿl¶&ÿÂuì‰]qÅxüã¿ýÛ¿Åç?ÿy<íiOë_ýêüû5×\ƒ¼à8ãŒ3ðùÏ^x!ûØÇ⪫®Êm.¸à<õ©OÅW\÷½ï}8î¸ãðÇüÇ{´žaÃ~˜,ù6ÆO4¯øcüKÿ‹-Z¡1¶#_N`"ïV5RÔRzM³–È·ÝéÐ1/˜2[ê)•‡†œœbolºSY=£î­&b}²ˆ…(²ö8Én‡%1Lv*(ygPQ=X‘‡÷ÄÎ?ÿ|¼ìe/ÃoýÖo^øÂâŒ3ÎÀsŸû\<úÑ2ÕW\qÖ­[xò“ŸŒ .¸\p®¿þz¼â¯ÀG?úQ<ùÉO¼á oÀýÑíÑz† ûa2³®¨™ÁÙ øEŒ©~öä\°ˆS¯TQU.ž9¹têZAR,pˆ7@ÓßvÜ¢V­Rå Z‚ŠÉÕ$è˜5IàÊM ¤(Ð,ª+¬ O­š”æ‚X$ÿ‰^ݤŸÍîï.Q—lÓ¦M¸ì²ËpÞyçåk§vN<ñD\zé¥ùÚÚµkÜàÌ3ÏÄ·¾õ-À¥—^Šã?>Á ˆ™™Ã† йúÔ‡,𺀦\‰7 ¯lÇä?ÕÚ@)g&¾æà+ ÞÖ¤‡ð<¹yŒ1;µOi9‹@`ö†¢D÷€E1Àk¡ºfi:p½Tp.dʼ™µjÄ–¢d‹ªÊìŽÉ¦–»£·ØI”äó«ï]{íµX»v-9ä¥×=öX|ç;ß¹Ëý6lØ*×]wŽ<òÈ=[À°a?ìVC> FÈ©"ÝÎþG‡!ÆQÌÚØ­ƒݦb1d¾µ[uóäìôak"…ØjO?£#U ¨VÃ˲-PÑT``œ, È+1ñ&/&BÎ Àä–M} ©°ÑÁlŸ©8ÛI×½›¼¸[vÄG`ëÖ­;Ù¦M›v*"Ü•yä‘éÍ 6lÙ…á¢U‚ÊßëÙe!A!§«Ã@1fpä_ÿú×ñÿðùÚ·¿ýí]^ϰa?ÜÆç»Ÿ‡\ýp©VDU>ÄÿV&%†”Èé³€©y¨ÊÓ«J*0‘îäÙ1©pư(”v k‰û¦J§«‚aœ?¨eF…uNÕ‘P‘Ysáá¹[™•Óâ’[2Ba¥ü š¤J&+w äN=õT¼ùÍoƺuëð‚¼àÿgï̓.­ªëáµÏ½V@SAH€b" H' ? 8&€R%1œêLF£ñû$&ŽX΄à„5?  ‚¨ b™`ƒ±ŒÚ–ˆ *C;DAèî÷9ûûc¯µÏ¹Íô‚¨×x–B¿ïžávÝÅÞ{í½6ÞñŽwàiO{¾ò•¯`—]vÁÙgŸ7½éMØi§Õ-°Ùu×]ñ×ý×8üðÃqÄG ÖŠóÏ?lW"}´Š©kÌw –"•ø5JT^¹UWÕþ[ïlûYÉ+Í—%-Gï\©±2vŒ¬²^zI_áý#qPWßZ'¿êÂ2zãzA±1rH:•ö¬[x^Ýr[­Ï½5‹¬¯yÍkpÖYgaë­·tÐAøò—¿Œ .¸›6mÂñÇ?øÁùú=öØ/zÑ‹ޱÿþû/ÔÝ^þò—ã ƒÂ%—\‚v؇r^þò—¯êzþ7Ã`)äüº‡åQtxx÷ZÚ—Ö¯a]Ã?+õt%iy›–RÁK;¹F=rMv`N¨%Î^`¿·ÛËTç®_8j:†4Å4§ òR"Js^„Ñ*ÉK,¢ÈmZÖì’¡«uÄ2„Mæç²xÉ~ºë7|Ÿ»úïïÑ¿œ»‹w¾óøèG?º¶ ü2âwø\l³åa5ó0ǠИû €ˆè¸”‘ZÉB‹äè¦iµ‹ÊÐæØµžPû_ä'·#Õï&f”VkëœA’ÆXK)Sí¿ÈAÙ6µ ç»0š:]¼g[¾Ú¢™8”Ù¥ðj^eŠúÓÀ4Mùs­§Ÿ~:=ôПÛõ ,JN/!3.%^‘¹qDûxC0p˜M€ñ{Ævt¯u Á'úÌK ":Ð¥ÄáQƒËfS‡#Ç®ôtÄ• ™U?9y6«#9g!RÇh‘$dWѧ¸Èš`kv›¯ûâøãÇ7¾ñ ìµ×^¸ôÒK±å–[â9ÏyÎÏíz– ƒ'ª®EC axÙÂLóXy°s^,Ëkw¶vxË“'ŠW¦¢Q§›ÇÄË›1çŽö†¤Š3w–ÍRtÞÉ¢‰WóÓøëø }o$š¬ÕSuý#åœ#ÒÆÚ©©\Ì t$i]Co⪾ŒUºž¦¢žÍ$8ƒ1ãºDoY¯/…?Vù\ŸMG·‹$;00°è;"Ü=ÔnxÅZ¡+€ X‰r¸Q¹r4 F<öÍo}Š„ÕNl°|€u‹ŸÅÁ®Ù×™ÿ24#A•´7 §ÖQ’é¬[÷圊(´öâðZ©®Îॢ–Ê#Hq¼fò:00°d¨.ç!Ú„KX´®¶ey`Ÿ,³6cjÉè¬-˜¢ ›·@ÇaLk[šê¡!<#u"£ãoŒ…V ì’ô _Óq¤£ ²³˜ÑØÂ ɳJ[[q°²…¤¶ûj'á2TÕ’vÿEèâ僡P(LØ,w4$fKGËÎÒ37 R݂͡ù‰»U•~æO¦,Ryd,¶‘'ð$²Ø« ´€kób"kR„*iUóg‘XtSÀ »&ÊPO’™_sOÄ`î–M}éB200°|Ðz?oÆäÑEQSh—ÃG×¢´>õ v™ºõ…égŒxÎl±ÞOÏÞ¬ÅåñŠetÄ ,¨WpŽ•µ( õ‘¬ ~ çN ÚšÖ‚qB{ø–Hµ’¯K»ÉnBÂ7wX”Žä™NVP¬²$œ2s‘Y6R¤0Y»V°x¸õàª7®Ù¢³fo:PÓn3#Ï”T(ßšg—Z#sT«]É¿Eeº=ãÁÍ Ì f^4e%½AÈÊ‘½Ë©ƒÉgÕãýæ\îºúüÝï~7¾ð…/äïgœqÖ­[·ú ¬òfëкf Z ˆž°d‘\4Ÿ!­DÏ…K‰wÏ5±³Y¦kyUë—•¨é(ifidJ΄Yå4ƒWÌÌÜ¡mÓi''ñ  Ýeçr±&bxôºÙÝyDŽ\Í÷Ňá<“¡#÷;Ä©§žŠË.»,ÿ“?ù¼ç=ï¹Ó÷ÕZñ¾ßûÞ÷Vw¢\­´äëá\çWYG›ÕÇdŽ)÷žºV,†æ‹GëXQ ZaýΑ½°¦à¨22ô.Û$ODZLUÖ sña×p7*O¢&\5è±ì,ß«6ÌÂЇµkCq ±¤Á¢„öä$·Zä›ùÉ —_~9îsŸûÜéëÜ'tŽ=öXüÚ¯ýÚOpÆ_ …r…jlÝ•[ì]Q²iÝû;¡zEFGËÿÂtMƒQnÜÿâ”BÞ!êüýv¿9`QóW“ö¡ðhÞM ½­MÐyD¶)Ð19†1(ݤ¿n³?—yA±Â^¼)_swðáûí·öÙgÀ7ÞˆsÎ9×\s öØc<âÀðœx≀SN9¿ú«¿Š¿øÅø•_ù•»uÎ_DÖ•ÑLƒ²1‚qw©@;5ÖèåV¤tµ ¬Ë«G)K ¬“€&`ÀÂ3Î8ùTÊ]¨a¸ëæÍ¦¨gÖFv[@rˆ5„T6ïõn¼Á~I†ª”¶š§S¼­´í[’‡É¾ËÝ–N=õT”R°Ï>ûàÚk¯Å~ûí‡=÷Ü{ØÃpá…âG?úžóœçäÀÙl†ù|~7Ï60ðËµŽ…I¥öéÙBÝ<»a€Ñ0ÄTq[lk®qñ")¥°VÛ 5¦²x2ž_KiæÖ¨¢EWÝThüÛØç’³£´³¤tÛNÜ\Eâ}ó¨j Ë IDATªÆ§(hxF‡ªä9ä ¥†>¿Û×pöÙgãþ÷¿?.¼ðÂ[=÷Ò—¾'œpžÿüçãAzÐO|®_Ô,Iñ;뚺l|ন‹ßee{4Ç5—!RûžS­WSê<@#Ì|^A™ªø­ÆVQØœVÍ1e|É<[dê扭0%Q¹>CñJø÷ÆxøÅY–©ÅÂ(!—ŽÜ*¤Þª¶÷“aÇwÄW\SN9ßÿþ÷âã ü²£xl¾+…ßñ2AcW‹ÍùñŽ6š¹¡ëóȘ֤èÈ@J#¤ÍêäªÁ}RO|lS³ŠR•¢5štÕ‡RsÇ/[õ4WלD‡¸ÙÒ½7ÒÌšÊkmšu-Ⱦ¹Îõ³µ½5yá'§¶À¡‡Š·¼å-8ù䓱Ã;àÈ#ÄUW]u}`à—!"x’“`,U->Þ7÷^˜eHFyfµ‚Jk®ª¼F«8;ßÅ{rF4ZÍ®Èci±]ó·xÁA2ÂdZj]ƒž±êkâ|™ÈÒ)Ý’(Y¬0LV1¡­“²Ê{E±f½tOàØcÅå—_޵k×âꫯÆsŸûÜ{丿ŒH¿/,cËùs0+ä¦>}§YÖwV,6óU¶}X‰)(µˆÉï­cƈˆª&ÀbHßͰÖ먬–¨I9+É7©&CGõ®QpVÿ“Äz¦†ZH jÜÙR¸ÙZT¢QíŒ^QÝ] îf†•••Û|®ÖÖ‚¸fÍuÔQøö·¿ (¥`‹-¶Àw¾óÕh`` ƒž® ¶P'“â™ ¥)2c´WË[*®ÖOJ±ûBÏ̵º4+u|Ž™¨[4¸¹›}}žÔ—ÒÒÅ>õŒU€ÒNu‹ 1EpÙ9Ü&è( •Çhí$`°Mäz*!«ßõ¨Gá]ïzî}ï{㨣ŽZxî­o}+N;í4pÀpwœyæ™8þøããTfxž€?ýÓ?ÅÓžö4üñÿ1~ë·~k•gø%…#Û3~«®‡‰=iÙ„¡š‚%Tèš!J_UdÈ:\Ê– |ÊW1@{ZJšÑ `ê³C[¥ÉeDMÍzDæ”àk#dlJ¨Á0QII±Aù¹,ŠÅÌf¨é9´Y´ihtCM‚ºžÕâ5¯y Î:ë,l½õÖ€£>ûî»/à¸ãŽÃ^{í…uëÖaš&|èCÂþûïŸïýçþgüÓ?ýnºé¦|ÿÀÀÀíØŠf‡•nïq#õ]´SßýXK¢e«Ÿ‰7"3LL7ãøÙe‘Q>£kpiÁ’=~×ÿÏsõ–æM•²r©CÙŒ™gL´3/n€Õ˜W \™8Ȭôa89¼³Û9»š="ExÅõ¾‹K¯ù‡ŸæßÕÀÀÀ]Ä~|î{ï£S‘%© 8MŠm? ³ÃÙ`Q䆉jh EÈñ—P+™RÓRƒwjá0}ý2+Ùµáî˜+B s6㚺ën¥g`Ë'ØëyEqÌÌsY¨t°?¥Ít¥xÑ磖 Eµvã4TuÌ´Ò%;àì™Sv©B<…‰´/×H¨ßF®ÒO ^w¨‚*<+×_X‹Ü²§²Õ׸úÑ¥Ž¤™Ô’¯lekÝÓ1Fò»¢aW&„jx9‡æYrX*X˶j­*):öë |] ³Úöˆ:.â÷VƒÃ¢P$i¢µhrŠÇêææaŽyN : SÆ8†/(1d»GUÙâ X7º¥.äp®lÙCÖð]G²Ä С7v```¹ †Ýb˜"k ÛÛ÷QoG8 lâWPÔñY¼OuÿFry׬|¼Zýo›‡K†Š9ÜÚ½M(>o¯‰MÏОCɰf3D³/M+MÝË:l·9ƒE͈±8 Õùz7RR).S:·%ÜÁ~XW==«b Ñ•ÅÚŠ–±µWV½´~ÂLQ™Ü”çµÌ&Kñ½ì‹cöçnp/±tJV’t,]zÑK5“{¦‚ÇloZFv[óç¨ë±WÎ3Ž$2ôEVXÌj‰ER¦ .„³3ƒ¿déÌ›A‡u¯Mº€£zí–ÀÏ ™ôxC…&$BdíÎiˆé†Ú2Ͱc²ôý@Zé=zQ|Z€‰ad,gŽUarïäè~k€F³:éʵcãýÄ~­þ ¨JÕe```¹P•Ñ9"0ò)› •4"½ ·p2üaÆ9Óh´Îß\-(1Fß¹ü¸ ¦c†c®³yN(œ-iDs@[ô@CΜª–G/·¬Ûe}O·Þ¢>˃8ÃØÖ1g@ÜŽn``ùP‹Xè¶„¢–e «¯pìhP¿[: •žæâ+ ÂÆ{TäMIiGë+H y#ÿÒ¸…#šõ¢Ó}?00°<Ⱥ›ñ ½¬$5ÅB°Y×Øï’¯)Žê´ùö˜3…ÔÌãZ‡‡ÁáU6 (=FjêM#(n!2D¸¨å«5‹„@óAoÍ!ÑÊÑZIt„~ä>nÖL{êÑõŽžÑB¢80D[ê!ds͸ ŠX:tnÝÑK+W¬mықo­-y.¤ ª8{^ál%1&ø‡Ùf8ýD`ÇH@#`†Â½¨Æ\ÙÎQr/Nòë+j+Ò"E‘¢D_µ'Ù-ŠÎu‚ÌÉãá¨óÍ270°lhõñ¶r =L^QlF×^À+KaóíÚ¡,z2³pr˜jü aEúXX­-ëDDn‘P† a®œ®z-!1CÚ]˜&˜L_cfTyg_rk'î1‹¶²–X¯-TfŒŽ"CcX>¨Cλ­fÏ9uköhÙ˜ëJ0­E2|SæGo¼ÓPf¾"I–ªË¥T ÇÜLÓ œûúj_ÞjnÖÒW¥Ý¨Ù‚ûGE›Åˆ”`Y|1§–-Ìí¥#ÔöúAqˆÜd…>ãÄ—«W”¢Î`E¢‹[jì5JmÂcO’™¶Z÷Sbõ“yañ„yLà“y]ùðbR¨íó"µÈ— ¢›¸¦í¸÷ùµT«)%—Êyµb˜tYjæ•U“” $Õ‘  ,\ŽÜ¨åL!MvåŒ®Š¾À5ƺ¦Í2¼õ°uóP”T}Vª…WíØÎR–Êi`“o‹ð"Í牨NH!VÎ&dz#:] Üè®%ÏFåi†³¥f@ÛÛIþ—ÀÑÆÃúýeƒeM*fÑ7õ¸Ç2wX!Ï ’VŒΦº‚.d«ØÄ`l±hURMîQ˜èˆa{PëŒþ’˜­Ö˜4N®èŠ-Ï^¬WSkk‰¡ˆ Ç``ÊÞ`Æp2GDh©œð²P¹§v2 ܳpÙdˆ€&Pšem¿e‰@ff^àj SÂÉBšµÒª¥‚5¸FA›‡W¤Ódš|`ÊGGßÂËb8ÔXdzƨtÙŒ³{¶Žek7áΉ »Yzl7Üß,âçöµPT!íÀÀÀrAí\úþhå%eaô‹Œ/|i¢˜ ZVÒ2­u,–§2àJWž)®ç¯A”r$š§Ñ¤ÔB½ÈÖ]lMk¤Ž(Ѽ'y¶=Ó¢:Ð>Ÿ§ Ô;cÞY õÎ9—K vXF´ÁJD‰Ê¤„v>HTùÂ{5Ue˶ð]Waj 0C­ÆÔ–M¾.¹­ö¶ÙhØI'ñŠÒ…—Ѧ”Nyq͵Y ë&¤ž@úgÉú]FŒ¢„Ƽj—Ë›fS­)°Ë-e®Yo´d¦eŠÓJ,hs2Á†ÜèÆË!ƒ8¶x„5;s«t$)FѪšúj™YΫD%Ó½ù3…gºR×DIwíÈYê§-D_âÇ’.­Th…*og¯¤Iµ˜à5¸¥C• `Ô‡b¨^» ‡‚¥«ÜÀ µH¸DØÍQ$p2Í-¾ÀÔ ”Q YµõðB"CüTr>¬t¡;‹[üÆi…”VMn\4î2‡è½WË×Vö¾è–r™4 ¹æa```©ZaK-‰Wƒ¬iZµ5ìšs `þæ,~¹ìŽšëˆ26ïU«Ž_9ÞÉ#y;&ÛD,óæÞ­)ÀxʤˆŠÐ¼š?êà\ “ª©ez„«T¹÷TÎñÉYÖzïÜtÓM8묳póÍ7ãÉO~2vÙe—{îà¿D0*˜£™ƒSH%*y«)ÒÊ\®„×w Õåc‚¡Šv*C[—à<·¶µœiKŸ7ÎÁ41! xm6š”[ýL'I·_ž±v’D<7¨.ð‚ Öo–Ç›G}Y0ôF¬?)~üãcÍš5Øc=°Ûn»a—]v70p7‘M·@‹¸¼d ½ZoÜÑœ½Å%Hç¢Æ]$©±Ë‘¯5FzíoýtzóàÝÖK‚<¼%™ÇôA„Ÿm†L³Â:ÙDIc&Ù˜¬ÁWçûÓω•H ¬éeHOözÕàÖ®]‹þð‡øÈG>²™b300p—a3FPf1ŸÜPr]•êè…~qáº&e5ˆoÖùIÆè§Ã0cªK‘¡àúQ#‰´p p¯L]ã¼sÓîe³ê˜8W‘­n˜!šìšP¼t¤ãM„ðp ê ÞÙà(ÅÂnIöè¬2¦™‰½/ûÝüð‡?Ä\€ï}ï{Øÿý±fÍÀ—¾ô%üýßÿ=6n܈W½êU€¿ü˿Ľï}ï»v‚€ª•s7.rÎ5QÌå´×عŒÙJ–·Š•õLÚbüF×^GpEˆâ•¾ ¬*ŠBf‡1#Y)àâ8j©¨¨˜Ì1¹ þ!2ÈéCU¤Ÿ5þ)qK…EÆkëÂ,É-^JçÌD5ù¿USîÆÎ¥ÖÛß1¾ð…/àa{Î:ë,|þóŸÇcûXüÍßüMœß ¥D”8ŸÏ1ŸÏWÿ900pk‡a01=Ô~d‘S ²G³)ÞW#Vs›¡.,© ÒS>„ŒÖ0ÖϺZ–À"Jœ•œ9óªƒ,0#hÊ5ùG«‘Y2±LÅÓ „ås‹¶Š–Y:x¦éžÂ#¬võùÏ>Ž;î8¼ô¥/<ûÙÏÆÁŒ#Ž8yÈCð‡ø‡ø÷ÿwœp «:ÞÀÀÀíÃápÚs«N~+'okʨDÈÍÑ–\m§jô×j°@uþxs=Ë6ãxØÈ'ÚÄe.Yœb6t±¨/&ΔqaŸ Õï,¬#E^v´ XÑKã¸z,RÖø3Þ¡–Y£ß1Ö¯_K/½ÇsL>vàbß}÷ŧ?ýé;?ÀÀÀÀ]„7C›kޏ¨ ²C¡Ñ‚'ͱ*׌lÓ»‚„AÍsñOmÔ“ƒŠöüXMmÆ›ÂÉ•`PÏrlÒ2æËU`ý¿ó#Hµ´µ™h{=;ßØÏ¢™SÍ7xH«’®ºê*l¹å–ØvÛmßm·ÝpÝu×­âwÍÌVý² éT§{8¿½­×U½`Új°ZDkЊ@‘_ñð‘,ÅÂ6©ð}•’ÒY°ªo@õ’)l‘j)ƒ8Mç/ Õ™ábu.˜éH·?Fײð¤}m¥ ]$.{aÏÈÝŠÕl¼J'‘í·ß6l¸™­_¿»îºë]ý»¸38hsFÕÄ|RëDf|Qk¯]]=( •—LnÝ-²¬ê ¥ïný*žK˜Øt_u­J/óÁ³Àj¤™6RÆ­ CJJupžlI1õ_cÏ[©Î¤ÈNwúYï¼óÎøÍßüM¼å-oÉÇÖ­[‡Ïþó8øàƒïÞ_àÀÀÀíƒå&ÍÊ3¨ DÌâLIùM5 ÄJìf `éÆI(؉%6)#ØÇ ªOp›£Z  *4ºÅÕ æÎô0ÓÇ”Y-H©ÚⰻʇÚÓ¬R¨3H‡ètT†’]’nšYµ¶tFõ7Õàrßõí£”‚w¼ãxÚÓž†¯|å+Øe—]pöÙgãMozvÚi§Ÿì/r``à6QSÖ¾²½C‚ë÷µpŒ3­Š ¯¢|¡¦—LImÏ,ò™,\sû¬"`b֙ÞŒÍd—äMë,No8cÔTTÚmf°4ÚðÁQ­‚î{ÎçNÒÕôrî¹èÊ‹·Z~º7αÇÿÆÿKA&“T&€ìL1g7°¢- ½á\Ï ºJ²e3°7áAEIã^Ap)Â#díXX…Çmø..½úÿÞC-÷Ö<ð¹¸ÏV;Áá˜e˜‚CNì[3ÇŠMt ³D쥔•cŸœ00°hB@6æ§Ñc×r¡ÁA ­( Péj¿7/þÛ[…®QGÑßœF½†•¢«Òë+æ®à-£8$‰E}­#%§æ ¨.§öu#l4qÀ6½©jtÅÃ’u:]¼&ƒ8kìVeÇ%@І“6´˳®nZ0…h 3fÌK•ž"ÞŠ)Û-8²©RO :[]­!މŹq8 ,B¹œh/ÞDƪÍU™ñgIÕø#³ªÕ üþG<ÔœÃ+'ù›·¾ 5·\Ð<ãÉH›5µ2À2ŸE“]ÕðëbÝEQ7˜uZŠÔ Š:žT‘üÜé·®¦¿ $3õQƒX:X¡pX^Uÿ¿÷­nŸU÷4ãhQ'²ÖÞ¬ÍfÖØ& -sà+]2ÒdYî-kÍ1+¬ò¸šH(h=,Õ ZaZúàÝ…x| 2%&XÖÚªj’tÎe¥Èž‡X.”ªrSa ½fÇ…¡Ð÷18Ae©ÚÑ—²½˜|ˆH ¥¶{ ¦Zq"ŠçTdhe¡ñ70÷pô“ñßœ +‹/e~­tUƒú¥³1Ñðm[ð ‘œia ¼Ek¼¡œkÕ1²800°LÈž ‘ÿ”›vÏ`³e0Údï&ço[XÊ£f³n ²41¡&ZZ+i_ƒ÷s­q^y±”Ö¨(¦uó^ícX¬§rÒÏÄ÷Có­®×fÑ̹»Ð¢žwëÍ2Q³ËsÝ#÷(L55§ðÈQLGôtt¨@L”苬ÏÛsÆmz)`FΩɅ|Lílæ¨Xêoõd¦8ç;áeÿ’ êÄžBM†‰9™ÐÿÙþ»¡º›œy+fTIÄü*º—f<Âx¯v&Å#GX>hy;0EùŠA•Œ’ÒNÉ8R…‚¬Ù§Yt{€K®¢‡-˜(c1òòwa~+T! • ŽÒ£ÐsnÞ5oè²ÓI$D&ÌTd´V(8¨ƒ™±´'ÕL¥† ÚÅoÕ ŠuÛ–ÎwŽdÌ>8Õâ–ì~¹D°Åâ–W!Ô¬±Ã/ZÃ)Å4W!í‹7Ô.fj–Ë´¸_†&¶0o=+ÞZB:±Bº@šeƒ‡·¾—ʨmÖ|V•=oRà ·š”g …Œ´_Fô60°œ°H;cRúÚªàTilÅ`HB` ¤1wîsQç…„Èt†ãlküX#u˜™ª”¼†øßœ¼BcIŠ „V¼¥ˆ S ð6«[2†cÞŽ7™%>ÊÂÆ¹1¦·™sKÅ%™ö¿«4½øB ©à€Gxã9òÙøB ýÖ7PO­q`ËšÙG2¤·MË}$ç,•©¯ÎÕ‰ÑÕ#œJOg-Mj IÓºŒ°&¨X๠5šïj’$0kW@œ$ó :˜(ÝÙ¡v ,øýïø;EB']:é$€.s´4€T¤WÛ„9¯VÎùVÐgÉÒÄkóLÝm {66"äRb¼ åÒzN=o³%z¡@ý2U¨©3&$Þ0¶ãÈ…5Å ,ÄÄNB'‹ÇÑ˪ÝW­ÿ5ý5`¨œ¼Š_çô£\ Éñ—U"]Çcœ”íf˜«ç¸8b 3Z$E7¦™μKvi£“„jF^hÇΆ¸ðñÉZ›ž£À}‚4YIÏ%ÓÔ…ŠÜÀÀÀÒ€¬ä‘ÁM,µ,ãÊ×B…Ihlå©2·µ(±-cê©;#:°ñ·ZF{E?;0·*XR¨)’Rè¨NaȰÒD»%7æè¦MFw8ÏôT¾sm€?Ce­ç(Ê› 1»‹—MËæå—cšú—EqµöÞHcEˆŠ¾¾vî!,¼)ÄtLü ›òÿDoï}ï{ñ…/|áç}?ShêHßwxÙ<"6T‹¥ñ¤°¬ÂË”ÇPUß½tÑœ|*éXYû…ò2ÅÔ~®ØxﱯVƒ‡è5ÌÛ¦û{·Ï;‰¾¹f‚Ì©‘XcتsÞ‘e©Ím³XsàÁó[ߌ:ñ¤2,7ɽç=ïÁe—]ö󾌟1è )qÑ<=àúÒ“Œt$er I¦^¯‘,oF¹$yU´`Ýï튢ÃC Ä\RSÙ!\ÝÈ{IPÙ¯fœ'#í©kXÞòæ¢ÞºÝÃzÓ ‚"[Pâ–›à~án˜´R>k“\¥.@c]ñBÖãÛʾÈè¸Ö ŽOxÑÞdtijo”C``$Zeeä<£‰¹iÛ´·|¹°Åɲö¢$ûÆÉb= ÚKt)Öy>yºoæÑE„&{Öæîüàññ|á±·½ímøìg?»ð؉'žˆk®¹&_»v-N:é$œ~úé¸á†òñM›6áu¯{6mÚ„|ä#8餓pÓM7n¾ùf|èC›ßüf\|ñÅ·º–o¼üàñ†7¼gŸ}6®»îºUßÇÀÀ/ ¬¢GªÈDdf°j˜1 «L¥›å~¶œ©· Ñ ÛêlŠÈ-™£" Eu:Fwâ‹ZP=ÒäRË]b1³Ã'pË´Þ®E¤&¿¶¤±yU´SDFvÅrÅB|¨üÀ…Ϲ}g¡f'e–ŒîùßÛÅ7¿ùM¼úÕ¯Î߯¼òJüÙŸý^ûÚ׿c_ûÚ×ðÚ×¾÷¿ÿýÏþóñÌg>_ûÚ×ðú׿{ï½7¾õ­o6n܈—½ìe8è ƒðº×½_|1¶Új+üà?À#ñ¼ñoÄ׿þuuÔQøÿø<ǵ×^‹=÷Üï{ßûpÝu×áïxÎ;ï¼;½þ_80©P«†EíLÉ.&”fYqw¯Q¦RÇ챺‡ÐYŒcTæ”8e…n­`%2mu”Ñ'ÎKżˆ9Ù1¸ûRyv¨h IDATn@’¦iÅø¡€Ž ìÉ++îJbzÈ!‡àU¯zn¼ñFl³Í68ÿüóqðÁ㢋.ÂÍ7ߌ{ßûÞ¸ð ñ{¿÷{ØrË-qþùçãœsÎÁºuë°í¶ÛbeeOxÂð²—½ §vZ÷ðÃÇñÇŸ¿Ÿxâ‰Øi§pî¹ç¢”‚o¼}èCóù³Ï>÷¿ÿýqá…Þ…«øÅCæf,†i¹LÔå‚S²ù¬ªà5ƒ¡f–æÖ-tŠ -^ª°#Do1ŽÅW(´n0&ÇÔ Â:šiK"i¥ €ŠÝ*¬DCH±v³U¹¯``t[µ Ï'£•f{RÐ:å¤Í”Îu䎱÷Þ{ã| þíßþ pþùçã…/|!vÛm7\tÑE€ /¼OyÊSçœsŽ8âl»í¶€ù|޽èE·"&½^øøÇ?Ž£>¥Ä•n³Í6xÀÏï¸ãޏâŠ+pÊ)§àûßÿþê.~`àUuzWO+ i$K! fPE}Ê%ï­Ê,oµ-²ÂÌêñ ÔZqÑEáIOzફ®ÂöÛo¿ðþÝvÛ ?øÁ0MÓížã;ßùΡmŽC=oyË[pòÉ'c‡vÀ‘G‰«®ºjU×?0ð ø]é¢CbƒêêHEÓ¼ñ‡g.Û‰’爼â5 ÏäËÉŠ5‡±Ç”‘$PPª9 €Qö›¹²zÔä¨)EÎ.„y´ƒ”Ö;Ç‚¡¹RÓÚþ±•Î]$Îæì‰™0Å 2'GgG¼rÈ!¸è¢‹pñÅãx¶Új+<õ©OÅÇ?þq\vÙeØi§°Ë.»¶ß~{\yå• ï_¿~=vÞygÌf³Û=Çm½os{챸üò˱víZ\}õÕxîsŸ»Ê;ø‚wké4dn¨În ¼({jeyÊ#;Ð9ð²›Î#+T½>"ÀŠssF‚2Vå¾÷¨Tù+§š§›o~ý`l@¿š#JUÕè­rkFbÞ^22;šá꟩ÙçL•ÛcmÄëŽñþÏÿÁ7¾ñ œvÚiøýßÿ}À¾ûî‹Z+N9å<ùÉOÎ×xà8ýôÓÕSO=‡rÈžãq{þîïþ›6mlذ?üáóùZ[´¹fÍuÔQøö·¿½ªëøE‚æØõeVÊYlÖÍ¡RçôBŸ6(+EÉ èþlßõŠÐ*Cd¨­MDe/oœå\313Ì‹# èŠ5ÙUãWN1¡d»HHÀfm´œ7•’êbM ©Ùtã,9®%ߦv“mW³f«Å[lƒ>ïÿûñŠW¼"?ì°ÃpÊ)§àÓŸþt>vä‘GâŒ3ÎÀš5kpØa‡á«_ý*®¿þz\pÁwxŽW¼âxìc‹5kÖà1y .¾øb\ýõùü[ßúVœvÚi8à€àî8óÌ3DŠÿ-® ëq”j³P*(h ©ZÝ­µþRœPs¯‰"”ßžÇs3´¾:ËTÙ«/PÙÕN]±Æáy3ã 0ƒ6ã¨ñCUÉΑÚ[¬ëP@ž.êz•³®Å¬ñ`Öÿ £#?';¯žäþâ/þpvØa‡|ì˜cŽÁvÛm‡G>ò‘í/§œ{î¹8ÿüó±nÝ:|ðÁxÒ“ž„-·Ü@å+^ñ l·Ýv Çße—]pÙe—ácû~ô£á˜cŽÁúõëq¿ûÝpÜqÇa¯½öºuë0M>ô¡aÿý÷_õõ üÂÀ‘žËb†Î W*§eà£úY”Ϫí_–‡œ‘$A^Iž²Íêúµoðån Ööø]ÿÒû‰|vkˆ1+@Ι:q#¸,øi‡©|™èúÛräHmWz…ƒÍ{¼™äe¤Š«Ûºá–«ñ¹kþážùK¸G°æÏÂ}î½#ÕâÈðlÙhlÅT‚4.v®ì‘c}>šÿ À½ ÞùNJœPÐSªÖ+°w¶ªwnR\Åb’ð §ùs64X1o€‘WÍæ.kÍ7äMV£LÌœº"Râô¶ôhŒ]¬NŸ9~0›Õ~þ0FKj„ »´’nQvoEq]‘§pý´"D²k5J\LWÍ$üµ‹ù^dRhe¬ ó %Ï uë£* "9î@%[ÆÉ ÔØj–•0 Jó8Û$‰—Kc­óz*úäà©´4;ôåAù¬‘LΧs‹kH@UuF]Þ^Î#‹)­£²e,ZÓ&‹ß%n‚aUDxÀ¢ra€«ÁØ0ŸH«3õüšÒѲÐî¡™ÒÔpÆ£„Á •;•×4 pKâKÛ%¾Îºˆ±OQ³zÐÛÀÀRÂúó”ãX`ÔF$&o£˜÷od¬ÆA{.Žîç㽞 j¼¶Â¹ÈÊ¥ÖfQÏZ .³Æ ¼E÷pn±ïRÎJ‘@áfóŒCæáÙá›Ñ^vµ ]~½cßÛ 5ã"]¡Û˜bXRDäUõ=U@2,@Zv˜õu}ߥ–"RÖh¨ôË‘yfˆ30ësR£Ž“\çèÉsJ™qI* æH6ÂÈ6‡ÃéQ®=@¼¥q-ª±ˆÔ¶Q¤7òÓ–ê–é¦á@ïéÔú– .¡A±–ç´VÖÁ8*P«¢¬fÖ‚0q¬Ë+˜Á0Éù›–m•ÁWq‡¶¥èÜÆqS¥»•583ω`D,^LiKÝ*kráÞ™˜#BSš\š5•D)mö¿xKU#[mªEúÄ¡eáCeX>¤zi {ê_ÍõMµöø ³#IƒBC·ÇTEwé­É7ÏJ^ó–øñ}.'’JuÃ|óIÖ¾A’I¥98Û”k¿›^%§ßî|,{cø&µ©ä‚š¾HÈÿBŒ@n``ùÞn¦ï5ÒÑ#›Ç ¨tQëX€ñ@,½še·ÅÄ (,㘦UÏ•2{49†#)f®—ÔŽQ‘îtøð6ÎUIx•'TO Ð"®’cšv¨0›²˜´hK•á] õäÕÁpKM,U ÚÊ×MÕ[”ŸµAú¬Ç#"¹ª® Ú+µm•¼ :QS¯S §´YâÆ\'Q´×?³®Dã…j‡Xº‘ÉZ“sîcü+âêÒÁq|Ö{´+bXFÄÀ|+Q•¬‰ñÁ$6–£º}%êƒõúA)^2©F_ä ‰V¿3Qj?³F–±wy‚0׬fºV:ÕŒÊè-®½m¾™Á’-!ÇM©$0ÌÝ0«…;88ÏÔÚىܸ¿±d{ ¢X6è;m¬›G«t{Oè2¦+Y¶38·Ö+ˆ?´¯FúªßU³·¦W*¬Zèèà.sÃK ÷2}Œ›hƒóYÍ4ÕOö:¢w™¬ ¶Å[apÆ™²`f4•qx7p± òýË…–¿© ‰e ÔÕìûÝ©ñ.4ÁÀ;'¢î=ù:¾6SQЫһ£qŸË?.ú{g€596ëfRB¨„.FQ[Äåm®Ì´A+bCLÆZÚÞíñ üÃ?Œõ‚? DIª¨ŽgÇXÔÒã;;Uéc×–Ù ¼Íª˜â¦ŸŸbfžÛø¡¤ºU€f—‘Æê@®¦– J'ÍŠÈ“I©}F,¦R\¥‹Œå}œ¥¯4©ø,T–ØŒÊçòY¼‘ÇóÏ»’œ®]»çwÞ]xÇÀÀÀÝG4÷¹£-kßoÑG³5÷u‘H¼Ë#jkû\Ü*&„o¯FB›¬Ù.G$ÉCEݼŸ-¡”V¢I/÷5à6Nö¶4b$}™¡H&5 ùAi¡4h: Ì^rÐ^ŠU Ü_|ñÅøÌg>ƒÿú¯ÿÂ+_ùJì·ß~xÊSžXYYÁy燯ýëØsÏ=ñÄ'>¥”;9âÀÀÀÁ2Ôá ¦"9h7)Ɇ$¥>9 í8Ö¢¥Æ‡Ù8 }LxIk&rSFÉß#sÌûèÉ€¶³5-‹ •Ìf€Ï»>Fi¤§vøšÊJ¤ªÎ¨°°'ÎÛŠÀˆG¹´†ïf~m…u9¿s‚3®033Ìçó$°n¸O|âafØk¯½ðæ7¿~ðƒqþùçc>Ÿß¿×°šîªÅ@}©…köj,Žç¦ùp,2¦3Æ_â4WúhpYžwî¾Cöyroú@¿ùÏ<²Q>:WüfÈ^áÆž) pƒ– yi\çdr) ]™‚*˜4µ4¯õœ¿ÕÔ‡šTPRmïûï¿?ýèGãŠ+®À 'œ¿îu¯ÃvÛm‡sÏ=¥¬_¿{íµÞûÞ÷â˜c޹+Ÿ=<\x‘4Ät³Úé²@fÁm‹ÔbÀ€ßwÕâ[EŸA³B«Ù—kÕ˜âv>’j6F¼&kp½FN=-qy” ÒÉò:•Bšfü®Ä“3¬$ÄÉ2K°N?p¿è|zM†zwçœsŽ>úèŒè¶ß~{<ëYÏÂ…^x·900€38án§Q°†¶%.Cµ`æ‘™Oè˜Ç Q™GDX¼ÀªE-Ô¤6ŽJò ±A#b:¡N“ޱ ÈÍ{e4t 7Â:ztÙ'q‹õ;sËþ:}j¡…Ï8Åý»Ïqµ*êm᪫®ÂöÛo¿ðØn»í†ë®»îns`` ²:-:P ’ÚèÜ?h£en›‡-ñ@G— göë2Ó¬élÔ½Fïè€Ò‡ƒ€¦¤GÒÅV$ºš I0-Ñ^Zór4[F—¦š_E•¡]ºˆm³Çï&¶ß~{\yå• ­_¿»îºëÝ>æÀÀÀm@ì¢n ³.4Q„³F\¡È«&e%ÉÑ—é­v®¶´¸Ë6Í›E~)a#T]’Ј-M*ÛA+,Vw¼Ø ³ëpqª™G/ŠP Øÿⱆ},€\Fâü3:u6ZíuØÜq‡Øj«­ðï|gá±<§œr 6mڸ馛ðÁ~‡rȪŽ900pÛÈÚ{ü@¡Imõx–šÄ ÕZ½n]v–vi1ÍPi‡¾˜ÁÑòÃÙfÖg¬òLnðZPÚ¬RI~>¶ÂÉ‚P) <»—A ¤ aÅÉÝ'`³”Òû$›¤ÊÊ­ØTcÙÌPö6Xnüãq饗âyÏ{þöoÿðªW½ ëׯÇïüÎïàøãÇ~ûí‡8‡~ø*:00p[è[2Ô6ö®oþE;¬ƒç&?EcVrì„hE¶Èè ¨ìƨQÆ*Xlõʨ&çk_Æ‹‹Ú™Á0KVôÚ|Ú’í(™ÿÖˆp0¥ŠÓxcn@@§ê?”}«nÊØêjpkÖ¬Á%—\‚‹.º¿ñ¿xàˆË.» ŸøÄ'pÍ5×àï|'ûØÇ®êxw€CÔཪNj{tU[\ZÉË•‹vA– ßB[í'ÑåÔÇŸZmŸ\e•s¬ñóÜ2O¦Ôà¡\ÒV)Å×d+$XŒ1´ôši§/^š*»•ç¿=Q è0-!uduxøÃއ?üá m³Í68âˆ#V}Œ;Ge[†qb V;Ÿ6•½ÔuÑ8 o¶ÉªDlÑ›\zÚ”D@X»>¸6R ˆÉd—DÖmÚ…Qp3}¼jåÝ› \ Þ¥˜ ݺ[ìoH²2\\¬y×’?Ó¡s```© ¡z—½il˜r#s.£aPd¤¸h™hÁLÚ+“”àÐõ^0tXE–‘[»ÆyEˆÑ{Vá6Åj@/˜uê…1$4Ѱòh‚ŸÁaVèëFåƒéf]²AášÜ}µD0êäX¡²d%iÞ}u``ৃ¨KïÙQ¡X§÷ƒ y>º©¤Ù,ÉDƒ9rÿ‹3N·ÞÒxdë‰b¾˜ ›Ï¼Ïã‚zßs •ùr#=¬µe½Rd(MD¤äºû°>i‘'Ò_½x'ÃÏ¥B¹õ“¥2¨µˆì"[TZ³w‚â²=È­ƒBÙ\ò†q¬ÓT¡+yÐXÞÅ:¹kîAå’”rÝ<(“Q— çRMÓ¨šm ieý..wBR&£?Ô‚©{·yôÊT…«KCDnRP#ôËÉ(3ÓÞRõͪ["¼âTʪ61 o9æ„s‰G˜tD©mÖõÝZÚuþÅ.Ñ) °PA ÑÏV­Í”¶A|äEjÚWäâ9co\Ì®*khÒ<œ=mpÜÀÀÒ!§Ðgn˜™©Û#[AôÞt ·P²ô’NK<€jyŽ\} –ó2ës­ T­Í"‚°? ›áBñ M&tªI(®q…Ð`­°ôÖFXnÝcË}H¶ªWªð8*pˇÖ(n³$ -ŸÉ"SÏ—;5јßFA^<Ï´LR2yH&SvW8wգܯÌ’xH—^K(˜!—FX”7Q¸Ò`FgÏâR Ý®{iäÆ÷6Ä1ñƒ‹Ÿ–²w¨]¤}w¡ Nå´xã—âi“w‹Â2’#‘¸UÔ"?¹ ‰˜…‰©Ò¦Û“+TR£!Z¥ƒ®úI@™VûpZ¤Å{€äaæÎ"(],*HiTVÛž‡hç+"JŽ™´'vDpˇ¬§e9˸3Ag)­P$ÈHÑ%M°¼vç‹‹k¼6ñ@§ JûäI©?æÝ >ÖˆÌÌ<ã<©“ˆŠµ“(uµôošAéf_½ 1Xá&¸±ÚQùÌ:öF˜Þy»ÅåA­5SÉNª„ªýO´$¦[šl˜Þ«Å3–µ<é‘yV™ã¢ï¿eø¥²Wª¸1';³ ‰,69ïò[­ìŒr°#<›Üä¾9Á9(¯1ŒÅž¶Šf·Ù\‹k½w```© šG’ä2`ÊbzŒÎÇ&û.dÝ?æàKÌ™f3pûÞ¥ŒC›A9 i‰^! Âs¦ÀYÿêu å \»t¯Ìzš&•Q³Z-²RmÑä­& F_ü¹ B– štêo$çä ËI½Š!M¶˜ÌÚ¸9¿ê5¹³µ•ˆÜ€&*IŠàjÖµÙkž„CQ ªËØuaŒ¡L–H¥åÅê“3ÇäZm½ÕŒ)gœyqÑ÷Cöìe¾p6ôµ|v```™Ù‹iQ*Ñ'£ &+pŸCÛ[2Êaq.¾âMI­ÖfPÍJäóÊ~Ù6ÞmœÆâáCdíe> 4A&t¼‰Ij2* ¹]K彉wî¨ÕÑO‘.¶‡04­¥S]©°hY4ÚqÏü} ܃ˆï1ÛÃlB, šÁ,ZÇÒtÒ+úåñ0'*ý&¹Ô(o9%ÇB9IÅ”Oïéãg™*ZFpAnY“kRFåß4&n°ñ §*"¡AïÏZ\JZØzÝ”†ªXhòYqdOvæCdX>„õƒšU†#ˆó«\XG×Ð= ž¸˜Gµž¯Ù+G5T†–šyGsJôlKiãZ†Ð8‹ùbQM Õ2ƒ4Vÿ¥pûÚáh©) Cºos#‰cdšÀüpL#_ÁüưպË7 ÑïªTUÏe“( _­ùSÖìÄ\-*g f@HR 4ÓðœK>“ó~fh9µ‘Œb5Oè€,†Õ†jx7b‘:G›Jð.Ë28-̓X6‘a``a]«‡k”‚BÌzËäT9ýžõ÷x„KGélÚÈG&ñ"ÈÍÍ0cFX3VR¡Ž #˹ќH Û’N0«€& "^cmŒ¼£Y1Eg…7ï\N£¡~Lç9CZi%Ȉڬ)¸uÜÀÀòÁÄÄ÷SnÝi•æ5kè­_Ží!Îh¡|SFV®¸G:]ˆ©I3(-šË ‘Á˜0‡Íîz;;£ zÍh.žÉwÖ†îÕ¿~! U•b*TmŸO:€æu¨06è1À_ß200°$ˆ]¥¬½«Ì•$Óš}ƒ+dF©†Þè+¥´}Z8£T±ÏÀ&>+5² ½È": ÅOwÓÆ*±V³HŠ )˜¬æ^õ¥(qt§ àF·6ŠÑú]´ˆF¡)Õ‘Çã2~«%æÖã ,OA¢A“裂%V@W ‹dæjð-,mµ³d¦´ŽØU#Ô+D”ÞñƒdUÙ‚˜'æ˜}Öɺ%9ArË®/„”cYÝvœœ[‘¦)0­Q׃åpláºÂBoâ–ªÁ£•š¢ f-55`B›VJ¢bäα+J ­ö’œSè fbË×ùB‰,Ú?h¿f±Ué.‘GòB{;#¦Óù*ÕËZ&NuµóqŠ™Ê×wʬΣ›aÁ0 6 ƒÞ–ROÍ(–Q†2w$íÓ²f¦xÈœ\ám‘ Zz›Û³(L´m\}]_û2ÕŒk˜ƒ*EîRlÚ™LØYèæaE¨µð¥ÚyªÁ«ì¬ë ”±ÙæaßdmBöiõ“Ÿü$þçþO}êSÞ—20ðS…¶ë•â±öS"A®:bIµT‰Ÿ¦ŒÖãY·CöW¼Rl îPW‡»£°%Dçó®æfVr²`¤hÝAj†•z‘Ü<âq:ð*@ôîF˜O0DÇ Ç´<ŽZ¹…+Ž+ƒÖ)ò_^BÙ¦®übà‚ .À‡?üáU¿þä“OÆg?ûÙŸâ ütíµ=fÙRæÉ ‘[I¬WJÔÒ¤sÀY¯³’‹Y(la †ê%6Ø“J+ '+‚âôü5çFê¼|ç;Ò# M…ª£ÜÉ`°ªLnPäs”ÒèOÝl–óà³p¦Ó–.Þy×#ø¿gžy&¾ô¥/ý¼/c`àn 3»õPT‹÷bñû]9ãTsÆ=²¾ö»ÈZ¸Â@µŒõ·NÜ Å¶?–iÀbcÖlT4 ¤¨{I,ÝC̵‰>TÓ™Ó,˜±bzÞ¢>sT«-dÚª–â«sñŠ«\ɦÿ•’æ IDAT¿øoĪ>îw¿ûݸá†ðÉO~oyË[pÞyçm&AÖ®]‹“N: §Ÿ~:n¸á†||Ó¦M8ùä“qË-·àŒ3ÎÀI'„Ë.»lá½o~ó›ñ­o}+¿öÚkñÚ×¾öv¯é–[nÁG?úQ¼éMo»ßýn\{íµùÜ?þã?âÛßþ6>ö±á•¯|%¾ò•¯äs?þñqÖYgá­o}+Ö®]»ªûøY™ê©àÔ­À&`–¡`- ³ÈÜZd&BO³åLƒô¹pTu;†FÇÊ÷2šŒšœú7eÂJNïëbÀƒÄo%åWu «UMìL9„¡cDj°SV)4Ï·Ò‘—F9n¢»}‡Îqç8õÔS±÷Þ{ão|#¾úկ⨣ŽÂ3ŸùÌ…×<ÿùÏÇ3ŸùL|ík_Ãë_ÿzì½÷ÞIX7nÄ ^ðì³Ï>8çœsð¹Ï}|ä#ñ®w½+ßÿ¦7½ ßüæ7ó÷k®¹¯yÍkn÷šžþô§ãmo{¾öµ¯á¤“Nƒô \~ùå€RJþ9ŸÏó³¸öÚk±fÍœqÆøö·¿Ã?üÏ10ðóÁbKYß³ÚÊj –dÆÁ%S ŠäF”ÊeøH¤”»`†pW -4ËŒPgŸßì0/á¼VPÔÕ²P‹›’œè¼+gÊîæÜ^*à%]6#…¶ëŠzcí‹]Ï]«ŠÉÓ3šëç;ÃQG…W¾ò•€—¼ä%xÈC‚£>}ìcqþùçãœsÎÁºuë°í¶ÛbeeOxÂð²—½ §vZãío;÷¸ÇÞ÷¾÷á…/|!žñŒgà>÷¹Ïª¯C8û쳓È`Íš5xÏ{Þƒ7¼á xÆ3ž·¿ýíxò“ŸŒcŽ9&_s '`Ÿ}öÁ?øAÀ±Ç‹‡>ô¡8î¸ãpßûÞ÷._ÃÀÀOšIp~Ï#šŠ©[ÂàÕò{­:\³ag†º„Ifnà°=‰O1WÆ—8žÏÂÈε¸žà¯(“¯`Ó´ëFL¾Òùž#™s^ãE=b_ .´æ%’ém¶ú²Ç¯ù<¥Bg;‡&X¯t9´.½Õ`—]vÉŸ÷Øc|ðÁøÌg>8çœspÄG`Ûm·ûšÏñ¢½^xáí㨣ŽB­_üâW} =DnW^y%.¹äì¾ûîøÎw¾s‡ïùä'?‰ûÞ÷¾øÀ>€|à¸ä’K°Å[àŠ+®¸[×00ðÓ@¤¢Yú—…ZGFÑBV³ØDæCöÉyÇw@Z¥EiÌRThˆ€Hݦ|SÅŠWܲr nÚðßšE5Lu#"ȜǸCÑ3bDðâØà!» )(óéºUËWÄ&7Wû^÷_€!-ò¹»ÁmŽwÞßÿþ÷W]uó˜Ç,<¿Ûn»á?ø¦iºÍ÷Ïf3ì¸ãŽyŒ»Š /¼ÇwvÞygì¹çžøîw¿‹wÞùßó£ý7Üp®¼òÊ|ìÅ/~1vÚi§»u ? L¶—Y´{x|·+ƒ¡Èœ±ÈT*ZµPå¯|] Œr<ÒZ*ƒö¸Àt&Çä6®lÂÆ• X©á>anÞLIV|Ž 3›3Bl,=Ð/lÕu›#‰©e⟛씵;’¾º´óŸ› ÿü$]"×]wýèG¶ß~ûÒ€õë×cçwÆl6»w‡r¼~ýzüú¯ÿz\©nºé¦UŸÿ™Ï|&Þö¶·áiO{àå/ùFb»îº+öÞ{o¼øÅ/^õy~æ°XË´ »wõ0’C¤¦ÀÂ2ÄsÆHŽî».¦kTUüC•¯ê›êFl\Ù€Ó&Lur„ëB#¬b² +¶ }#6M›0ù ª­ãUJ7C8h•8…”ÈËiýnî‰{gö*¬À0ks&U段ùž{œ~÷»ßÅ¿þë¿â‰O|"àÀÄé§ŸŽk®¹&_ê©§âCY8Æ9眓?øÃÆ6Ûlƒ½öÚ @D„\pA>ã7.¼×̰²²XYYÁ÷¿ÿ}lµÕVùüu×]·ðú­¶ÚêV)ëSŸúTœrÊ)øïÿþï»pç?c(Rcg„yÏ ‰¼«¯÷‚¢µÎ ½ÎÍ¿1¾(d­M|`Spó¦[ðã 7á–M?ÆJÝ!¼¼yŒFóåv(g8Õ sö±Iõ@ÚoCVÍ~ÞGö»8šK§™£Q9ŸVÍšdu"*€¨_­Y³¿û»¿‹~ô£xá _ˆßþíßyä‘8ãŒ3°fÍvØaøêW¿Šë¯¿~°à•¯|%>õ©OáxÎ>ûl¼ÿýïÇ[lxÁ ^€g?ûٸ馛`føÔ§>µðÞG=êQxÞóž‡W½êUø«¿ú+zè¡xö³ŸÃ; ßúÖ·ðŸÿùŸ8ðÀóõOzÒ“ðêW¿7ß|3ó˜ÇàÐCÅK^ò\tÑEØwß}ñô§?6lÀºuëpÞyç­þƒø)#œ‚¸:0…$Qµ2“ˆÍ`Ý=@5ê2•­¦=ɪ¼SlL®S68aô‚¯lÄ´²æ+p«ádT¬‘ï#w9Úá`ÜÂ+zª3›af÷Â[ ¨ËØ{‚*ÙûbÚÑFJC¨¨pT5Bªû˜0£xÄ#ÿRÜqþùçcݺuØ}÷Ýñ¤'= [n¹%ছnÂÖ[oµk×â‹_ü"Ü|0vß}÷…c|îsŸÃg>óì¸ãŽ8ì°Ãðö·¿=ÓIwÇ¿üË¿àÊ+¯Ä³žõ,Ìçsœy晸æšk°÷Þ{c÷ÝwÇe—]†Ã?ûî»ï]ÿ‹"¶Øb ¼â¯ÀvÛmw·10ðËïn’P?WÎ8®´¸¦ Ù#ZMQ[¥¹nõMذ²·lÚ”ÖI0Ï=Ê=¹æ.L0nâ‹T×aüú1 Ýšë®<Þ"'ærÞ@©Î­õ1gš¡ `Ž9¬Ì0·9¶¨sLV ûQ2ïmª‰(fð*I8ž/6‘ë n®ßp5.½ºRýÿí½[Ì®gU6zûyÛ¢¡þTܶ =€èj µj E$E\¢AÁ\¨ì<û…Äü¬“•¿ÄÍZJi¬ TŠ–‰¨U~T"AÛ9¿ï¹Ç:×5Æxf…ÎR/úÜ3sÎï{ßgso¯±co{ÛÛW¾ýoþ<à>ß83 ɘŠÈñ6[•½Éš 蜌øÁ„ãxN…žíG˜ÎÜ’æ4D†1ÒpL;h¹eyAWìCÀêÁg‡ƒ,›„"“ÍÀÃKÙ”À"÷ÒdbEˆ­Çp;°È g&æTiƒ Æÿ §t‘¿2¸àþï;áîmo{û 6Wiƒt\,j0D1ûQ‡+cxs/c:r˜ãh®8}|gŽOc+V›€+]ž4>z€?B dšrêUÒðÀ¢Tá /S‚6Sn%îY‰>½\˜„.4ekJÚ«;XlÁ‚H„—Þ# ‡qZ—e©å¤UnNI±¿{ÛÛÞNFsúÃc4›„Vº| Ä…Ô䧨ºúÄ1íHQÀW¤ 0=8ò.‰— ß'¼ v©+ŒW5Ê¡¤œôØ=æ‚K…¡ ŸÃI×öRØE±‰uã<[p°ó‚âFG?z>à>‘«å8´¢®»‘ao{;q-·ðŸ0(6µùÖ*hJà7=üÙΟÁ™õÌ ¯Š›Ã>Úý'|Ãæ¨D/{Sl—'Øb¡Œ½–lcÙhùà&P)Žf0¤¡^BN`ÓWÆy8”¥–„¡ÝhÃ2?£”‘{ÛÛÞNL †DÜS¤ËPLièÝʸ9èÆ1á8ö#œYOãô™;#ƒ‘Ïr1ôþŒ"5„_îXe’äÇRd…ÅTÎ(eÌ l:˜2ú(s¯{9è*ªÁ7¯@•3ÉÀôE‘kHZpƒ»;^ÃÒ1–‹-añ €MXZG¦Kæ.'–½ímo'¯žY“À,r´ÍKÓ4MŽÀvæè¬ë=5)•"×ï€ ƒÏ,–@XLaE¡`t+EŒ¦›ÈÚbƃŸ•®Ä(šz¦DQô‚UÌÙ¤´ìQöËù³¥îubbÅ\¦-8o9†%,+^oC j2nœ››ÈÞö¶·/_‹Ê#Ï)ç~ +Ò"œüôñiÜqô¯˜8éÓ"VdÚp>¨00µpƨ4¹ÃnU‡Ðæ0ufJåVÌÌ;±d,Y™lǦC(Ðs/«(o›>±âÃ8ÏXë:Ü%æÞö¶·“Óäí@$™˜££3¸ãèNœ^yüëkd"Ȱ IÓ"#‚‰þ³é[Zù¬”wVüiÚ :Ò$ÊÄ G‰Ð*Õ®!½Ò_2‡Þ:`âýdZЋÅÊÊBš¿òÙNvb™ç†2yðÞö¶·“ØBµ:pzáôÑ8:º‘ÊQÖÑ8'6‹Øf,º'Œ´iÞT\žã*2ݯQ0Âl:ÿ 3Td5AÌ f#EË)™H«¼âQ"K©sMƒ…›r¦—/Ý Od ¼éH*àX±ú _W,6qÀŰ·½ÄЉ3~„;ŽÂ§mâ¨ÔW^@“I.aÀÙ" @º”8õî’|«ªK È¤žOÑì’ð†:”òr|w˜VªBƒcJg˜—NÆ“¶j_™ýC5 z*!\²‹†MZ¨+—¾F›«cÚ‚cüûaö¶·½}åÚ±ãŽ3wàÎygÖ(OPIs+.ò“0VNéÞˆåªËëZ~ФJeîâä˜iÒU†¦ªú)9GêàJêäf 9elˆ6iÕŒº…Š:˜u]¦1‘¾M–ˆ&Cc¡nÆE2B‹;}âG÷|ö÷¶·½}IÛé£;1ç¿aå9Îòž.—îa©’rê×@KE÷òº@ Hð4DÁ,ÉÒ¼ÆYtå\ _Òâ·Ï‚QzhâTK*,§t˜C¡\’£c,ÍBK ÌJdUÍ ƒƒšs¸½íí¤µ3ó lYuOHѳb(CóÓ@à †(ä²Ìó2åS7k õmY´F`IY+ ’OœŒ ‹ÜMf£¡'dM²´ŒKÎ7®Îl2œq|be¡µæ”Œê kÙXYYAtt¿·½íí$µ‰ ³µ8§Ì¦qW« ;p2À°^ÌAò9c™èºÑ=8D£;‡™aÁ}[Ø'$am:Sú°aÍED*:¯¾zÒë!Îê™_Íœ+§?‹ šŠ}G8ʸàΘµ‘z8MŽ)ü¼·½ííKÓº¦lš§kW|\œ”ôbY'+ÐYœª¢”lCkÜU€Æåņ0(¨©*=Ä¿+…Рàà˜ +P>”v€Â(Œ>r²›¢Æ £H 0m¦hë­Ü–%”"0XP ÚôÜV¢+ö¶·½¬@"!pf™}—q¡LLipø4DÔ‚œÐd=Eéì[]…´P6Ø™š‰p"ØlªµÂðlfŠ¥AMÅúéaƒ7¼%Z’¥ÃdQ‘å¤ÑÎ~¤ðŽ¢auÅÝÞþö·ã oxýxÂÞö¶·¯9F(ø7©ÉŪ4V~¦ˆrñ´ º É¥·k ØÞÞÿfÁSÙ*(Au³çP—Ò]v@¥EW'&&…SÖ ´êôb]a˜!j·#äm7¬lî}è ߸s¶Ë[Þ‚ÿù?·åo¸á¼þõ¯?§û÷¶·½{Ëw¹eøÀ¤*j° æxMþŒ` µ¨ß 5ÖÀꎵƒZ2:eœ£ô7¤÷s6)ËgðŽ• <»Hœ‘ ’r‰ÍN#*ï6’dÍÔèM ,DÔ‘aH?BŒµR¹¥¶^C¼»öÇüÇ{õ÷½ííËÕ,hL+qV~)*2lÓY½= Ñð¢f²cdI‰#ƒÏ3“ÉóÆM(8)‰ªŒé!:BGº”‹Ć•]²“dÿÊ ÁTJ5fÔ“€™JÅIÙY¥ÂÌÃ9‹Eƒ HëÖÕsƒ·w¿ûݸùæ›ñÉO~¯xÅ+p饗â)OyJ~Ë-·àæ›oÆýîw?<ëYÏÂ…^¸¹ÿÆoÄ­·ÞЇ=ìa¸æšk0ÆnØØÛÞ¾`óȺí°ÈÄ8ó`ŒF&¿¤ŸnãÈ>,qbH7Ï´iÓŢä8™)¸1@^ŽÌ“Ûqjÿm.é‡7ò!¥x‹ŽŒ°bNiòrB Ô”rP6º‚¶øÜšè‹ö(•”–ÐÒ'% U6×R[~á–\ ‡Ã Þô¦7á/x>úÑâ×ý×qÙe—áŽ;îÌ9qíµ×â¥/})N:…W¾ò•¸êª«* wo{ÛÛçiŒ2pÃÁfBUéå÷æèaœÝ´ÿCU¹\¥QI¶æ» žªô ½Wݪ¸„.¹gØH?avh ÑŒ1²tZ¾$2inUŠ¥Dì Ånq/W“éÀ¢ìÀ©d¨¾ÉZû…ÛcûX|Ï÷|>úÑâ~á6ß]~ùåxë[ß 3ÿü˿ࢋ.ÂüÁà‡ø‡ñº×½ög†Ûn» c œ9sßú­ßŠ·¾õ­¸úê«ïþÅ{ÛÛÕæ¥¸ nŠ,‹âб©Ä~k.a3 8+2 .H£Ó°¡`ºžUz¶øÜ *(¦‚g3R 7`2ãkÖD°2¨ÜW Ê€)OæA#A7 Èl ¸ €1d‹Ñ …rùlá\Ó åtwï9©‹.º(ïw¿ûáòË/Çm·Ý ¬¬xÄ#pÝu×åõ|àñ‘|d¸½íí 4§ôWeA›'†Óç"ë-Ëä óeðb3´UÉŸ¥‘˜bÝShõcÅmïi‘ìÃ!r©Wð{ë:†·Î0F,+t yÉöE¢»²_ÐÞ˧ñe÷ueé´dmSž†ÄT"µŸ«‰áÜÛ…^˜"è§>õ)œ>}:žúԧ⻿û»ÿƒßº·½ýçj6X^Àšó>¹¬ÀЦªBèЊ%Ù¬Ê6|dÙÝëVø#I0ì+mÈg 0`äÀ®—Õ¼ƒªF-ç»x˜ªÞˆ§ùÐt2‡'<¶rNgDò’@áò{ÎG¡9ô}‰Ú%—\‚¿ýÛ¿ÅË^ö²/á[ö¶·ÿ„Ínkf’1M)mÂLÑædŸ,âÙä3+å”Ô\Î{#003QDTM8‘2D8(@£ ¸µcóð­K®%+i¨,¿’uÓ‚’]”•”wû¤¥¥ÞyääM'N-‡–V™râ»»vŸûÜûØÇîÑ=ãÏÀõ×_[n¹åÝ··½ýWo¯rŸžæÉŒ\R²[Ř–Mqî =ÕR@M=ž~Ïä½ùVéû2æ”q°ªÒ'qÐÑŠfuyXƒ5=IJ“FÅ¢ ,ØLÇ`v‘ mìì S^s&A‚¨)¨>txHG½Þ“sÓÃ=éIOÂ{ßû^<ÿùÏÇk^óšsºç Ox~ú§üãñ¢½¿ôK¿„Ç<æ1¸ýöÛÏéþ½íí¿jëú¶®'KˆJéS~­úvn~ °ëª©pþ/F‰©ùP•K(ݬ$GKîÑp ÇJÃ@iÑ”–DöŠ ‚6¶š YÝÆªD„sy¾p¦b°†çæÀŒ÷Ëo`­Ú¥œ»ÛvÙe—á=ïyÞñŽwàâ‹/ ÷¹Ï}nsÝsžó<ô¡Íß_ýêWã¹Ï}.Þóž÷`ΉW½êUøº¯ûºszçÞöö_µ}ĦÍM ½\DŒDÑPX@]¦FsO)09@£Zʲ5X/©ï?&ÅÖAÕV¹/r þž¿ A“ÏJ75Œ3󡆈ÖtõY0殓IÄá“ÅX]`<1ˆÊNŽaImN|&K-bŸ=ýO¸õã{<éÞöv’ÚŸœÿ߀Å)JúZéÏÖôôôo%¹†¸˜ˆá“e5\?„MÀVÅ5á´AÊ*.®…k™á~(Mv†U6NE¤ÀX*PªO˜É¡@ V€'ŽÌëû4"(A§,&@›ž½ímo'±…S„m O‰š„OÚdòËÒË9ÕXÃÈÐCi*礸9¥SŠdf„huÆLn$+ñxvÉ­u!º#YÖè„î ®·¦‰üÍuMÜ‘¸gí~˜ iÈ>Ä%ÊÅ¿{ÛÛÞNT3æxóÉÃmÝ€@Èrƒa)k$*Ö)½>ª¨Ÿ $†Æ…  K‘Je •8†ã°áÂÔÇü¤^˜ dåóVºDËÂX™ô$»ZfŒ¼r?1S֒ʬ;qÎvÔ½ímo_¶fo¸yêÐBé_QMÆ6ŒâÖÀ#”YEiŒ¸BýšEÊÆ|™‡´{¸eꩇØÌÀD Ö1ÐãÊ& áÒ!LÖ™iOÈN(±™Eqiݯ]™–;—··½ííÄ4å\«xÆ‘&€Õ•n+qG>·,Cñ³$ɪ‘w½€|^ïªB‰ÕW¸-ÉÛ(¢Ê.ànðáY$F!ï‘€sR¾´l(˜6:#é³ðsÒén)ÑÕz"^5ÃÒ2ÈÉMêáŒJ¹ŠeÝÛÞöv’šÀgÚVìÔß‚¨™ -…á¡'ùˆ60MwÖS+*¤³Ôdƒ>uéµc\¢¦Òû7Rl-nNÆ4“‰@v‚ 0£nÔǹbP—(h¬€ÚÂ:Â{Ù,Íueo{ÛÛÉjŠP’¤Ö<1fÞšœ”d΢p´QÜ…ÑÊJÿü€µ¿2êŸÆ G¿6/?¸šž½ímo'¥eí”n­~²§®¿@/ Ž©ÂcÓZLîA±We ”¡a#VçppVepê½ä*bódÞʪéÈä´kšE €°ŽRNŒu¦Yq”ØË'o?)õvNno{;‘Íf¨°¬Î®¹cbApX2F0³¡Pª¬š›ò¡\ÓÄH©°@•²£è>Cÿ–X׆G WŠ¡nPú’,1¼…O*¯6[z¹ð[‘B&(Jál  –@l£î[ÙMv?¸½ííÄ5[eF€a…MævtàW`-^=8=0²@Õ èYz9 -šëÖ4†k40G8+`˜8XÊÉ´@¨ïpzè=šÒÄ¥¬,Ù9]M¤ö³Œ{ÈïÀ}´ÎSÿGq¸ÃœR!×Dìmo{;QàRçÙ¨_›uº›ÇEp/#uí]2³,D%§å†³z¡oÞfc`;ñ IDATõ|lÓ£ƒ"ðA3Ò'ESO\ÉrtÌE{…Ò,…Sp³d ë=ô[Ô`nºu¬0,û²·½íí$6cé>@¶ÈJ§Vê¥ø²ŠÕËPP¹"{Ìifj¡Ë–*¿xw3ÝEŠ{“{I(ˆh "ð¨&¡4Na$èéMÄvML› 8N%aˆ¢‘ñ×dV5Ýi˜4áv/ç%Ñ3þ‹z†î3Aoø6XCNÅw1Hœc[ׯxÅ+ð©O}ꋺÿÞ´›nº oxÃ^ loÿ™[3<Bm¼œ÷Òω©ÙrfzZ}Ukn"#Ÿ%¿·ÔÛ7]}ü¥™† Ã00ÖK,˜Õ+=Žrozw”Ix dh3 Ê…ItíaWäݳëõÊæ¿âØ ÿ+£ãå/9>ùÉO~Q÷ß›vã7âõ¯ý—ý½{ÛÛ—«¹ªÜ(;À|Laz@Š•ý¯š¤µ¦ p«è*Çl¤Q¡tu²ÊÆg‡aÙ pÁ8Š¿Œâ̘…ÓS)¨®èMÞö°€T¹AUÙV"®¥AbFˆ×HkEB¦ž¾«àö¶·“׺·Äô ÃÂp-I@¬tÆXü9ó—;,õõħ±Áß%#¨˜)©ÂÌ,ŠÍ2nbÃA<ã·&ÆT}A9Þøœ°&Ø7ÃR¿äºâCr…S±d-ÎÕºÏÒ!8ãÑL2ud ¾§¸S§Námo{>ûÙÏâ OxÂæ»·¿ýí¸ï}ï‹>ð¸þúëñ¨G= W\qàŸÿùŸqà 7àŸþéŸðØÇ>—]vÙæ¾=èA€w¾ó¸è¢‹ð´§= ÷½ï}7Ͽ馛ðçþç¸ä’Kp|||—¾}¾w¼ë]ïÂ_üÅ_à…/|a^û¦7½ wÜqžýìgçg¿õ[¿…‹/¾—]v^ûÚ×âùÏ>ÞøÆ7âÔ©SxÜã‡Ç<æ1÷`¦ö¶·{׺ÿ½5?sxcX¨$àP¶ÜÔ÷[2P:™R©EAìÆ\73ô˽UNv9·òŒ qMƒÞÇnŽ9&æ˜LJ9©\ üMY’¦YPÓ%$¼<‚«›ácÃ7^sÇÁúŒ©°R9§§ò9Nø{Þó<êQÂßøF¼ï}ïÕW^¹ùþ†nÀ‹_üb\y啸馛ðÿð€÷¿ÿýxô£ßû½ßÃûÞ÷>\qÅxÙË^¶¹ïiO{~äG~ùÈGðÊW¾yÌcðéO:¯yîsŸ‹ÿñÇ_ýÕ_áW~åWðêW¿zóî/ôŽ9'~ögŸýìgóú½èEø‰Ÿø åg/yÉK0çÄ™3gðâ¿~ô£qýõ×ãÖ[oÅW\ßüÍß<Ç™ÚÛÞî}sÏ4Î Íš)¾†Ø)Œ–!®¬TÒã Ç:~2MÖá Ø9'M.h´„Aa¨òÑn8@8ëMYç]ò’ƒòbÕž ‹3›˜©_-$º]ƒß B_7š…7J@ØYWß]{á _ˆ—¼ä%øùŸÿyÀ>ð<êQÚ\ó™Ï|ïÿûqÑEåg?õS?…Ÿù™ŸÉû~ôGO|âñìg?ßþíßxøÃŽ·¿ýíX–ÿöoÿ†K/½¯yÍkð²—½ ozÓ›ðŽw¼þð‡qÿûßîŽg=ëY›÷~¡w<îqÃýîw?¼ë]ïÂüÀà/ÿò/ñU_õUX×ï~÷»ñøÇ?þð‡qçwâòË/ÇwÞ øßù\z饀oø†oÀ«^õ*<ÿùÏ¿3¶·½}ñ­LˆŒ2u%Æ`ñ‰|÷×ý×ß«w\sÍ5€{ÚÓž†g<ã p7Þx#®¾úêÏûŽ /¼Î×{ÛÛ—§e*$Tê"O¹KìN|¯ÂñC€GñÓnTá  þ€•5d²èŒ¹añ‘"p)<Õt0èHüe{6àc–?š B–ï‹4H©…S DÜL—ÁjP¡¦wÎd3JB­ée¿P{Ѓ„Ó§OãöÛo¿G‹¤ûγÛo¿—\rÉç½ïãÿ8¾ù›¿9Ÿñ…¸§syÇ“Ÿüd|èC©S§ð|—_~9®¸â œ:u ó7ƒ?ú£?ÂUW]uƶ·½})[èÚtä¶6¬Š·KðŠ’¡kãœ`f0Y¨ÊÜáÓgmTáŽmÜy™Š­Ä]C`‡Œ ‹E :^î#des2&Çp_1=ào¨$Ø9ˆ¨yÈCðð‡?¯zÕ«ò³üÇ<§û¾å[¾¿ök¿–Ÿ}øÃÆûÞ÷><ñ‰OÌÏÞýîw§?ÝÑÑ®»î:<å)O\y啸íßþíÍûúÏçòŽ /¼ßû½ß‹_þå_Æ•W^‰eYp8ðÔ§>¯|å+ñÈG>r#Zïmo_éNùñÇ$ÑåÉN‡5@ÆGódvdU5æ“`ˆQ~lò 0ŒFªÃácbÚŠia ¢Y ä).rFÑw *$VïŽ-Œ4FèsfjJqv¦Å ÔLf EžêMt#IËK½3 w7Ùcà7~ã7ðÌg>üàqñÅãæ›oÆ\p·÷½öµ¯Åµ×^‹}èCxèCŠßÿýßǯþê¯âÁ~p^wûí·ã;¾ã;põÕWãOÿôOñ€<?öc? ,¨¯{ÝëpÙe—áéO:þú¯ÿ·Þz+¾ïû¾ï½ãšk®Á‹_üb¼îu¯ËÏžþô§ã‡~è‡ðò—¿ünç`o{ûr7¹¥NÝÌÞ+Œ“5Ò /ý`^¹@ú#BÜÔ};Ã≉ù³W”Dæ§·ç†Ã E±fÓ3ÍøàCJ J»GK©}Ž, “<0}HèêFÞ#Q8Tx¼ÔçÅ̹2œœc»êª«pë­·âmo{Î?ÿ|¼üå/Ç›ßüf|í×~-àIOz>÷¹ÏÝå¾ïÿþïÇ?øAÜpà 8::‹^ô"|Û·}Ûæšk¯½Ï{ÞópË-·àꫯÆÕW_ ÿeYðÖ·¾o~ó›ñÑ~×^{-.¾øbÜzë­÷èÏ|æ3ñ‰O|b#Š>ùÉOÆK_úR<ç9ÏÉÏ46 ¾ñ¿¿ø‹¿x·½ý´&¡™"‡¶eà¨c"$qcé©QõùÄymj=$¾X½Ó…™y Ë`!W5`À¾÷Áÿ»†c³Ð·M©ù3ÃÍÌçtIÜ´LMîÔ§axdî…a™|y¢nY=ÚRp£ã0]ÿåô?á/nÿÊÅuþÜÏý>þñãºë®ûŠõao{;iíâÿvîsÞ×¥¹PYx=uörð—Îmï›"šò·j¬æò‘WZËØ[÷ŸÕŽ*`¬lŸØégDÀ‘Y6‰Ac2¥EPòáÃëœY@ iFVÜQ^vaÿ€ûÊ‚9å Ã:k"ö¶·½”&se0,Ê©êôñiüëÖÄSO|PÆßî?ëYØŠâ¨Ì:">2j3Ãep’­ëç×Y¥ÁË=Äèçâ™ëâèHù5ÔŽ&]\/Ö:肳”PN%%ÍÆÊ½>¼…mímo{;Q­¸.e󭤹!f#˜X•i8UWá™…¦ÖÔåU‚lÍTk!ů…8¬Ìáa7ÉL9Åœe§æ Ç ®”Ó©»•$+ dF÷ðõt0 p¡¯C!cg[Lí.Ÿ|ùÛçÓÝímoÿ•›ÉÍÎ:ï^ùØJ¯ø¡Ë] Ê4Žp1‰òqÇLÑTqíL§¦ðQÕ}±B+i¬<¤UƒfØ(C~…|”;ô™ëA¯rbU>¢”r"†:ãUãúè$'ƒ™K¸_ÉÖÝEö¶·½±éXZ±>æRGí*¢¬¾:ÿq½Î}øÂ)©%=/$éeiøŒÊÐÙOއċ@ÈCVÁ2ÂÊàJQÑ„†–ÖO9XÊÍl‘ŸÜD"F-= øU‚¥Àd_ r Ž ýáp–½·½ííD´A•/ª’ôÜ +k™*¨~ s»$X¹‡I¿/ç_qZ%’]RÚ6y2/R³¹0_ ºñIas[iâ]0ܳàªâU‘IJÂutiòZ0B!ÜLcTdÌÂÀàe_M…a¼ýK²6{ÛÛÞî]K·^›Í ãÌ ¤óëfX½)]Ül«„R©Q µƒaYk` åàˆ9Õ“J{‚$PЍLo‚¶Grl|kÏÅ`Á¤B/*X›­É}™#½™+HŸþnnX\üè$°ϨlÀ““'np¯ªµ·½Ì&£`Ši<´`zà¡’äÒLÙâRœTXC÷«Ãö¬¸'0”¯3þº„Öˆª¨¬&‡pгvÊ5Cr²ƒNw4æ €''éáâ~uAr·-%ä Ó°9°R›8ÝÒòš)—djÎ\S{ÛÛÞNN34›%µ £éÜZé–’ÉLFOÂ’c¢]ç©Â’š YÒ 3cé'×zxˆ²h  š‰×|„5£E0ˆL9ÚhÙšfG=Q}6–RVƒBíe!÷—ÿïú·½ííd¶Ý²ÔNÊ/yVP€ e eÁ)8à "²½Ca½GOùëlÜ!U¹²,©{ÔEE ½Ý<8«ú5)õºŒn`áÕ™0ÃÙÎ¥tÊÙ£àe 6É1NuVV‘YȽ·½ííDµÜ òUÑx3¬dz,¡‹Ì‡¨* ¾¶Ð$* Êö5&ÉåKÛô~™Eõd)+c7ç‹¶èé®2]ñÝDÇíxÌ„Ám£ö_"ÄNB@VXwfÿ†…žÏ‘ÌÎm`(‘_õÙÏüëвìmo{»·í3Ÿþ…3iФÞ7¨ˆLdüÏSA37œ”¼R©ÒâvK—±ÔZIDyu,6°˜a±ÈûÊ'*A¶˜Ž ÆWc±¯ýï×áÿ{ÛŸ| –lo{ÛÛ¹´·¿õ=xõÌ–q~09@ê¬Äy9}eÝÑÀœmåÀÏ•Ð6bD£¹c:##LIÑ—’Ba›Lâ¦Ün¦BñkIŸ,ùšïx¹¡JVI?¤ ³lʃŸfð½0 ÊP–Žˆf0êßzƾcH$î!ì‹ë­À²œ;Î|7½ù½X }é·bŒÝxo{ûr´ããÿãÕÿ7~ñÿø ¯gpÁy÷§¡¢I:8·ç¾å NÈêrè‡:ó‰<¼È pÒÏ¡YG…1&Çb+v’Ù öÝù‰ÆCmì„”Ã$U@älrW¡ˆÒÕÉ(z8¡¶žím>˜¾Ø•”™~I–\gºE;L¯gð¯GŸÂ°¹äëñÔºßóÄKñÐK¾÷½ßWßË%ÜÛÞöÖÛgÿå_qÛßü#nºáOð†ß½Û)L[qÁáXÆyh|TªÓ¤žrêÒÊ*Ú2e"[‰šñŒ¬Ý@&ªj/3äËFYJ}bÈ+ƒ´xXuצ÷·ï}ðOºj£Š? ¨š™žÜZg`3ÝBŒ¿P7NÍ1©éÈ‚ÊB27˜¡.òÄ`™aMYÍà ŽéÇø×3ŸÆô6ôÄeK-Ì`¾&j:GŽìÿ€´°êoR ÖuÔRºäU\Ç–H_º}®ô#Ÿ¿m–,ü@-jºôäSÚÞ¾1ã3KÅÛ¥E̤ÅPFü¾aõt©„³òÑYßkHžº…*óh>3Ã6®ÃqìÀêkfœ ßG‡Ùˆ¬Òép0²¯½ç9cažKÎ_‡IR‚Ôë¶¶&ëP U •±Û¥j™°YÙ+ B®7˜…¿ÓÐ~EìëT¦×{ä¹P’ÌÄÊ__ú¢f_ÜÛ*Ó YMÞý¨×Ý©¾K¼»aïÝIC@å+l,8ï¼ûcØa3ŽÔ}!8*c*E@Mó¬®WÏv-If$Š@˜Ï‘€µ§{KQëÒµ9œÆNFìP‘cê’+Ìë6½9á!8:Ó¤2ŰAE©íú~AJ¼˜^ J”7¹™†âbÅ"€ ž7;÷½àA8ž§q´~gæiL?Ó Áö¬úiµY{K,5D ÌÌw•d³ÝfÑIØsV.¶Æ{6 Ô–`:@¬ kŽ­|J¥œŠ7VÂýg(ýFrÅ¢’º;/ça&Õá"U\ó¬.k?ùhÆ%ö"JSíÙ=îT¾_tù6U§ à4nƒ1ÙÃØ³”y ÃK mó7O*”½¥Û•3Š&¯kNç€5¬ñœ×íôéú så-3ÀkEEìysxkîãl%íò"Jî©­ùü ‰a…wî\‡*˜±.}Îy®]}F󵩚ƒ”‘wŒãœ?¾ ¶×&ÉJT÷ÊÈ G%εº‰ x™D‰8ÜÏ_­ ¹³¡·›Ä&YR 0Š~0¡ˆåœ’+³ÀÄ:Öȇc(’AèßdbwŒ¡<êBhC½ šú¾ ?Ç5ùe-’8éuÊ2mbà0.ÀWÕv« ¬ždcëèíºÏ‡eºXùîÒÉÙ¼qñýÀV,1±9 T¢z|6ZŽ  ÝlâM+8“?+ñŸÜƒTQ”#ÒW!Ã匰œƒÑ¯ˆì=7PXÁ cd:*lFçuapM€(>u´>a¾Ä:"Ÿ:Û›—~•AÙÇÑ ÍnGÜŒt'wã§Sç€ûÌÀŠ‚ £¯xª˜ Uj•5KtlÇC€¥œ¦ùÎZâ‡àhæf—Ä¥:DA˜œÉar#8dÍ ˆ"_ƒãˆ©•sû(ÔÜg„ï[Z‘Ey'÷Ä}33y-A$ƒ§ZŸ«×5ǰƩœM Û¹ °uÀF ì’N dÂm Ü J²%ÆI;Þ‘bîlï 4cÒeÄ .„U7žtXmV®6÷Ä¢VLw"„Üà)ÒKÍ….έ¦Ç…¾F®Ï1™à2¾(QÊÕˆ¡çó‘ÎÑý3& ¥ÅÚüaÀ4*\²`¶t.›Éýäè=#;± 6¼Óÿ/D®‘€¬¤T!pú,z8˜|ÀÓYZºÆ}·&jÁ8ñ5—JÓ%KQP è$N×#(s.cåKÕà¼N\#XÆñÍÜ0@l4ãi0„÷¹,â Wk¢’DŽ©Ír€Nk—ÕÕ"&‘˜å8IT-@x,=‰  æYg7=C©‚ô7œ1+n!Þ¬4±ŒÆšˆZ%d4.¸åqœ—âÊtXy àXÆb*V °² ‹5pªÃAâ4*Q-A@E¥ÒÑ{ÕC)ä £V:q¸aI®œášA‰á3¸5yE¤ÿ™  ¥>Šs­>9Ý0¦8hÉ¡+¼鯙|‚¾!ö-Á.cSSµ¥¹Ð‹¯Åùô±¦u˜£ÄƒBvð°*“6 ý+nG¯CÊI•ÎΕ-›ŽêmýÍ–z>u}ù ɳou%Ê|"6°©­`œ(ßj–´Ú$É= mÉèólf™¤\›£Ý—НlAÄZ…¼†ÊS%èk2°´Mß=â*ÖOs‡„z;£nµs•ÜcÆ…ÓÇÈ7Dß4©ãÁJYÇ´¹œ`%nY!-ŸGîBEA¤5nì?©½×Øg±rí«ÐJ¦‚âd^¯A§rŠ{¸ßÛˆ°:lý¡n›wj2"D‰;Ê pðÂÚ›¹Ÿšñmð¬LŸ€Shª±ÿ›ÑjîEÈmÀ©Á‹«y$€ÖÒs”˜€³VªþãÃfê‚¥£“Ú£¥Ÿ@ç¿ý-+añ¼xžË¶Æ&ñ¼Kg½ÄaI"]Rd‘MÃaUuNZ¯c%ñ*;—$E§×ëhWˆ–UÊ$wŠ ´Øb¤;Ó’bM.ÊÈ‹ŠÃF޵Q0Öš5×±Äpç¦Ð&oá¤FNnAóY€|×ÖÅ÷,‘rK.Þ¶¤0êá¨,Ÿ}!qØö¼x&8Ñ.ª:9È™ë5†®º×jå{ÈI¥êŠß¨7“%8Ç&YG‡š;s<{ŒµÄp­‰9éÊ2ƒ˜ÏT®‡¶$”à}Ss3¹8å-©)bã–ªFÆùÍÍÈ~ÆŠûK¥´À¹­~ŒÄÕLN’X¬¯mú¦=Z´[$M†4íý¾§QgŒç¦øêºFb¬öe:Õv½˜ˆœ@<¥-Ënäô¶×‹Ý,P6'·G"à†I¢î‰Ê%î¨Ôç[ñõèöç]Dã,cÆaLZ9êh¨<ê¡ã(±°Tº†T¶X=° vÃ2ãZªMóõSd߃šó@ç&Ðã´íô,-8Å/Þ×FÑ82êS¨œ,š¨)iQ&*`1`©ªYÉ)ˆW³S2up´$ªîm l+7†,Ø–:Œ‰ÙÍL{®3:D£•ž9@yÁ`] ؀ϙoÑî˜ÓAm"xÈ IDATDnvܹ QßèØY$gÁˆÔô1h& I@,#ˆ¸õ æšÃªžä7(Íð0û1ûqd5w>;õTÌH•˜¸"¶äˆ§¡öÐþP˜x|7rMCõBÎÓF‚¬f g‘–R©SÒ“ï-ß„œw¤n7:÷t çSŒ0L…)–=n¢¡Æe°ªïTR Òÿ‹>QtÔ¹0î$µp1rœæÀÒŸ•=*uaVª(õHƒ& Y;A¹7”~)>¢O©q@(£Ù8#L:¥TŠ}|pBúH Œi©cĈ—ìJR¶¦˜I39m¤Ž­x lþ6vZ³å‘¤+,1Ö}´'RlX' ÍÔ- €ÄeÎ<ïÍz"õc£.ýŒv €3)Êäädœ›.*~6*ð0K_0É…äNü…à]\:Ÿm:€b³\\qú£²X™Ó‹wíà#®cM –òYÄ­ìm!’B`๠}¤£”}»ô&muYÄX³"f–Ø3_0¦az‰ÝàZ‚Âm.’£Îý]Vcq 9w<ìæDñÉ+õdœkq[¹–O-¦ Ö̘³ú7º6µ–T9´Þ ²h ‰}οÜc¬Ÿ)˹LͲ•å[ó"Q|Slô˜Q¸ôvIjˆ‰÷ŒKWéüz&†æµ0­¸áèCÅ‹NJÍ;(‘¹OÑ<6bŒ™D—g:~/òsH?%u.®§(PÓÆ`ɇZENaQ)•›ÚPê¬<„¾©÷+îй1`ŠÃ£r†°´‰CSöä7`cBÖ3ãnVDˆ(´­âð\1\ípr”QX¸”€Àä}Ü«9Fã¦8X×GÍEé*¼ýs¤·˜WÄÈàœ .´reº—}z´¼ôSï َ˪ýpžÒÒ)–.µzÄ ‹ë .%â“£Dˆæ™1Ë•'‰EìcžÀ©A•Ô\j-0¹×Ìác,*°8ãSÛf³.3 ]'©5R@úY‹ƒ{=†‡#¶Ö„X)Ó-÷IÌûl¢{®mû=æiÒºž[âðRšAjõy&š`yÖŠf§2 ”ppBS£rA÷Ê=—útQ„C•^Iq£:1>wŕ֩”h¬¹ŒÍ[) ÚI¬RÞɹHCóHŠHÀEð9‘´DÝMD@rjœ$÷¢.^»„÷E§b¹Q9!uvkêãÅÕ!ÍÑÞ6dŠ•h`í}š¼fÂ?GFaH.Fܪ¾HO&oi±ö"$#§X*5Cmkz«xô6}ÓòObµ% KAêm1\ÏÊ· êŠ(%9á<û›BºÚÜ3ðþ,½#9^öIû@ÀÇ~§Ê…¡ïÇÀª¬¦¼ÔcuÊïÉr â€¨ÓÊtV¹ÌW¸OøX¸G—Lí…0ll{‚t¹n4¢ˆ"Pr\ÎúmåsÏç|Özkã+ Ö“@Ãf“$èoèKW·c+.£sí qµ°ú¬aïÈñIb74ÓÆO ižqò›3¤¾5Kq7èAD«$º¾GŠxÎq?çIMuöß ©üßÙËZ“\i>ûV'² §ozpN* ‘§>·‰IPåz…3SH±¯’«FúS йšÒ%åšµ«ì‰¢›`_Œ}—CU5Y`k¨=3Íõ.†nÖW´% 1jZ×QÂaßx€Q”‡ƒ¾hÚ¹f&œ%ï¥É^S~DÚ ùpצyà¬m¯Šå³³zÌ~{›‘‡xMò3pmLœëÍê]Cš9a¥Aɰ¼èh¬Õµ¤©œ(JÜ]<É/ÓœpÃÆ –Átàøöš"¼Á‘5©W÷=—‹çi|‰g6—ÔáÑ)šÖˆPêÔêÙ1oÕZ(ç(ñQÒ¸èâáÍbša7NŸºÒ;öÊTF½´¬®©&€ÄÚ†ÍZ$£~Ö J4„Õ\sH܆ÚLÜ=¾U_ÕÙ&zÍjÅÅ÷•‹[†W `áHú%=´ÓÛtX¯Ü”ƒnŽÈâ Å+•Èú(8Øê‚ä‘Þ‰MÆ çU«©% 6<Ü$Z²¿ÃÙõQš’íÄ99ž9§¶CÁcmmq&*»hp[åkÌ›FŽ® àƒ‚µ·ùTqlm2´Ú4=˜ªŠpKD\yPHa/ˆ6a.7™Tàiþ§²-£:¦6~ 6ˆm?Â9“óWz:Oâq&¥'ÀNo'7ô·ž¸K®FŽ¿BS¦-½?C4t _;†Û€óHЖfÈñ³²%÷žÔÎùªÝ"Xr÷µÐùNí¯ ù-†Ž-ú\)‹Cddß4¹ç Ù$^~kHuZÓâLÒ‘;;¸¢:ÉáógTsT *x¨)$zûÔ yú,t¢ù­¶$ŠñÉse’š\ˆ}*#“úœž+ ²šVÆ›°)&ãlݼµµÄ]ÚAžÚ¹ýŒéLŠ=m>wõnEŸR²C|ÕÈìl°kj¸y…àžïîiлz'MúÔ+Å ó¡ÑÙ“h2;›¸6QD…”PIç¦ÿñ㔩£)~kÍ, â«^Eõ»ÇAÖ˜5|^™›?¦ÎrŸ@å<\=5s>ÃD%ŸJ´°ØPÞÒbåí#-æ#@µ,hZ{Ï%OÝ,9pi`ÓZŸÌÐÖßòþUÀÜŸŸº½ÞãSä@Ä'NŸP $jŸ™>a~¨á’ž¤åc6Ó @3é\£\C~^”"o­](É=¹¯!ÎÙ§Á²¯›L=(ð cAçÒíI÷ZòIpI"<ÜŽö½Î]vO8•D!Ïú†£"ˆ¥åÍC;(Ÿ!uOòZ‰ "=}M¾ÓÈÇj¿KŸ&Ò¥½!8M%IŠÙFÝgÛ^¹nI#|`u呌>tŠŒÝ ÑŽ¯ÕºÖrÆUV´!´ƒþ-³~W*R=9 —¥ÃsNMÀCŠµÈšÂC«˜¥ë„»%'ÙÅÖè'‹ 2Põ±Ò»èDnSýKÓH=ÔTÒyâX´\&0­oèâøZ"¸(*E9ù(eßÔe×ór•9>Å‚t5“F[×8N“R¸Äx}ë`Å=âDðò½-©©ˆb*ÈΜš0:4¯ ¯e³nqî…Ã!î%~ZZ­^÷ã6^À'#N¦E(KÕ}u!1„:B$€ JpòÜk{-BÃEÖãYšÛÚ5‹58–ƽewÚÚD•(ƒ¸K¯…ÜSÝÍ]Ûĸ\C‚²‹z#ÎPî«'µ §üRR‰åóÚÙçG‘Œ_`Ÿ5á†,°×z6ËnŠÚ†BgE€ÔúëE•瀞¡þãtؘÖEMˆ¶™e$­„d›…Äœ·x@Dg㛈7}sóàm&©&+©‚Ùïu×û¡Ä~k~SO…|w¦DcicÊ ¹Õ=èú®!Ø< R¬žõ1Äçât`q­œ¡æ¹µ·tB–à¡kó*‡zc±à¤} Ž$"ŸJ3oÙ¹„f -÷#¯Ó8ºŽÇÙ‰L¨]¶¿Ž@fßØÌ¡Ÿõ× C†4F^ëŠú(ªÜ)ÝœìÀY..'€j‚Ù¬•|Zœ›ônÍêiÕÉžã]•´·ö³|¶4ÚnŒ1i.䦽áe8ÒtzÜT Í`ãò=’=îúÐ+g/vFÀÓ¸¡Ùh2f‹ ñ„:Cùè6Ï:@Y:`Z›A`b‡*8O< °—šÜÙ_u¬(ÒJä ÷‹–½­vƒÆE%:*n ~7+ ÔccïDöL×Ô&©­=÷1β¥¿>ôñòQê¶*d€çØ ü¥¤7‹å_Rg¥ÞÐ%ê%h—8-.¶í Êå…ªŒœ=%tÃ07n5ëÚŠ:D9#¹ÿ¶+gÜ(2Vtް¶…v_ÍÄIôûÝK<4­W9 -àÞž‹f€i„@€xZ_a¶Æ¼ ‡Ù@[uAF)à;hÆEÓË*kT%Ìvà9'^û¢Zß9€2PP¿ç^CêP»Hù_bü€ 0ê® tapTj³Æñ¨mOænÏ}Ù9½¾ÐíQÔ¼Pϼµ>7ü°þi›©}òÛ"ìÎ=œÖ@Ìú1çtCò躃DÀœ`R£ÇÁ s-1FÔV0½yÈ ÅI››ù\Œçtmè* ò€â@ AÁÿ±+G…Ø^NáÉž;²,až}½»QOMOÉôœ(´¥6fl’žÎÌqÓè|‚âŠ)ëY­½QA\Ö˘:ñŸµqÊ3yP À"*Q}cé3Ç1ªÖ…î’p–Ü„9Ü×vÅ”tm@r i¾ñ°Û ©OÂP åÉ»¬œ@h/Æ€„5ñÌ[c½8¶\—Ö×Ô¡©*”¿¡š‘~¼ OuÖdjõY8Ç'àžH$£!ýrvÁ„¯i02m<2çO`)¿{ê“йm»Ui[´¨À+4'Å;Q‰Ïr4”¼?0³>*d™3榖Ñgj’úqUÚL+ <0¹¤ñìLo€¬in-@)¿›d™Ó*|J¬Üyì5Òãº0¼}—‹gºg-Jê15¯’‚‚:7‡Hmˆ&r,†H 5 •$Ip†vQiK®Ç ÷m@¯P/‰htyÑÞ‘œ4}›¹%ˆeÍ@rkV–dLCq™È£Ÿ©ðF S¢™«W`â(ˆ¥ `0e”f:E„à>A"“ó9ß"6MÕâÞú¬HžBãg"ˆ˜ KM›¥ ׊Þ𘣰ÉÎ".ð" yz ¼/çxÙVè4ÈíÆ†@iI=š;m÷äÜ”ÿÐyVtvÌf†jÿ•›“¸hêâI)ÀR3ÃùÔëw, •0Â]©ÕÄÃÜYlÚG„j-t‰00Üì-4 É4%ž Ë·\[ÓÆ4ª,Lò‹ÏÈ™8žÂõ®>-P˜›'s¸›ÏãŽt*v NP±Ö›D}úžÏìGŒ§Nv¿¨-î@%Bºs§rpÞ3žbÍe¥ ÔüíÌ”Ÿ©·¨ÍA@iÔÖÜäºW_ú¨Ãm†°Œ/]+C1N+âÎtg_è¯LB7€IK<Rpe~%êŠx½ö•&O‘(н—ÖÝ©S$Ö+²&C7×JÜEL½8ý³%õtÑ߯1¥>è€Âò{œÚÃoêÆrïWyÒ}bðYÇ(½+¹!ŽSÏHâ:ïÎEdrÞŠ›g“ÒJ-1x˜ç÷qÎ'” ÝX@„è:½èºùÄòi´¦Þ"÷•QR] ’²]îw…ufœu÷j`Ù™*œ ˜•´šö¦aŽà¦©ßâ…’÷§•æ+•ÍgO Eh †ªy¢³ÄIQ7qRZ¶Ldè ´Üî1 Qgv!zQº£žŒ/92–ÏÔá+¥çÌT·û?‰CEqÃ|ºaE¯›‹ë}ÆŒ‡CÏ/î2»Ý¿*`\›afÇ»:8•Õü „Q¹Œp-Š…þØÆôO©7kÔÈ9©CXó8ëÅ9áZß|‹æNÏóØÊZlI µb5Ïj$ÇÆ7s>+ù$w› )ËtÍCkûF÷¬À œN%ÏÚª’›ã—99Bž«ò’i&Œ‡£2¥”H©,8D`d.£jÇMÛyÏU‚u’Í]JÞ—Vý•]*ñ‹¨ŠðÇ~e?R»¯o-ƒæ7ç|‹uíEõ±"`DÍ×UÏÌVMqê|uŽâlZëφj»T3¸Ñ_¨6h¼@‹UÀf ˆrÖH½œµA6…tŽ:޹0Ð×:Æ@Ë‘Jpô:€‘j§m[ýUé¥ú< ‚GÅè¨ËHzMzUrÙû|iÝE‚t@•ÉD³S’„ˆÁÚ]rËâРT÷¥çSb9çáé\,¡„¶ ±Œç ¤««?"ŒVºl/ïÇÐq^h2ò¾F Ȥ)•0Ô +¤ŠÉÉaNqjù­ÕòpeñÚU†3j§˜i¸yG°®ˆë6%Aî¡-, Élý©òèŠò™Ï¡HåI#+j¾K™Ü,R¥Ï+~QBÒàb÷ƒd ’Š™,B€˜XqbH 4ô‘f–Óì÷¥;õw:Ÿ“ÜñÈþ®ŠÆßiÔ{pcrJˆ˜–® RÕ®Vܳçå‘{°¨pmœ@æÒÇÌ}clœkfžûd£¯YòÞñ$YI””Ê'ÔT£­^%&5rõoåÌGÖ§–{*Âsc˜6pXmEÀCd¼j)¹€Ù§Ì ú éN¢Ä%•Ö«Ã1Ql¼”Ì9G¼•¬¤4ËX ꪪXÈ} põ ÐfÜäðkõœ íJ(qÄfÿÞúì9gµ?O†¥ObéÜDÁ @ÚêËWuŽAŠC×-°¼&3d²ƒ—$ÊbŸ4Š}šùêL‚Q¥6@õ¼f²ÂÏš>ÓR‘z›¬“úqnáÚ‘ÊçX¬p¡*_:Ý·ϽÕ3Ë ˜K.ñÀQ›6·H€FK ´¦zn8=§T 2É÷Õ#—ÐY¦Ö®á„Ò_¹ÇÖ֖쑜W€€R" {—† #·¨ž«÷ÜZÉ܆ܨ 2r…!w–O¡&ïËÝÖ!Ä)ø`kìaXì°™GM\?¦@ù1B;Ò=Z~”Ù›ëeòm}s„$_5Ú^²<Ùµ<‡^*2)ÚWp= ˆõû9ÍŒöjí|éÖXLªIÓ6ó#ÒV„ÕPë y(p`TÇÚ¬(ai‰´q¶§!ôÝ0|Éý~X‘„ mæPÜÙ ~­+ö„¢Õri²0©Ì­¬òY©7‰b!'?(x=4GR°é˜¯L¬]FýÌЙ¥%ÛñÁÒПM˜sä#OÍäXbLèrœ @H¢žÀ:¼ U±Úè!²“õöÞûüï4?.j2‚q¶ÒT›—[ ÕÂ}MÀgöUBJ5N‡ÆÎEi+hs×Ni? ó-upKŸú¦ôoꇖº38’{ªM×[Ï<¼ ÈMtKC×*Ï’E_“é-‘Ï™=wŒÔ£JÀÓ‰é0œÔºÍN\ O÷½Ñ8§Üv.b¤9özVrx®qG×ÃÄõÑ9NCAÄJ £9HÐaW‹³ãˆ¬1&I­ 'ü"æ‘n¿,¹©]ᛪïü=¿·Ô÷Ý…àˆ`ÅŠó]µ¥&¿3Û‹BKT¸D0ËMQ΢åi pCrO1X@”kë(¿yß 4Qˆ…˜í^‰ŠºÂ½^¬vŒdu@–Q§÷{ùQßQLÇš‚i‘¯l–‚Šï[x¿†á#@®®Ê±i^b]䯣ù3zÅ'=2ŽhtüŸiù­ÇìÌè\fÒr¡Ý$“¾rótc‰#@ÛL^çV.]Æ‘ò•ŸÚ˜T W’‚›ÈÒḑ–…˜ €? å_ÏÎ_ÑRž:^§MîäpP@ÞäQFn˜hG¤ÈŽŠìHòJy O€“Z3|ç:Š|= ±n©8ì™cÔ¬T&÷ £²µ5@$˜§! €ÔçMF®‰jx€\_24µ‚É!ðYŒƒV,Uiåœ!£½ráâ|Ya,•ñÿÒŒiëÆbâk¦TŸ3Œ2‚0£ñÊ]w蓤}cd(ÊYâºsŒî Êå™ÀŽsrB#º'Åð`§>Ë$Ne,Z®Jqï¤*1ŽÑ ØpÀŸŒ“$'^q 2ˆ8äŸ6žÜÀ€Ó¨è¦õkŒœüÜG˜©K eì¨ÃÏÏáq@Œ<)Ÿ;l ¥–xÐ9oñÝÐÁ–¨I¿½˜f[ŠÚÃ5¦DÙ׉1 Ã Ÿ /×”8_â°ÆËÂñhÃóó V³ÆÉ#!< „,€£$”î|dpÒ¼hMS8Jn¤®k© kâÚëR+g€b½K]|žyV‰wðp6.ÆuîKŠÜwì³Ö)Sïc§ëøÈ÷p…ù1̸-ð1[ ¬-Æu®yãií“ ¯äÒÄ£¾ÇL„QôSWêùÆó†ÕIéÄÏ”Š¿éU —Ü—këAôa`„ÁJó8‹ËŽýê¹çY\% tS(cÉ‚¤¼áá(?%Y˜˜ŒØ¹3ûl”È&2¢E@ìçì5´Þ:ăŸ7Ö)IÑGw&Eö´¶¢¶Z"n bÚ2Pdy݋ҷӧ ”WK,ñÓ6€¬™ê &ÎW%Ôqí&x’e† ‰R™YÎEÞ!.•siúÓTfÃ~kŽI‹—Ókì%Â:çKjô.Òi|å·†6FöÖJŸ¨è„0`8"OùÒ•¡^2ãáɸ®rOÄ;'ùìº*æF:ŠÛý“iú³šZ@Ô¼Í ’7Î0¹5E³ÕÄr¯kŒÚ_äcH$Yh®p[ÈÅ3ÇHÿ·x× H1|¡T0kA²_ŽtÞkÿÖd¨ØqógDöÕ»[Søù çônö|“,ÿƒæÓÛ¬rʵɽ ˜rjwpª(¾ŠDþÜœ>¸aÓBÏ=›yÑŸyrȇâØDQ]­ÄËp›œ| AŠPCŠ4 õ²Í#´!Ñ6,Øá~½;ÄJvÅ#e·;(Ö*{HÖòt÷™ËBq+½õéOeY3¢or²å™%¢X΂¦)XjY K¬Bö=ô <ôܼÁºëЧfÕݸ6(ðä .KOïFŽò´iœIûIS–ßt#b  —E¨ŠØ„t†Åk€3KåHI+Pp¬ÒݨGºŒ ®I :±^Ôµq¨ÅÞè"Wi …➆šRi”³u,•Þ³2[váàŒƒ›ð4i]#eº¯ÈÄs,ôÛŒ^ÅZs¼Ò!ƒQÆ2U6d¿ã˜Ë¢]zÐ^${5o Gísíé‘$êY>/‹í˜íFCr’IDATö¤£ôÇ(#„åé5ö,ÔìCÊ©˜ùTÙè³ÐíÎ\[ ˜‡ÅŠÀ‚óµeß…%£:Ʊ{;ßq¶Ú•¿¬øŽØ=Q'3&ʈ*Ûr. <„¾Ã”µ`°ðŽÐÝM¦"©¤`rñ™åp1Sø?ÉM¬<‰Oý€ôt¢ˆò³r•ý£W´VR‰ª –™ÓÇhï0¤§#¦è 1‘b–“­©[´Ô$š×ÓßÐ{ÂÂS‡ÐuÅÍ8\Õ+ç«Q¼áM»™)ê3à >•I„žÿ®º+TßTz­´DºÊ×ɱ¹Æ‡(mwP! mÕÈ­ÓùÒßÅÁ]C_ªtùRÆNdÿ Êô ;‘zr.ÉÅ>,]H' s¨ÕÙIä´nVëâÑ€EÖ±xÞ<¦øx øØy›žÊ*ì4õuò7½Rl¥Ì˧¬‚ÖÌ«£> x43†€‹»G‰¥‚#É!u8Ëo6rbq€¥î,ݹ¥ÅTnX¼ûªËcD:ƒ.@¦ž3°U°휲³£}fé»êý ›¨ìÉòQ,Ëö*çâ)` rfñÔaÔĸô-J7âŒ&¶te7Èép§ƒ-ŠÓÀP+PêRMFÑfËéÕ¹ÊÃŒõ!µ¡4ùEÕ‹:rkz­ëÏÈ»Þ^<çô™X}Ùø´¤¶ ª00m¾¦x×™ç¦è:²ø‚]V“'Њškûˆ³™F W”…Ž÷ ¸½6°)äǨžÓ ³é5RS:qQ`Qv‚@p2  kYçÊ‚ E¥;5Fý¤fÑøÜéL~™¯hpåÏVÑæâœy'L{%×иòs’0û©…R4Kô®<ÈŠ+Š ÑþXsPoÓ{ ÖsBePרevÎS# ÅÏw)ÃêÞö…msj=[ù¥¦FÒ 'W§1pc滺$ç$Þƒû0Ÿkâwë„9€¬ÛAfa³&d%>±f%›:.Evç(‘DÖ%* 5wˆÝ0Ĥ°¦b­ Óˆ€bB®“%çF û"/ÿdñ-9Ë6}ÈR‚qz·éÕ5Źé€â«AAÒ*ñ•›¼&S‰Öœ’ ÇøÊ[géþ¯\s„A[^ÜF)u½Æ+0☆ÄïÉú¾ÆjñùåÓÀ,À˜9 ÿ·•ÄÈfŸi½Ièà…rŽ”éÜG7Iòšá6sÙ· nªÚ”/Aêhøùp)Í56ê_e ¹ö‘ö°F˜Eì.{H…¦k̳%ˆë‡M¸ŸÖÁ3²`=³L\béË0!Τ8Gó &f¤ÏUS­¸Ã©c3˜ÚÑùì"öF+8‘jG¬oºÔ$PQž¤C ÄXéÓ$zè=?ãzè˜åfi‰o½öƒDÔ8“€(œ*]tĸ[qÛ°22"þPŽ­A@HaØ—áIâó[;ÉDajwC2xMRmÛžŠÈ!]´Õ¤¦KÇVˆ+ ¨Iƒ– `7r.)E< H¹TÊfnö)¾µÑ¡)Ü ì’›‹+µD©Ó(òÁ®Õ&µLB¨(¸žš¢a^Rž”/¹X®SV/'ç˜ÜD× ñz-‚2^l ÔkVjnØ©)bú*aA?~é]Ÿœ* KªfÎV@djÓC>S}4“ŽÖ å›W‡É9Ÿâ¶Ï¹WDÀ•Ý¢ö‘) TÕØd†`[aÃ1Ò*»Y2X_ï<›Ô¥?äØÛa¶»ô¸qb¯¥nKãÉ=¤+N’ܸ«)G°Cì­æ-ãÆ¢oî©!:—§;89îC™€|*9;Ï{]Ì¥®è7÷(dmþmKGÖ9õ…IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/images/entries.png0000664000000000000000000003376515074673150023502 0ustar00rootroot‰PNG  IHDRpþ#Ô^#sBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timejue 08 dic 2022 22:23:47R=šƒ IDATxœíÝy|TÕýÿñ×Éd™d²ïd!È’ û*‘E,ˆ´¥¢BÝÚª­mµ¶Ôºa…jÛoõWq¡n´ ¸"D}“%„„ˆ¬$!+Y&³üþH2d’I2„ÄÉÏ“Çyܹ÷Ü37“wΜ{îB!„B!„B!„Bˆ^Dq’:…âj`îÎʺ#lÛ«C‚\!µÜWè] ÙÖÛ)v>&„}Ië€6Ûù˜].7\mµÒÁ×]ÝB8;[amîàk[Ûuèr‚µu0+-ŠªÕ÷í¹Bô%­Ãºe1µú¾õú²7\m…vspÛ*âBˆ¾ÎVx›Ú)­Ã½åöír±£íõ¸Õ-þWþ@ à ¸5Õ-.„è«Z±¨*b  06S‹ÿ[n«ÐIˆwà­Ã»¹‡ÝÚ.€0ð£ÿ­ýÉèQ#¢à‡Y[!¬(˜Í&sÙÁC©üdáÂuÀwÀEÃ]áRˆ7y§!ÞYж2iÜÀôèÑc>\ûþÿ) >]~bBч˜¡|îÍ î;vìØaàÐ@c7÷Êm ©´ÑQ€·ì}7÷¼]šŠ+à=jÔ¨‰ëÿ÷Á›fû†b„B4QÀ0gÞ-KŽ?¾¨ô4†¸ë±qh'Ä; p[=oWǸ¿?¹¤ç-„]£”õw+pœÆ1òæ·ÕoCÕ^­­¾nñæ¡“ ÷ß[³ o!„¸f¿w×¼5ŸÆ 3Võ,>h§³ÝÙeð-‡N44ö¼=€øìÓ™ÿUÀïŠÛ/„}˜Ùdº—ð3àPKcO¼yL¼õIM+]ÛšyÒä~Š‚o÷Þ–Å9T*/0P\i¤Á(DˆÎhÔ A:ÃÂ] ó6u¾ÁUNQ©ühì k°>™©¢“™(öÎoàZ™*Góáx^Þ¾~„z (}þÑ)³ÙLm][¿+#1LEbxŸÿ½Q-ÖC(ÍDvÈžxëo:‘Ù·{›•*Žç5ÆØZâ‚5h]ûü QˆNÕèÍd¹óÍ7¾Í+ HçJ˜Îèèf9š+—òµe€7—.õÀÛFQ÷ñüæxo_?ÆÄzáêèæá4´® Ã#ÝØYçlj¼rÂâÛ›OÑg\ÊÖ¶·$i—­£fëv°­C\eëÎ,}©Wqs÷`P°¦£ã+„hÇ WÜÜ=(®6:ü÷ÙÑëÛ“´Þm¼³?{íݸJÝÉvW½£EQкõùžƒ]¢uUP½Áìè¦ô-ÃÛÖ mêh¸­¹à-+BÑ=Zç«­üm£«w#TúúIL!DwêóyÒ¥ÏR¸œ»Z/ëóÇ[Ñm$O ýO>ýìs6µ³î\|ÇeÕ]VVÆéÓ§©ªªÂËË‹ØØXzè™´Ïh4²uëV&OžŒ‡‡G§ëçææròäI›Ýpà ÝÝãw¿ûááá–åf³ÙiîÇâííͼyóº¼}yy9û÷ïgæÌ™ÝØ*!.¹ùÖ%\“0ˆ?ÿþ7x{{PY]Í‹û'NfðñkÜÂ+ ð®ÿÑè3ÒOe0iü„×›8~<­ß@zF†]õ V« µZÞ:¼+**ÈÌ̤¡¡øøx«á•óçÏ“Mmm-ááá 4ÈòXff&nnnxzz’‘‘AXXšþÕÖÖ’™™IUUÑÑÑôë×ϲ^¯'55•ÊÊJú÷ïOtt´]ϧ5£ÑȾ}û3f iiimꫨ¨àðáÃèõzRRRðôôdâĉ”””pîÜ9âããIKKC¥Ra6›ñöö¶z~yyyäåå1f̘.µOô€^˜'‘ýHÏÈä‰gVð—Çþ„¢(,îE²sÎÞ+Ú,=ðTUU €¿Ç·MoÖʪ*»ê Á`0’’ÂôéÓqqiûc<}ú4ï¿ÿ>C† Á`0ðå—_²xñbâââÈÉÉá½÷Þ#&&†ºº:RRR1b?þñÆ?}ú4•••DDDàéé @QQ«W¯&,, NÇž={¸óÎ;ñõõàõ×_'..EQظq# ,èRHF>þøcvíÚEÿþýmÖ×üÇJ¥R¡R5޳qãFRRRðóó#22öïßoà»wïF§Ó]v»Dßòä£àñgž'ç\.O<»EQøþì9‚YöèÃŽn Þ£t:/ÊÊÊ)½pààv×+--µ¬o~ò“ŸðÅ_°{÷n†ÎäÉ“ ‡R>üðCn¸áÆŽ @tt47nä·¿ý-QQQ,]ºÔR_zz:o¾ù&sçÎÅÕµñÆ\uuuüþ÷¿ÇËëR›6lØÀ¸qã˜6mšU{ôz=K–,±ô’u:;vìh7À+++ùüóÏ­–EEE‘˜˜hùþöÛo'22²M}>>>Œ1‚ŒŒ ¦OŸnUGUU÷ß?QQQ@ã;””ª««ñòòÂl6“žžÎ½÷ÞkÏ¡}X€¿?Ï<þgKˆðôã"80ÐÁ­kÔ哘æ>þÏ×Ä'°gß¾×Û³·ññ„Añvÿ1cÆðøã3kÖ,rrrx饗x÷Ýw1\¸p’’8t臢ªªŠóçÏ—z¯z½žüü|ËPCEE…¥þ¨¨(«ð®©©!++‹ñãÇ·Û¦–ë'$$páÂ…v×UWWW«¢ÑXßL«ÕÚ]_3OOOKxJFÓðTNNnnnVC?ÂñýûÜÞ?µÚWÍ¥»j\4h4‡ä‰-ÒïA7̘ÎÞýûùô³Ï6d(qÛžÈü.+‹O¿øEQ˜9cºZÚ§Ñh˜4i“&M"##ƒ·ß~›C‡YNlVWW[Í iî­ Ö­[GNNÑÑÑ–!’Ž”––¢R©¬Bµ#nnn˜Íí¿0u:ÝeM쬾Ž$%%qòäIFEZZIII]ªGô-eå,{v¹yùcÞ@n~>ËŸ}‘§ÿ~¾ŽÿH` ðÇÌÓÙüÕž}á~tÓ&M˜@€¿?%¥¥ìÙ»O¿ø½^N§#´i¤+ˆ¥¨¨ˆaÆ0dÈËDK¤  €‡~µZÉdbûöíÖïááÉd² E8“¤¤$¶mÛ†ÑhäĉÜ~ûíŽn’pyq•%¼Ÿ~üO,{f¹ùùüeÅJV=ÿ´ƒ[x%óÀ=mÒÑÅNw,ZÄ Ó§S¯×óÑú üîpÇ]wóûGþÈG6ÐÐЀ··7UUUüåù¬†1ÚS__OuuµÕ²šš éׯZ­–˜˜¾þúk›½ÖÊÊJE±\ùYeÇÉS???t:°ó™÷,FCmm-õõõ®D@@ûöíÃd2ÉðIoäèßg%ûûb¢£{Û>>øùøðôã"&:Šìœ³½a¸ôÀ{šZ­æÎÅw0qü86oÙBÆ©L***ðöÖqM|7̘NXHϼ°‚s¹¹üåùxâÏâãÓþÛ³ÌÌLÞ{ï=""" Äh4’™™ÉÀ1b·Ür o¼ñÿú׿ˆ‹‹£¼¼OOOæÌ™ÃСCÙºu+¯¾ú*AAAdeeÙœÉÒúyÌ›7µk×RPP€YYY,Z´?¿ŽgÙØbë$&ÀM7Ýd×öaaahµZÞzë-"##™5kV‡ë'%%±iÓ¦Çð…hiÃ{o·Yæçãêçßónfëæí}¦pk*¿ýÍý}ú ŠcùftÞ>ŒŒv³ký€€ÆŽÍœY³¸åæy̹ñFÆŽM`@nnnŒ3†o#7/#G2fÔ(<<ÜmÖ¸qãÐét¸¸¸Èõ×_ÏäÉ“-'(u:£GÆÓÓ½^OXX£FÂÕÕoooQ…ÀÀ@fÏžMpp0ýúõ³œH $¸ÕÌ™ÐÐP1›Í¸ºº2zôh"""P•JÅÀ­NDº¹¹Û¦ýŠ¢àîîŽZ­nSšç›wVŸ‹‹ ÇÇl6ãããCHHjµOOO›óϽ¼¼Ø±c7ß|³å¢ áx‡sê©®¬ ©°ñßÿù¯Í@. o*ÍŸNoj*6ûé¶ŽZËðnnw?5Y×TÆ>•¶ª{Ÿ‚sy牰ˆ(~q]÷…Aee¥¥'Ó¿?Ï=ýT·ÕÝ×¥§§³~ýz{ì1G7E´ðï•äžåŽQ}û“­ÄyØT5• ë o3àrÓûvé ÞÞÞ<þèŸCP/™gzµ8zô¨åä®è}ýûìèÒU2ÞËx{{óÌ“O:ºWƒÁ@ZZwß}·£›"D·’{¡ˆ«ž‹‹ Ï<󌣛!:"yÒ%WЗ#.„è.’']Ñ·Ï!„“ï"ZÁl6S£—žƒ]q±Þ„ÙlÂUÝ·§^‰.¡ôõØ òR¨­«#³Èá‘öÍB\òÝyõuuéT˜19º9NINbvÑ0¶.ã›3á=(Ä­«ô$„èLÞLf‘žoÎÔPY^ƨ80ëÝ,§$'1»(X«gX¨†cùì¬óãÀ§ù83!Él6S_WKeyÃú¹¬íü~6Â6™~5èåÊÉ‚rΖÒ`ìÛÔ„°‡F­¬S1*N-á}…$À¯P°‡žà¶·ûB´Ë ›Š¸2 E!œ”¸B8©®O#ìâÇ[ !„èÒB'%.„NªËC(yg³»³B!.S—|ìäiÝÙ!„—I†P„ÂII€ !„“’B'%.„NJ\!œ”¸B8) p!„pRàBá¤$À…ÂII€ !„“’B'%.„NJ\!œ”¸B8) p!„pRàBá¤$À…ÂII€ !„“’B'%.„NJ\!œ”¸B8) p!„pR.Žn@gjª+)-9OMõEL&££›#„¸Ê©Tj´žž… õÒ9º9êÕ^r¾Š ¥DôEçã‡Z­vt“„W9£ÑHUE9ùç²ñöõ' (ÄÑMjW¯ ðšêJ*.”’8—^ÛL!ÄUF­Vãë€ÎÛ‡ôcGððÐöÚžx¯/-9ODÿX o!„C¨]\èKiñyG7¥]½6Àk.^Dçãçèf!ú0o_?jkªÝŒvõÚ72æ-„p(µZÑØ{'OôÚBÑ1 p!„pRàBá¤$À…ÂII€ !„“rú_·n›7o¶ùØSO=E^^ž]õ|õÕWlذÁòýwß}Çßþö·.µé­·Þ²ª«Ù¾}ûxíµ×Ú,¯©©á©§ž¢¼¼¼Kûƒ¶í·å7Þ 55µËûBô.Nà}ô›6m²ùØ“O>Inn®]õ¤¤¤°~ýzË÷™™™¬ZµªKm:qâË—/o³|ùòåÜwß}?~Üjùž={øç?ÿ‰O—ömÛoËêÕ«9räH—÷!„è]œ>À{£Y³fqâÄ JKK-ËjjjسgIII|þùçVëýõ×̘1EQ~è¦ !œXŸ ð-[¶°jÕ*>þøcL&Óeo¿oß>^~ùeÖ®]KEE…Íu&OžŒ»»;»wï¶,Û¶mÇgÉ’%6|æÌ™ví§¡¡çŸž††6lØÀË/¿ÌÅ‹m¶£¶¶–uëÖ±råJöìÙsÙÏUÑ»õ™7™LÜrË-,[¶Œ‚‚ž~úifÍš…Ùl¶»Žûî»Ûo¿S§N±bÅ †Nvvv›õÜÝÝ™2e ;vì°,Û´i³gÏfîܹìß¿Ÿââb*++9rä3f̰k?z½ž¥K—2}útžþyöìÙƒ»»{›6”””0nÜ8þú׿òÝwß±xñb:d÷sBô~WÅ¢vîÜÉ#<Òá:ï¾û.‡âûï¿G¥R¡×ë‰çË/¿döìÙîcÓ¦M|òÉ'œø`»í}î¹çˆˆˆà³Ï>C¥RQUUEbbb§ÏSá<®Š¸««+^^^mJK_}õqqq¼óÎ;¬Y³†>ø€ÀÀ@ÒÓÓíÚÇ'Ÿ|ÂÂ… ñõõÀÅÅ…‡zˆ­[·Ú\Ö¬Y=z”ŠŠ ²²²¸xñ"Ç`Þ¼y–a”mÛ¶Y ŸØ»Ÿ9sætØÞ/¾ø‚_üâ¨T?bNGhh¨]ÏUᮊø¸qãlÎúxòÉ'-_—••Q__Ï÷ßoYvÓM71iÒ$»ö‘““Ãu×]gµ,66–’’Œ6n¼•@DD»wï&;;›Ù³g[NRÎ;—™3gÒÐÐÀ×_Í‹/¾h÷~ìuîÜ9 l!®rWE€Û#&&†ììl›Ao«ð(**"22²Ý»&Μ9“;v––ÆÝwßmY>fÌ<<<ذa™™™Lž<ùŠöÓQ{ÇŽk÷6BçrU ¡ØcþüùlÚ´©ÝyЊ¢`0Úý~êÔ©¬]»–üü|˲ÿûßÌ;·Ý}Κ5‹””öìÙcu’R¥RqÓM7±téRËŒ•+Ù­ö^ýõüãÿ ¡¡€úúz«iBç×g|êÔ©üú׿&99™|'žx‚qãÆQTTÀ¤I“زe O?ý4&“‰±cÇRZZÊ#>\Ad¨û?Cã¢&2ÄWØ||ÛŽ]¬~{M›òŦÍíÖyðÈvìÚeù~Ë×ÛÈÎɱÿ‰´ràÐa«úZ3 ¬~{ UUÕ]Þ‡=ºûø~üégì;pÀæv{÷`Ç®Ýèõz6|ò©]ÏíxZš¥>{ŽIgǵ»”œ/$~H’Ý!àî¡%aèpJÎÚ|¼åëòíwßcë¶ÔÔÔÙ]ÿõšéHO—ßì®&^œ&ÀÏW.+\Â|Ôx©qÕ¨9ßÎÀ×;¶³s÷^ª««­Jmmû¿,aÛŽÝ–ï_\õ2Ÿ~þÐø¶ñåþeeö’Ð7ß´ª¯µ††V¿µ†ŠÊJ»ëìŠî>¾9¹¹¼úú›6·ý׿_§êb5gÏå²bÕË=v¬Óý½ûÁÿ,õÙsL:;®ÝE¯¯ÇÝC{ÙÛ¹{hÑ·3´ÐòuYPPÄk«Wó³ÅKÈþþ{»êþ¡^3é©ã²ï›o®´iW§B0™í[/!TòùQQcâ–v¸îˆá‰üî×t¹M¾ÿžÚK/Ôµ®cþ¼¹øùùv¹NGéÎã;=9™þû!……E„††X–çæåó}ÎY¦Lœ„NçÅ>"Àß¿Ó}>ýÄR }èÓ™Z¾.øÃ£Kyaå*þß?þîà–‰ÞÄɼó„¹.Î?ÌôÅU­àë¡â·Ó}ØwüÜí÷à‘#|÷]áaam>âmûÎ\Ï ¸8Þ~ç]>Z¿n[øS<<<øþìYŽ;Neu5q0vô(ë˜ÍN=Ê©ÌLú…‡3iÂøN?H5ëôR~‹ÖSKòäIxzz^Ñs„î=¾C_Chh;wïá§?¾Å²|ÇîÝŒ= Î ƒÁÀ†O?cá‚ètŸ;XXTÄþßP[[Ç€± <Ž?A]m S&O¶ÔUQQÁáÔ# FFITdD‡m¯««cïþo(:ž¡C®aØ!ö‡Òh4,ZøSzt)z½žÚº:>\¿»—,FQOOK#¯ €YÓ§Û¬Ãd2±ÿÀ7œÉÉ!0ÀŸ„øxúGEYï‰×Ó¡ººšqáBC‡&>.Îrô\n>‡S (0fÔ(ÂBC-Û}òùçLKNæxZg¾Ï!"<œë&M´Ogá4C(&ScñvW±ê'ćh,ËL&˜—äÉŸoôÃUÝøC¨¨5±îðÅ+Úçò¿<Ës+^âlnï®ý/k?ZgõøÇŸ~AFæw@ã'y¨T*KŸH;ÉCü3©ßãØñ<úÄr^xi•UÛvîäÿ­~ƒ³¹yüíÿÇ}þŽz½¾Ý6}ðßùÓãËÈ/*dÛŽ]ܺä.J/\¸¢ç Ý|§''³c·õ0Æö»˜~}2Ðö­þ7‡³èçwrðH*ù…¼þÆÛž?ßø˜!‘?>¾Œ'N²÷À7Ü~×=lݶ£Ý¶”––rç/îc˶¯):_Ä£O<É›ÿy粑£x{ë,¯«òŠ V¿µs‹?¸ÇO¤±ió›ÛšL&~ûðùÇ«ÿóÅÅìØµ›Öo°<ÞS¯§ž–s–Ûï¾—)_ñÝ™3,ÿ˳œÍÍ`ãæî}àפLgûÎ=,úùÝìÝ·ß²íÇŸ~ÁÂ;~κ?#/?ŸV®âéç^pÔSé2'냇ŠÐ?Ð…ço àÑuÈ(Ôó›©>ü(éÒPF^™¥—‘WÖñÛîÔoñ½fµlÖ Ó‰8]{ör(õ(ÿýÏ[xyya6›YºüÉvëZ¼èV^{ý n¹yÑ‘‘@cOtýÚ÷,ëìÝ·Ÿ‡ÿü¿}à><šNð$ÊßWýEQ¨¨¬äŽ»îe݆Y´ð§mö‘›—Ï¿^_Íûo¿IdD? ñÌÿý_ß÷ËŽ`'ºûøNŸz=ïÿïC**+ññö¦´´”Ìï¾cʤ‰6×ÿä³/˜sã<üàoìjï³Ë—1§þtª7šÀÛC…¯¶ñƒÖUá…þdo 1ÂÕ²^êY=Ë>)£ºÞÔi­õ™òæðž}û™15/¯Æ·÷Š¢ÉùóÅv·¹ù-Ymm-¹ùù¨ÕjÌf3çKJ,!`YÏÇÛ›¹sfsèHªÍ?rô(>>Þ;q‚c'N4íCEöÙ³v·©=Ý}|âÊž}û™=óvìÚØѣÚ}{À®=û9|8ãÇŽ±Ä-X¾^¸à^ómÎdgsMBB›u:Ì䉬fi4—†?”'ÓYýöŒ#YgÎðÝéÓücåK]ªËÏǵZÍ›ï¼Ë‚ èÙ×SOª¬x†ËIIDATªâБTž}jy›Ç§¦n o€Ûn]È[ÿy‡syyÄDG kú½yíµh4 $À{ŠÉlæLq¿ù „—@€§­«b.›NÔðRJ FûÎÈ | ÷ü|‰ÍÇŠÎsíðÄ+j³^¯çÅ•/sâäI†Œ¯¯O§ÛôëÎÎ={m>VU]‚BAᥩVáVã™]ÕÇwZr2;víaöÌؾs³gÏlwÝ{ï¾ WW7ž{ñ%ŒF#?ž3wý|1n®®ínÓÌÕÕ• À@JJm¿õ¯ª®æbõE«ã¶háB»žƒ#èõ TWWãæêÆÔä)üeÙ㸻»w©.___V½øß¸‰‰ãÆZê0šŒŒ1EQøpýÇ]bíè‰ã7`ÁA¬üûß=rT‡Ó| 4 'ŒgÔˆk)ì`¸*//Ïòõæ-[ñöñ±ô®EÁhº4>Ÿ|Ýd>\¿‹55öŠ^-(°qÈíÀ7‡,Ëjjj-_·~͘ÍfË Ï°ÐP-ü 55uTVUõèë©'……†àïçÇÇM×`´4ó´ÓM쌭³8J‹¢jZÇÐnM%â±Ç–¶?˜Ùþ{ “Úf3–R^c¢ Ühµ¬e1Œxªë¹{J@›:Tèt^Mã_—Н¯/ƒDQfΘNdD`æú)×qëO~‚Žþ–ž\?ˆ€€Æú§\7 /OOÜ4® ˆ¡tS“§ VTôëοüQQ‘ÄÇÅáîæŠÂOo¹™b1™ÍÌš1»¾Øêíìu'P¯o 4$˜à  ÄÆpÃô©¨T* F#cGbÜØ1¸ta†BOßfáa¡èt^Ì™u#Í¥>ƒ¢(¨Ô*F^{-nn®Œ3/O/ „‡…ñàý÷1(n`óÊDö £t4Š¢àëãÃ÷ÿŠÚÚ:"#Âùͯ~EBü KÝQ‘Ä ŒÅh00 6wwæÌšITd5uuúû³àæyøø´C½Å…ù…†ãÒôË^uµ5œ/È#,¢íX³‚ŠØþÑDôë×îöÇ#:*£ÑÈÄñc¹÷Ο£õÒ206°~Í ¾&¤Äa`2£¨¦%Oáwßi ³žx=ýÇ%6&†ë“¯Ãl2ãîæÎœgqMü E!)qÆŽÅ`0; †ïûQQ—NÞ¶þ½m^8<)Ñîa©îôìsÏmr}Si €©©Ø|¯këÏQËðnnw@ èšÊ¸š‹Õ«llÛcV|^È;jðõõA­²ï…Õ8FVÁâqZþxÓÕõÖ©»Éñ횜әÔÕÕ’0t¸Ý—Ž7ß´ÉÝ]Kô€¸n¡cÈq¹K½@þeÜîôöq^<0Õ¯ó•û89¾]Ò/ŠÂ¼ŽìßÕî=Àbcc™7oÐxƒ7ÞxƒuëÖñÀ8¸e?¼±cÇ2dÈ.mk6›Ùµk&LN¥¡¡/­$-=€ßvÆ E__OZz:kÿ÷!Å%%”——Áú½ƒ[}宊oI­V3eÊÞxã ...œ?žììljkk gРAVÛœ;wŽœœT*ýúõ#** EQ0›ÍdddPTT„N§#22’àà`¶lÙÂСC-=ü‹/rèÐ!’’’ðõõ ²²’ƒ2mÚ4 ±÷œ‘‘Aqq1ÁÁÁ$$$ ( %%%œ;wŽøøxÒÒÒP©TŒ9ÒRÏ©S§¨¯¯gàÀWtl233ÑétF²³³qss#))É2Ü´uëVvïÞ§§'ÉÉɨÕjvìØÁ”)SHOO§¬¬ŒAƒñí·ß2mÚ4«‹­vîÜÉu×]wEm¢+Þyÿ«ð~áÙgðòôÀÃÝ¡ƒ[^ç‘<þèŸðöövX{»ËUàZ­EQP©TäääðÞ{ïC]])))Œ1‚ÿøÇ¤¤¤°oß>ŒÉd"55•û￳ÙÌ¿ÿýo*++‰‹‹ãìÙ³œ={–ùóç“••E}}=sæÌàäÉ“|öÙg˜Íf’““HKK#++‹iÓ¦QWWÇ믿@XX;vì $$„{uJEqq17n$%%???"##ÈÉÉáÍ7ß$&&www¶lÙrEÇ%33“C‡áïïOdd$§OŸfÛ¶m<ôÐCh4TªÆsÚ*•ÊòµÑhdãÆdddÐÐЀŸŸcÆŒaûöíÄÄÄ@YY7n”?¸s¹¹lùúkË÷‹o» /OOR~Ëê·ÞÂŒ777 ‹¬Âûè±c„‡Ú{ï6Ø™«2ÀOž²³³­^žžž¨T*¶lÙBqq±ÕþLnn.uuu˜ÍfNŸ>Í-·ÜBNNŽeYVVƒÃmܸq–¶èt:FEVV–ÕþZ†wee%yyy–€,¡ÚFƒ«««UiÞ/`uòÓÝÝþýûsáÂ…Në½æšk¬¾OJJâäÉ“–ïÓÒÒHLLì´!ºŸõ K}óL,³Ùvxû-«^~…ƒ£“HÌUÑ7 ÔÖÖ¢ÑhHLLäöÛoG£ÑX[·n999DGGãÙ4.Ölñ⍤¤ðÚk¯áããÃôéÓ3f ^^^ÜsÏ=lÙ²…+VÃìÙ³‰‰‰! €àà`²³³Ñjµ„††Ddd$™™™àîîn ܲ²²6½xrrrÚ}Nåå常¸àîî~YÇâÚk¯½¬“˜]n™ÀÚµk),,Ä××—³gϲdÉ’.Õ%Ä•˜šœÌ毶`2™H;™ÎÐ!ƒqus¬Ã;ýÔ)V½òw T*S›Þ1;««"À[ÎBiíàÁƒððãV«1™Llß¾Ýòx`` ‹-bþüù¤¦¦²nÝ:‚‚‚,ã»qqq\¸píÛ·³zõjž|òI4 ƒ&++ 777KO{èС¤§§bÕcÕét”••mYV]]Ýfº_K:ƒÁ@UU:]ï»™|ó18yò$þþþ 0à²ÿØÑ"úõã†éÓØ”òk?ü÷ÏÜÛŒyW_¼È¿ßxƒ†¦iµ7LŸF¿ðpG6ýŠ]C(©¬¬DQËl‰ªª*«Ç›‡M<<<?~<ÞÞÞ”••a6›-ùûû3eÊêëë©©©ÇÁ³²²ÈÈȰ„õ°aÃÈÈÈ 33Ó2þ 0pà@vïÞm¹-¥^¯çðáÖà·Å××—€€vìØaõ\zRóq*//·ký¤¤$ÒÒÒHKK#))©GÛ&DGnûÙÏHÚ8ö]\R¹ÜÜ6=ï'žzŠÂÂ"‡å¶ŸýÌ‘MîWE¼#C‡eëÖ­¼úê«‘••eù”“ÉÄsÏ=Gÿþýñ÷÷'//“ÉÄ AƒÈËËcÍš5 4­VKFFƒ ÂÇÇh<XUU…‡‡@cÐ{yy‘““c5åoæÌ™¼ú꫼òÊ+ÄÆÆ’™™ILLL‡cÆŠ¢0þ|Ö¬YCaa!þþþœ9s¦ÓO(²usРAm¦N¶·ÏøøxÖ¯_ϰaÃ9r$~~í¨Fó0Jqq±åœƒŽàââÂ/ï¹›‡þø'êõú¶cÞMÃ&Š¢0ë†,Z¸ðªø´/[Ÿ˜ ´(ª¦u\ àÖT"{léÌžlXIQaѯ„††ZB´5oooQ…ÀÀ@fÏžMpp0ýúõÃÕÕ•¡C‡¢R©0™LDGG3þ|´Z-ÞÞÞÄÄÄ`6›Q©T$&&2sæLË AEQðññ!!!àà`Ëþüüüˆ‰‰±L„Æ“…£GF§Ó¡R©;v¬Õt;EQðôô´bÆák¯½•J…³gÏ&00ˆˆËKŠ¢ ÕjQ«ÕV% K-Û S›ç¯6 www\\\ÇÝÝ•JÅÀÛìS¥R‘ŸŸN§côèÑþœ„èIϼ°‚’ÒR«ðþöØqþïµ× bâøqüòž{˜&tEXtCreation Timevie 09 dic 2022 08:53:46cZKIIDATxœíw|TUÚÇ¿w23™”™É¤÷BKÐ{sQYÀ@ŶȺËGÝ XTTØ×²+«ïê⺀ðU׆¤÷Ž$„Jz/“)ïS23™I£ÅÍùæs?3÷ÜsO¹¹Ïï>Ï9÷Þ@ @ @ èÒ/¤L@àó¥,ìR¯§2„0—OBpQÑU£uÝOêà6@pq¸¼¹ƒÛ:DgÕáKm|ïj= 5îŒßÜÆwwûµIg ÕÕÐ%‡Eæ²îIÁÅájüŽ‹ÉeÝ5»tÔX݉€MÜ-B‚K;10yX\ÅÂqÈ;ÐO—çÀÛZ¶àÒáhØ  ¨J€ Àh]LŸŽûJ´# í ‚«Ø<›È Ï'm˜3bø°¹Hè0 .;f³É\±ÿÀáõsæÎÝduXÄB¢ElÂЮ(´g¸®!‚£(€À#FŒüxú¿JÚ.wL \f¨¼)möŽ;v(š±ƒÍkpB´¢-ApôlžÜº(ÍðáÃÇmúhÝ»fs‡B@p‘ 3ÒfÝ}üøñÝ@  Ç" œÇÀƒ(´'î<%–1‚Aç²ÎláÝ©"¾wßÛ€ãXÆl¢àÎSh…ÌS©.ßm¢` BÖý{íl„Ý ³îƒµïÍÄ2À¯Àb³^8Ïúg ½ÛŽCÏÀHÌÎ:󡺋n¿@ ¸¤˜M¦ò„¾Ió€Ó@OÁ6¦à:ÈèD[±¿»™›0è$Épi«—I&Óa¹X+p\”ÑÎLCGïCp_LbjQ 螘%ÀçÁvÃ`›tÄCp9 Î@ЭQÒb¯Ž‚`[:5¨hÃSØàuIš,.޶êúHGÜyî_vÙ%~/ƒ@ ¸´8>^àI Zy ¹uÙ݃L^B‚n£¸{àÐ-žÁÝœ¥£(ô˜Åo¾ÿ‘ŠÊJfÝ8¥Ré´­ªªš·þñO†̵“'v¨¼Ÿví¡ °éS¯Cãïßjûá£Ç9™i_Wû«‰‰Šdà€d$é—qØó Ù¾k}]å­"2"œ^ñ±]Å–õ(\íÕ=wjÚÑqgÇB$@ê)ÂW[~ ;'‡iS¯Cá"é™YìÞ€Òò ¦tP¶íÜÅCG?v4j7‚pèè1>ûê›VéÉIýxî‰ÇZ‰’'ÒÏd°kÏ>FÆ€¤${úº7a4¸sÞ­*§+äæ²þ“Í­Ò½¼¼¸iÚTn›3«Ãýt™.½›¤3O;º¤õIp÷2 CSS¸ÿ¾{éÓ+¡Õ¶Ž•ënKÚŸZİÁ©ü|ú ùÛÛüœ~†CG1zİ•ž“›Ëg_}CHh0’íé[~ø}s3wΛÓÉövK¦LœÀœY7RS[KzFnÜÌæ/¾Äh4°à®ù—±þ_i·ÝMrR?žxø4 Õµµ¼ü—78q*Oׯ½˜â=½áÌ#]}(é—á»^fjjk)-/ÇÇGE|\ ••|óýV¦Lš@uu 'OŸA«ñgܨ‘ÈåîuæÙl>JHpS&M°§ËårT*o†¤düè|ùí÷ró Ø¹gýû1(¥?` mª˜}Ó Îçæ³ÿÐ9N]]=×NžÈÎÝ{ihlÄd4±aã§„‡†2yÂX{§3²ÈÌ:‹JåMÊ€dÂBBìÛ6þß$%ö%48˜CGc6=rZÇããççCxXáaaôíÝ›ÁSxè±§øâ›ï˜výµD„‡ÐØØÄácÇ)..!::’¡©ƒìáÑö]{0ŒŒ9œ½RSSKêÀb¢"),ºÀÑ'‘{É;j8¾¾¾öºM&‡ž /?Ÿàà@ˆŸŸ¯Ûv^Mb¢£ø9ý KW¬äù§#IϬx™ìœóDGF^LÑ]²ÑÎ BK%=ÅA°áæ‚^^VɆO63vÔÆi_ß¾sù……ö|[~ØÆò%O´*¯®¶ž•yƒ²ò ^xúÉÖoÁ3CS“žÓ™h4õïfÈË+`Ã'›™uó `„¯·ü@vÎynúõõ‘± ¡£Ç8tôƒSúóé¾¢±± € Ÿl&5e“ÇÅl6óÚš·Ùº}—½z¥BÁ¢û0iœE0>þô3ÔþþT×ÔÐÔ¤`ýÆOyý¥h]EÁÃÛüb"#3r;÷ìåLfaaäðüÊÕ\()A’$Ìf3ÃRSYòØÃH’Ķ»9~ò|ø eåå( ®<‘-?nÃ`°ˆäÆÏ>çµ—V T*©¨¬bù««É:{Î^wNÇÒÅãá|uxöñ?±dù‹äœÏcéò•H’Ĺó¹„óôã^ ;ë”0´w‚  477³ô±GYò§‡ ÔpâT:YYNyÌf3kÞý'%¥eÜ1wIýú:mùµ7¹õî…ܾð÷deçƒBѱ¸{ê”køÃ½÷pï]óùtÝZ’úõ㽿½Ž.@‹ŸŸ/Ÿ®[ËsO>ÀÛ¶³uû.† į¼È¿[ˆÁhäïïý‹šº:{¹•U,¼ë^|æ)ú'õ£ªªšïÚÑ©c@~akÞ]Ë…’–þùÞû¯Œ1œƒGràðû>MMzÆū˟aʤ 477³}÷núýoyþ©ÅÄÆDSXTÌîýX»~YgÏqëÌ›ù몗¸iÚõ”UTð÷÷ÞïT[¯A,_òá¡ääæqî|.!ÁA,[²˜Ðàà+Þž. ‚¹‡üµ×c×m}zÇ3tð@† Mëá]p*oëölß½—!©I»á×­J3r8³nšÁ̦‘ÇÑ'yö¥WZµ«½u×–»KÛ±w îºè¨~5i>>\{ÍD’ûrﯠÈÚ/÷u´>j^^–{ÚüýühÒ7q*ý j2Ξå?_‹——å‚–“—çTÖ”IãéÝ+¹³ÒÐ0~ì(R$ó«‰ã(,º€Élb÷¾êtÌ»%Ȉpîž?]@ég2®ÚyÔÖŸ——¥ƒØ+ä  ÅE•ÙU„‡p™ÑXž7NéÛwí :2Âítâ„1£™;;ùsoaÅÒÇQ(œÎȤ²ªú’·ñÂ…B¦##"(¯¬r».À&\úÕÖP*&*’††&L&£‘¼‚Bò ‘$ãÇŒ">ƽk`­×ñœÀh2QYUES“žà@ûq•Éd„‡…`6w¿8·¢²Ê2äæItd$EE<³âe*<ûËI×ßtÔýŽí奭O¹nóôl‡<¿¹ã6V½ùÿùæ;ÆŽNR¿~Îù¾û¨|ˆŽ'û|.5Õ5ö °¦ºÆýOs8Ôe6›[•ivi‹V«¦ ¨ˆ‚ ÄÅD™• @Dh¨ç_pMsÅ¥žòŠ vìÙ‡V«¦_ï^øúú¢RyÓÜÜÌþ•ªõþúå©^µŸ?2™Œ¢âbLF2™ £Ñȹœ\‹wÒÍÎÛç_^M^~Ñ‘‘,[²€§—¯´Ž­¬bõ Ë®h{„‡ÐAòò ÉÍË·/555U^tTsÒnÂd2ñúš ×ë¶›LFL& ìÜ»Ÿs¹yhµj¢"#±Æ–!=#ƒý‡SZZæ´¿Zm¹ÇáØÉS45é1™LÖt5õõõœJ?c÷ZL൛_ÈþC‡9ùs:!ÁAôéßå>Ö74PRZFn^>[wìbñ3ÏÓÔ¤gÁüÛí3cGŽÄ`0°æÝµ465ÑÐØÈÁ#Ǻ\§\.§R"UU5üó߸P\̦Ͽ¤¡±‘QÆt¹ÜËEö¹âbY¶d1:­V˲%‹Iˆ‹%;çüoÏE¼ ±›IíeæÉe+œÖïœ7‡T딟O—/Ϯì§±{ï>²ÏçòÁ‡Ÿ°àÎÛì9WþÏ›Nõ©Õj]ôd2‰^ñ±¤$'qâçtžxv2™Œ  ë ¥ŽÔ”d‚ƒ9pè·/ü=\ø¦LÏ”Éxïƒõ<õü „ó÷×^áæé¿æð±œü9{Â^߃¿[ˆR©ðÐ/OýnÉóý¶í|¿m»=U£ÑðÈ¢ß3aì({ž;çÝBNn.?íÜÍŽÝ–0Êd2ñÆ+/ár]]/÷Çø¾»çóÜÊU|þõ·|þõ·ÄÇF³àÎÛÝ´õê²ùßï9¬YÚ¦ÓjXýÂsNiWŠ. B÷:¬—©S®¡¢ªu,—œØ.€¹³Óˆ‰ŠÄ ­Öú'%2wvqñ±˜ cÆÐ;!µZÌË‹‡ÝÇî}‘$‰Æ&=CRâë0_®T* aHê@|T*K¹’ÄÒŰsÏ>êêê”Ò£ÉÌÞ‘+˜__V½¸ŒÝ{öÓÔ¬§w¯xÌÀÓ®'!.–̳Ùê´M&”ÞJ–/}œÃÇNŸ_€N§#5%FcïÇ-7߈L&³¯1wv q±­Î…ÈÈpæÎN³¯«ýüˆ‰¦w¯ø–>XÑj5¬\¶”#ÇOŸ_ˆF£&!>–ˆð0§ã¥Ñ¨12//æÎNC£VÛˉ‹‰aîì4$%b¢££xmår;NiYQá ”‚\.ï1çmWq7GéøÜ‚í…(*,/\P[—Ñ™§O®¾R£Oâ€G€=XÞ¾\Ô8¿J­•{'1† ìˆY@`G * ;b A ØcÀŽCv„ ;bPQ عˆAE! Á"dvºì!äŸÏ¾”íÝ€. ¨ S.e;A7@„ ÀŽ@`G‚@ °#A Ø‚ ìAv„ ;B!ÀŽ@`ç"Þ˜ôËgÞ "LLòoµm[z-zƒ™IIþlÜ_ÉŒÁZ4>mëçáœzjLnËkâj'óÉ*nBí-£_„7ƒc}‘$ø×Ž * ÷½k\ yåÍœÈk`Þh]«>ªU^̬qJ?‘×è6?À¦UÄ+ïÓé~~Ùôh!»TϪ¯KÜn{åËbªd—èyzSûÏÖµ[Þ;[+œÊ{G‡Î5´¹Þ`æµoJ˜öjïýTFv±žm§ëxà_¼úU15MFjLÔ4˜Øu¦Ž÷VÙ×kLMp"¯u»+Ê^óC)o~WƸֆí.¿Mû+9˜]ßnÿ}ôhaú ïn+'¿¢™(ž~¾¬™¬b=× Ð ñ‘±û龫Û?T«oÀàðëè_«B)‡¡m\i—v¬â&¾|´aZ…Ó¶ÆfË´þqJ°=ííËø)½–§n k³-Ÿ®æíËØ°(žH¢Í¼-©±>Dé|²–»Æ·¸Îßž¨f|??4>2 F3ëöTpÏø {ÈPPÑÌO§k©o2“éÍ8|•2œk ¡ÉÈu)>;\EA¥NÕR\c`ú }¼ê?v¾ÏUñõŸ[‹€JÑ5nïÙzžÞXÈš1ô ÷n‡PYodûé:Êk ÷a`L‹ÈíȨ#Ä_ŽÞ`âโÕr®IV㣔ؕQÇé¢&z‡(™œìJ5èMlK¯£°²™Áq*†Äµü¦åG{+˜žªåHng šè¦dB¢?’õÇ›šMì8SGv©JÆ5ÉjB4Χó™¢&öfÖã«’¸n€†M*¹gB`‡êï©ôhA‹—°åDµ³ ¯å¶1èfÞø¶”´¡h|dį̀cÑÚ\&%© ò÷âëã5¬˜Nß0ovž®£¤ÆÀu)$ëÏfÊdr™äö•s;2ê–àëV ºJæ…&­Íã…9‘ŒêuiNðSùÜ÷^©±*|2^ýª„ßNâÁë-žËÎÓul^öïaZ}¼ñòj)gB¢F“™ U±Ùq¦µŒMªØt Š#9 (½à\©Þ¾Ox@Ëõ*!Dɸ¾~ì³vÚš˜W®çHNqÁ ­eïɪ'>Xi€„P¥Sß=ÕßÓéñÀôT-[NÔ2s˜–oW3k„ÖcÞ‡¦†à-—xò“BLF3óÇrÿµAxw!ÞïªäÓCUNi¶Á UÍ|´Ïý,€'$ V̉`þšx?ÿ]ƒÜñ2êBˆZ΃ׅ´Jß—ÙbèåÍ(åjŒ RPZãy*ÔÏ[æô^_¥e³5”ªn°ÌœäU´À‚IAN"àJD€‚ò:K»2ëx~s B•U6`ñ¶ +›ÛöTOG0c°š[ßÌ¡¸ÚÀ‘óõ¼qw´Ç¼þÞ2þ4=”‡®aGFK7á­¸ÿÚλšýXõU1[®m5àÖU”r‰·îŽfÖëçXþxvfÛ¡M{©åè fJk NFVZk`B¢_—Ë TåÍÂNaiáÖq‘G×ðÜÌp®h þçërÊ,Ƭ–SP®÷XNWëï ôø )BE¸VβO‹Û×u1»ÉzÕSÈ%®IögLo_ *šÝæõ–Ë(¬ô|MŽTqËHO~RÈA—ûjõ]Í}°ZΚ{¢Ùt ŠvVt¹°\•ゼ»­Üž–q¡‰“y Œï×uA˜š¢æƒÔ4ym~„‰‰þŽE9õÛFJ”ÊéÞÉá8*å3‡iéâMÞD¨ZÎü±:t~–Sòý•üîš`ÆôñCá%±`b iÃ[Æv¦¦¨‰Ô)QÈaê ¿„ÖWnŒ‘½|ÓǃúG«˜Ò_Í¡ìzîg™vl¯þ_:+^xá Ð[—fÀ˜¬‹[Ô݈“£Ø„@øjë2º¾®võ¥í•'·¬í8SpõøÃ?ó¹q¨†éƒÚŸ>ퟮfgf/͉h3Ÿ$At ²Í<¿|ýüö5Ö¥hÄY̸Cþ¾µ¼ýL‚«Bq­méµä–»Ÿi³ÙŒäàýpª†¸`e»ÿs•BbI;·…ÿ7Ó£aùì‹\>Næ5’6LË­#º´ÿ³›‹È)Õ“¡âhn=ý¼ygA ¹çiXAA÷eóCñµÿÅN·öTÄ´£@ °#A Ø‚ ìtV̸™ªÝŽ.Ùj{‚`vùtMÝO6Û¦ívÄCp,¨Í»œA·Á½¶k·  7Z@Ð}±Ùi§.âžîC0»YœÁ×ÏÿaÀPb¹½YŽE`l"#î.6·Ù¥ËmÉz ÷‚ິ¢#7&9Š­ÒCXžmðÁòœƒÒZ–B‚+£ ±Ø¦Ëó Xž]èÐMޏ3-ÆìèØ*mšh1|“5Í˺H1®6û´y6Ûl´~ÚÁæ)¸z­¢-Á]¨`3|›ÁÛÒ´xB‚+ƒëÛ2Ø<ÛcÏîB·t&d0`1x½CºÍc°y6AWGA°‰‚£0p~ܹMÚG—D²VΊä8˜èør@pyq7èo€f‡O›X´{£R{!ÖJ eªÑ1f±yB ‚«ƒ§™@ÛØ§Ù·t4d°‰€kÌ"Ä@ ¸ú¸GqhWl´eÀ’›OGãw'B‚+㈎ÂàúÝ5o+Ú3`É廫ñ»zB‚+ëT¢£7àîF$žBG Ø5'o@ˆ@põèèÃLm† 1bOy…ÝOß¡gºjÌB‚îx*Y @ ÁeáÿVâv\hïIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/images/spinbutton.png0000664000000000000000000001665715074673150024237 0ustar00rootroot‰PNG  IHDR5d级âsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timevie 09 dic 2022 09:12:29NôgMIDATxœíy\”ÕþÇß3à ˆlŠˆ¢€šænaV^Bͼ޼™eú³›–z»Öµ¬4MëfÛ­_×[?ÛÜ×(Ê}Ã}7\@öMT@Ù™ùý1Ì03ÌÀ3¢tÞ¼ž×Ìsžs¾ç|Ïú€@ @ @ ‚?,’Ħ@ h¾¨­iÌdΆ7@PæÄ¬Q"×Pá1N'±ðš@ ‹–ÚÂkQ_Á1%^’ZÞ74@Ð<1%`êZÞ›JW+õc±’èR£ssâ&Ʀ¨ŒÎã׉¥‚cJÈ´bfêÂ&LaJÐTfcÁÓOo; aÎ3“é½Ê€Ö€;à ØWÙ¢&ôѧ  (r[@eÕ¡Ò{ÕO+¡a«KÔŒMë‰i…Ìh øoÚ°nBPÿ~‘àŠZˆ˜@ ° jµJ}ë䩨µ&NÜ \î¢< Õ¦·:…­.ñ1nnê‹™h¼qÝš/%\|càn‡GŒŸw¸ ”£7­÷fª9ZƒÚDMßKÓzhvU‡pîß¿ÿ-ÖüŸZmQ3V jE‚¤bTĸ)ñññGB  °U`Ø×f„­.Q3å¡)Ðô™õ¼~íò:š@ °&’[;LâÑô¹i…Í”ÇV©9«FïµÂ¦mvz¬Yýýx„  «£výéûUcÑ <ÊÑèŽ Ã`Æ)«k‰“~³SŽÆCS]’®]^/×F—_ ŒP«T7ýºþHŠÑxlÚ>6ãjë 35â©7W‰DÝʺËP@ƒD*uEã4É10RǨ¥óÔŒEÍ•˜¶!l…Z8bØüÔNì¯K<5cQ³ÂI6FAµæè‹šö¨×@sMP™UŠ,æÑ×ã%˜f1å©™Ú:ÈXؤVÞ×M ŒÑ_ŽiNÐjxl–,“2µx]&4M Ø}A3µQ†Ỉš©ù úÂ& ¬Ä;Eœ=Ovî •J:øøÐ%Щ´®ž +WýR Ó§üÕ¢øé™™D9¦;w°wÀË˃~½z¢P(t÷šòòr6Gþª;—Je´õòÄ×LJ¾>MX2•1ÖSšT¯)ú‰õH‰pÔÏ‘ã'ù÷Êo)**2aò$ÂGý©ÎôwïÞå÷Ý{˜í¸xé2o/YÎâó‘H$¼³äC’’SðñönŒééL}E­:á¨5Š–Ž-8{†ßvîaè A´léh'!á «V¯cïÁC$§¦ ‘H˜úì$ÂG> ÀÆm‘Èå ÆŽ©;wjÙ’‚ÂBJKËX»yŸ/[‚‹‹³É]ßÏÆŸG*•2$8ÔPRZƺM[éЙá¡ZQ‹#ò÷øùúâÓ¢´¢–‘ÁºM[‘I¥¤¤¦‘RUÎí»÷"•Jyf¬FÔ~ßµ‡o\CEE….ûQO ç¥ç5}%þüÖlÜLî<d2 çÏ£Wgfçz…\AĨ|½ê®\exèPÊÊËYüáÇÄŸ¿ˆD"A­VãááÆG‹Þ¥•‹3 WX³a û!#+KgkØÐbââ¸u;€×mdÙ{oãçë‹Z­æ³¯W²?úˆ^Þrþ6ý2ØÔÇݬy÷¿óÖûœ’ÆÛï/G"‘p=%Oww¾1ÏZQ/qþyÑ5ПÞ={PZZÆÊU?0eæ+|ôù—¤¦gÔˆëîîÆ.åõÙ/#·³ã§õu?6Sܺϴç&óÁ; x¨k ùùì9xÈ Î¯;vóÌ”iL˜2{öáÚª•ÅýPíÚ¶åË—0°_¶­ùž áÌ›õ2!ƒ4žæ'˳å§U€fpâ›VãÞº5Ëß[Èûo½‰›«+Q;wwþ‚Îniiƒ‚ûó¯÷ßáÉaaTVVµÃ¢2iéàÛ^—'À–È(âÏ_dBD8k¾ýšç&N 77-¿D¤óôpcù{ yñ9Mó{ÏÁhF=ù8.z‡Aý)--Óy§{D³?úýz÷ä‹>`ÖŒiTTVòŸU?Rx÷n½ÊÛpkÝš÷ßz“¶mžîî÷¼< 5µøkÔŸD*aáüy¼1wþ¨¬¬äð±¼:ÑGéâ „7ƒ3x`0eåå\¾zMw]ÿóP*• J×.ŒñYYÙñ:û1.|cÇŒ¤ßÞäݼÉܾMÁB0a×Ð9ªQ×ø.P#üØÉÓTVV26|$èþPÆGŒàLü9ëÃC‡Ò¹“Ï>3€Œì,“õgî{(•iæ…·lÙ5jbãâÍàÂÏQ¿Wݤ¤¥Ø êß—À€NŒñ¸î‡øxØPüýxú©ÑUeÑÔá¡ã'xṿàÓ®-=úƒ‚ûQTTÄ•ªÏåö'“Ù¡WžËíäÈåòFÙl(ÂSkB$ ú÷cù¢…|µb9C¡R©Øe6MOM¿ÍíBóžš>®­4}iÚþ2-þ™8>‚IOeÁß_£K€?Å%%Ä»`ÊL£ÈÎÉÀCÏlçÝ€›·n›Lãää„T*¥²¢ÒäusdTyhí½ÛèF–³²³IËÈäÆÍ[<2h@Í&­®U*µÑyUfg×¼ï¶U÷S‹Ý\¹u;_ÓüLMÃÇÛoo2²²xgɇµ¶(lEÃw¬}jV¥­—“Ÿ™Àác'É/(4û$ÄkIÉxºyXöXsqŒ¶Ø èäG•«š¼«º0 ÍÛ©:W«Õ¦¿ ªêp—ªAŠÌÌlúô|€«×’ðöò¬µ\µÞ›Ñ{•JÅ/Ûw"‘HêÛÔàååEjz&#†=Fïž=jÚ1õ´IãëFù¹¸8‘‘•EFf6ÚûÜO[OOÓõÑŒYüá ÒÒ3ðñöfÑ[óXøþrÒ22X¼ücV,]tOË#<µ&"3+‡%ÊÎ}û9wñ§cϲjõZºÄý}÷^’RR‰‹'þüœœœèÐÙ”Y‹Q¡F¥RQQQÁ¥Ë—9~:©TJ·.8µhÒÁ̬>Ê嫉\H¸lÞÙÉ €+×’ÈÏ/¤²Ê‹q© ?{–òòrzv€Í¿DqáÒe’®'³g4R©” ~}|åäÞÈ#3+‡Ó±gy{É2“’y<ôQºø08¨?߯]Oîùê?€Æ“Ô·ãÔ²Á}{s"æ /¼ò*C‡ âÕÿ™ÆÐ!ƒØ¾gk6nfÝæ­|µb=ºuä'øeûN,^ €T*eʤgèX•_Ý.SÍó´ô ¦¿:O*“ɘ06œ OÖÅ LÜù ì?t„é¯ÎC.—S^^ÎÿL}Ž'‡‡Õ«Î´aOAlÜ9Î_¼Äì¼ hšË³gLC¡›°Ó¼Ùºz•Þ™æÞ]]œY±ô=ƒ°{EƒEíõ±YŸ!éÝ«ç/&{#©D‚·7÷è†T*5¨ß©Ïþ{{•ôìÑï6mtן~jŒA|ãs777&ŽÀ¯ƒ/jÀÛ» ÇGèlˤRÜÝZÓ½[W<ÜÝté&==–.IKË cG_:ùùûN¼½«óþÇœY=q’Ü7éXe?À¿Ÿ,[Ll\<ö { {ÔÀÔ¿N"dÈ@._¹†B!§[×@Úµm«³2hýüpvvÒ…M÷JGeïš\npö >ÞÞtöë€kÕ*]‰„Ù3_âOO ãZÒu@M§éàÛ5Ð%П‰ã#èì§K3Œƒƒ¦ìJ%ÇGà…½‚÷ß~ƒØ¸s¤§gàêêJ¯Ýpvv¿‹ûSó?ô×yj7…t@³a›SÕ1ðjÂù÷ªT"£¶óÝšõÌš1°¡Cšº8Á=Å¿K÷¹À14O•*Š€ ·õ®áÚ‹‚QßEˆ>µûšÚú™)ÄCˆïcÂGŽ |䈦.†@ð@! A³Bô© ‚f…èSÍ ±¢@ 4+„¨ ‚f…(ÍŠF Y÷¢ù)š öÔÒS’¬Y@ ° µ!ÃHHÍçTR!9ù”WŠ&éýˆ\&ÁÃIF°¿ >Îu'`µLjo\±É%8·rÅ­‰äþzr^iI1öʦ.дeQ«Õ—”ðëÙ[ô¹YBXOËX,<ˆ4XÔRó‰M.Á³M[tv$ÀSŽ£âþµü[¸¸ÞžIS–¥¨LÍålN$Ú“œ‰[!휚¤,­ið@Á©¤Bœ[¹ÜII/Å}'h‚jz··'¸“çV®œ¸úÇ{8ˆàCƒE-'¿{%žrk–G`C½Ø;(É-¬¨;²@ð€Ò`Q+¯T#‘Hp´³B$ eb@GÐ|Š$šBÔA³Â&¢6{îßmaV êDlç-¨•JEzr"¹9Y”—•Z”F¡°Çݳ í:tB*Kõl=„¨=@ ÿÓ(vÿuÏòLON¤¸¸ˆ~‡â ´lòpIq—Î!=9‘ö~þ6.aó@Ô³õ°©¼ÅçŸNLLŒ-³؈9YtéÞË ґ®=zs#'Ëäõ}¢Y»a“Ék1gβï@tƒÊjK²srˆüÕvÿLlUÏÇOœ4ËÊÎfã–mìÚ³»EEºðã'N²e[¤I;IÉɬ۸¹Îò¤¦¥|®–ÔYdÔo\¾r¥NÛõÁf¢–››Ë#<¢E‹8~ü8¡¡¡,]ºÔVÙ lDYY)JÇz§sP:Rf¦µ÷À~>ûò+víÙWãZÌ™3ì=°¿ÞùÙš±ìãO¸sçŽMìÛªžž8¡;Oº~)Ófp-1‘˜³gÉϯž„]^Qο>ûœü‚‚v¶Fþ•«Wë,Kjj*k7lÔ[Rg‘Q¿qé²uEÍfÍÏ×_???6mÚ„D"!::š°°0ÂÃÃéÑ£‡­²< ôìÑOÿý%ƒÓ¢E‹¦.N<=.‚áÃÂhÙ²eS¥ÁìÚ³~}{óÆßçÖ¸6 (¥RÉá£Çùä×<Äüysê_SÕ™M<µòòrÖ¯_Ï‚ t‹ÜCBB eåÊ•¶ÈRð€1hàz>ܯ¿ù¶ÖxkÖo #3Swž——ǪÒ?uš«×¹xéë6nfמ}• R©8~â$kÖoàÈÑc5ì–””°wÿAÖnØDüùó×~þõWòòò8w޵ë7’–žAzF&;ví1ˆwçÎöìÛÏÆÍ[¹˜€J¥jHUÜ9©˜RÓ2øæ»ïk45år9¡!p ú°AøÅ„îÔ¯/·oßfûîÝü¸v;w若¬Ìlž¦ê¬´´”}¢Y³~qñç¬tw†ØDÔ ‘ÉdôíÛ× ü±ÇãÜ9Û܈àÁcîìYü¾s7—.›³zÝÒõD-÷FßýP-j'Nœäosæññçÿ&-=oV}ÇÌW_e櫯±iÛϤ¦gðÎ’¥¬øâߺ4yyyL>“Ýûö’“Ío¿Ëÿýð£îú¶È(Þzo1‹>XÆ™øs”••ÖhZ%%§0ùÅ—ømç.®$&òÎâ%¤¤¥Y«j¬ŽT"‰fE‰L&C*«ùÓÊñ“')-­nÎî?MXÈ#ÈårÊËËy~úLŒ&11‰Ï¾üŠf̤̌°×Y~~>/Îü?­[GJZ:ï-]ÆÅK V¿W›4?KJJðòòªÞ¦MRSSm‘e£¹}ûvƒÒµjÕÊÊ%©å¬ïõ{9*j <ÜÝ™>õy–ü ß~ýeƒ§%ôèþ°€Ü7z"óç¾FDøúôìÉ»K–òÊŒé( ¾þï·t àÝ·ÿ Àا™Äk³^4ÞÜ–u«uuRPXÈèq8Ëàê,Ãw?­ÆÓÃ}°©TÊÝâb&?ÿ¢•î°›xj*•ŠÊÊÊár¹;;1‹DPÍÓã"P£fËÏ¿4؆S‹ê>wwü:vD¦÷=Ü•JEÉÚ¢e ¢¶ï jûο€\.#5-]—f`p°Y‘-(,äTL,c«D³¹`ggGhH£oôæ­[ô×kqI¥RT*IÉ)$&^Ç»Mrrr,²øè1"ÆŒÖÕk ¥7·ÖÖ¿«[”J%ÙÙÙ¨Õjƒ#³³³ñññ±E–ÆWC1çq5Å<5[#•JycÞ\fÏ{°GC¬bÓÑQ‰ZïÁ@J úYA…wîp÷Î]2³ª§BüeâD<==,²Ÿž‘L&ÃÅùþثϚ ,Œ…‹—ð¦JÅþƒ }t¨#²výF¶DþL€¿?^^^—”Xl;;'·ÖÖ1cl"j-[¶¤¼¼œ£G2xð`]øáÇéÕ«—-²<ÀtíȈ'ç³/¿Â·}{Ë %Å–ÿp,¡m›6úóìÄg”¾e‹–TVVrûöíû꟡5èß·gãÏq ú3§¿¤»–œšÊÿ~ó-[Ö®ÆÝÝ € /Zl»µ«+™YYt¨›u m„MšŸööö„‡‡³dÉ݈P\\Û·ogÆŒ¶ÈRð€3cÚ‹Äž‰ãäéÓá^žž?Y=´¨¸¸Ñy… aã–­“OëCÛ6^´vue› 'ã62™Œ°¡!lؼ™Ì¬lú÷é­»vãF { ™åPP 7M"1Ùí¤¥ŸÞlز•Š Í~~eees嬅Í:¸>ùä†΀èÙ³'‘‘‘,_¾œ€€[e)x€i¡T2wö,Þ\ø Ó…O|z‹?XNIq) œŒmt^ÏNšÈ騦L›Î°ÐPÊ*ÊIJJæÓ–Y”ÞÎÎŽ¹³_aÑ˹–˜ˆ‡»§ccy÷­âסC£Ë×Ô ,ŒWæÌ#bÌhd2™.ü¡®]híêÊô—gѯoÎÆÇsóæMÝõîu#¿ €/¾úšñcŸªa÷Å©S˜9{S§Ï¤wïžÄÅŸ£ðÎ]«—ßf¢Ö¡CN:Å®]»ÈÎÎfΜ9bÒíˆBaOIqQ½g»—¡PØ›¼öØ£¡¸šh¶…=¼ٳpww×…=9|íÛy»›ó^›Í柫çXQRlèq…I×ÀêžvvvL›:E×ÖB©ä?û”ã'O’x=GÆŽ©îôe }ûöLzf‚î|øcaøûwætL,eeå¼ú·—éèëkIÕ˜ÄVõì¨tÐQjAXßÞ½˜þÂó„5ìãT*•|ÿ߯ٽo?••Œçv~ŽUK»\œùnå×ÄÄžA*•Ö¨³6^^üðÍJ=JaA!ãÂÇwóÎNÖœkêÁ’ªCŠFôä€à8Uß]¿¢­/Ó‡Öì,=÷ï|¾â_V-hCÈ¿uWÛwLZ‚5Êb‚• ÈLKá~ÅO¾v™’’bºöèmñN»ÐÚÁÁ‘…gn ¢žkâØ¢å\àPXu%@9P¨uÕ¡C̯x€hŠQO¯v¾d¥'s,ÚìCc {\Ý=ðj×¾îÈ@Ô³5¢&¨¼ÛûáÑÆµ…6H4s …m ׌õl=l"j÷CÓS`= …øáÜD=[±]¦@ hVQÍŠ‹š\&A­VST&ž!ù p·T…Z­B!35è-4ê+jÚáSµ‡“ŒÒ’.g›ßOIpq%§‚Ò’<œeuGš5&¦lÔE]¢¦6zÕ…û»PXp‹‰ÅœI-Û}LQ™š3©¥œH¼KÁí[û7¯õŠ‚fK Ý1n€%£Ÿú†TU‡:ÐÇ™>7KˆIÎä`‰+Ç•;rÜ”–”cïPsÏõ¦ )Ë¢V«)-)¦àö-úvt$ S“”C ¨'š£V+–NéÐ7^YuÖÓ·BN\Í''+òJá­ÝÈe&tEXtCreation Timevie 09 dic 2022 09:22:14\È2ãôIDATxœíytÕ¨¿ªêM½iG ’e[Æ6xlj!dx™³:^Ø^€†7ä?’ylð`ÂdÂ#¶@H!C!aŒ±Ûò¾ÈX–µï­Þ»«êýÑj¹ÕjI-©ÛS²îÇ)zqõ½·Uõõïnu @ @ “ i‚¤)LôL&– ‘†JCH*˜, %å¸d«@ÉŸ“Òü7àT"Y>=ÍK‹ÑŠ“JBi˜çcÍG 0:©DÔ‡yžêsÃ2i’¥“69éõP’ §É"&nZÒëäýG$]qR —2Õ&œê¤SbK7ñóCbJ£CEJ%áQ €"À XûÒr NU%‹!À´]€Ú·i ‰Ÿ•AБäL3ãBš'0ãÍ_½vÍÒ%‹× ‘.dL2$t]Ó»>ߺýÕkÖ¬ù5pðWâ„ qIGt$‰’«±‰Rš‚¥K—.{ãµWž“$rÇüÅ‚Sº/[}Õ555Û€N BLÒx4MUÍÄpr&FÍxÄ4õmÀ½dÉ’óÞúÕ+?×õ´ªÇÁ¤ABŠ~cõ•7íÚµk3Ð „‰ e`[†t$9SEL ±6åü£µ_1‚ÔH]S«Ïø°‹X›4.hª:y¨T“žÇWg‹_yù¥«b NTU% ðyñy=ôzzèõôàóöðy …‚hš:ÊTõü_¾ôâÄ:JÍÄüQ8’CÉ‘¦Þ%VgÍÄ"f0ëËÚƒ¯K?ÊÒ †"‰ÑôôÄ“e«Õ†ÉlIk]Ó:§1û›À @,‚ÆÛ ÉD®­˜ª‡6.i¾$éy™æ+œ<4M% Ž.jšF àG…ȱۑå¡*Ÿ1$YÎ'ÄÌ ì’¡Ç6ÝqÎd9íhb¸D01‰FUBA?š®¼óhšŠßë%Çžƒ¢˜‡ÙS—;«µñ‰:Ã’NäL–ÓXDÐLDT5J àËHZ::~¿Ÿœ'ŠInW 'ÜI”3¾ªC(ÎPUÛaK"]ÓüO7ð¡kÃFáDo’§¸IªÈ™ê’¯dAå _W*d`Цgþ¼ÕÑ ýäØCí’8Ýu(1EÐt¦ï¥šä®7‰h4‚:ÊΟѠFU¢‘(&SJ¥ÅLuaHJ†’3Õ8L¢ “ª3Èëõ³s÷.ZÚÚ±çäPUQÁ¬™3Fì©KÅŸ>ü+ÛvÔp×m߯år©m*óæœ Àî}ûÙ½w?+W,ãøñFÚ::ñù|´µwòù;ؾc>ŸŸ‹¿rE…@ìĨٵ‡ŽŽN¦L©dfõ4ìv{ùÚÚ;غ}²,sÎ’Åäæº‡ü.G¥%%”–”pFu5 çÍåÞ\Çïÿø—^r1e¥%ƒ!¶×좵µŠŠrÎ^0IŠîŸl!UY±l ŸnÛFo¯—óæRyz9MÍ-ìܽ“bâÜåK”SÓ4¶ïÜÍñ†ŠŠ X8o‡=e9³¦¦×Ö¬(/ãÀáZ[ÿ,ëÖÞ ’Ä?ÿË©«?Nyiišy¥ŒÐcòe´ržÈäÔœ8ûzß¶nßÁÞÿ3¬XÓyâ¤ÊɱñÚ›¿¡¬´„•çÄä|÷½÷ùð¿>æ¬Ù3™wÖ:~ÿŸâÓ­Ûøúª¯òѦÍlýbç-[Êá#_²µOÎ/vÖðÅÎÎ=‹¢‚ö<ÈþåYº{<ýùÝwçí\¸ò<<½^îºÿ»„Ãa^yã-žùÁcƒbõšÊòrV,[ʦ-Ÿrðp-e%%olä‘'ÖÓÒÖ†$IèºÎâ ø?ÿx’$ñѦÍìÚ³—_¾þ&˜Íf.þÊüé/FøõÛï°áa±XèêîáÑ'×S{ähÞ…ùù<ôàýLR9Æ#3:4-½“õÁ{ïâ±§6PßÐÈcëŸE’àØñFŠ xðÞ;ÓJC×µáÜ•¤£ïјDÌž9ƒ…óç …yáÅ_pÓÿÀžyŽú†FJŠ‹©ª¬ ©¹…ž>‰vîÞ‹$Iì?x˜@0ÀÞ©ž6ü¼× |ý¢¯rÇ-ÿ€[n¼žß¾ò³gÎ$²áùŸáéõr÷ÿº•]ÿC¾»ö-\ÐÿYI’¸åÆëyü{ë˜uF5==>Üøñ¨¾_Uåé445ðüÏ_¢¥­‡þ÷Z~ñÂsœ³t ÛvîdëöýŸ …¬\±œ'ý>]x>‘H„›7sïwnã‘u2¥²‚¦æV6¾€—^}Ú#G¹öŠËyî©pÙ¥—ÐÑÕÅO_üŨÊ:.Òœ TŸÇºûï¥ô´bêcb°îþ{úk3#f5ŽYGÉŒYN}ü'Éß{ð~¾»önfÎ˜ŽªªlÚò÷>¸Ž›· £³lÉÙì;tˆãMttv²ê‚óÐ4šÝ{9ÖЈÇãaéÙ Ð~Rãy¤ú›©«£©¹…s–žÍª WRZzË—œËéèÿŒËéà’Uræì3¸ô’‹hjiôN¤=ø˜)J¬ãÂép ‡Ø»ÿ .§“CGŽðî{ï£(±úºãǤuÑ…+©ž>5W® /7•ç.gîœ3YuA,²75· é›?ÛJA~>ß¼z5åe¥Ütý7ÉÏËcÿÁC'ñH¦I1a6Ÿ˜Žg2›0›†›ž7i¹DDÎ$‰åKóÄÃßã'ëŸà¼s–¢io½ý.Ë–,`ÿƒÔìÞ‹Ýnçºk¯F–evìÚ;ýX²haÚy6·´pZQQZûÇ#²žfõ-NcS•§—„Ð4¨ªr¼±‰ãMH’ÌÊË™Z™ºú™—×W…ÖßË@Õ4º{z…Âô·[eY¦´¤= “†"ž÷Ht{<<úÔÓÔ74R^ZJyi)Í-­<¾þYº=ž‘E^é0ö &A›3™²’n¸ö6mùœO/èP]5•‚ü|öT¾.‡Y–inmES5dYFUUŽÖÕÇ¢öI:‡$IFgäN¡=ó¯445S^Zʺîà±'Ÿ¡±¹™nø ?ôÝ´òÊÔ÷‘sšš[yì©§yÿ/e÷¾ýlÛ¾“_~€3gžÄ~)—-^Dí—GÙ½og/˜ÀòÅ‹hniåómÛYºhῨ.—€š={ …ÂhšFõ´*l6+[·ïä£O6Ùè^ߨç…úÚÚ;¨?ÞÀ_?þ„¿ÿ¡P˜›¯¿®¿gõÜeˈF£<ÿó—†B‚A¶í¨sž&“‰³fÏ¢§§—ÿ÷òk´´¶òÖ;  ²|ñ¢1§;Z”ÁãŽ)9z¬žªÊ Ö=pyn7yn7븇ªÊ êê§——’9¥Æ±öÏ©:ÕÖòÅŽšþÕ8S**¸å¦ëˆÿ –-^Ä{|H4eÑü¹€ÎÒÅ xéÕ× ƒ,>{ƒÃ\,ô,˜{&E…lýb×Ýúî¼õÛ\táJn½ñzžÿù/xú¹Ÿöç{×mßæâ¯\P’tBgìõŸ?ÚÈŸ?ÚØÿ®Ûífí]ßéŠíó÷ß¼šºúzþkÓf>Þü)yöGSQ^6¨ìé,n~ûM×óŸxŠwÞ{ŸwÞ{€©S*¸ùï¯ãdC&“B$2r^/¿ðl«Øþyn?ôà€÷†CV”´öK‡1Ëyê« çŸw ÌeϾ´µw KååÌ›{&²,÷ÿ æž5›5W­Æn³QP”—•qã·®%3Ιýûž¿bÕÓ¦áv»Ð»§þùa6oùœP$Lõô©èÀª ÏçÌY³Ø³o½>奥œ½`:põå‡I91½¹ä´bÖ\µšê©UƒŽKyy)k®ZÝÿÚåp0¥²‚êéSɱÙìŸ›ëæ‰‡bÇ®Ý444áv»˜6u e¥%è)Ê.+ k®ZÛåêO§ª²’5W­fÎìYè@EÅélxâQ¶×좽£‹ÓËJY8.&“éäC²Œ$Ë#]9’l”çÅxIU×JœG¿¸ÚFì‚QWßvÎá{Ög¨ AÖQÕ(ᾡ­la±ÙP”ÁñnƬ9k-ÄVáëü@Ë• ZèKt &ŠlB’ôQ/Ò•²¬ È¦Œz!Úœ‚IƒÕj% daGÂlµi'Do­`Ò If‹mäG‰ÕfC–2¯’èL*dEÆb³ …ǵÀ€„„Åju6e¨|‰ˆ6§`Ò!K ‹H$ˆ:Æ\YV°X¬±ñë,¹ Úœ‚I‰$ƒÅjCUU¢‘HÚQT–dÌfsßx&dÓq"Á¤FQEAï›W¬ièzÿÕ%’$ƒ$¡(r_ïÉ»”YÈ)’,cÚPÙDt eBBO ›+Ž ‚~Æ9Ž}™Ér‚$Æ,çòó/Êd9A¢Z+!§@`P„œAr EÈ)!§@`P„œAr EÈ)!§@`P„œAr EÈ)!§@`P„œAr EÈ)!§@`P„œAr EÈ)!§@`P„œA™°72êé½PЮëY¸•ø`$IŽÝ•ʤ`w¸pç`·;²žïDeÓ!ÿ±±…íµÝxaBápì.^YF’$ÌŠBU‰“Û¾VÉÕË ³žg6˜prz:;èìlGFpåPZ^ÅjÃl1 G‡‚x<Ýôvub²Xq¸\‘W×u4UCU£~<]˜ÌfN+«Àév;ýS…w¶wñÈ›Gèò†°ÛÝØÅäåZP3RîäUî ãïj¤Óä’…§qѼ"*‹í”æYhîQßæçƒ]í<ý»C¼ü—:®XQÉ;ï“Iª› J}›LL^3`쀫o;Çïó®?Y…PU•æãuý~JÊ+É+,ŠÝUxt]§»£æÆãØN,6[F#¬®ë„ƒ|^/v‡“Ó«¦!ì6r'“@DcÍ3ûÙW×Mna vWÁˆÇh4(’D…¥™Ú†.š«W”£Œp¿LUÓyã“Fžzû0³Nw³áæÙ¸mʰŸÉ4v‡s-°èíÛü@ˆQ@#vã¾'ç„3ÑxìKÌ+•UÕ wNUU©?Z‹âp:3~ûB]×éíéFªªg¢˜&\…dÜ4tF¸âÉ|…ÂÒJ$9³8,:&oåù6Ü<‡mtco0ʽÿ¾›¦îOÝtg”Ú2Z¾á«œ†ÿ™WU•Æc_âp¸©š>sÔbBìîÅS«gb·Ûñy{3úk±6Ž;/Y‘©«=xRÚUF"ѸâÉBØ(*¯Ê¸˜Š$aòÖ±|†›î˜?j1œ6ÿvç–UçòÀK{é ¨-c60¼œMõu˜-VÊ*«ÆVYåT“™P(˜’ ÆáÊEgòÝmÍ3ûñEòŠËI]æfÊó-BnaIÆ«²qü]¬½l:›B¦Î§M᾿­æOŒ}Œ +gOw'Ñh„Ü‚BtŒnyE„CaT5š•²[m9DÂ_VÒ7 xcÃ%®‚¬¤ éð¹êœ²ŒŸל[FkOˆ·>ëÈJÙ3aåìloÅ›ŸñÎèëÀÉÍ' e<íxú«žÎά¤o~¹©»Ã•cà÷yøúÂâ‡KÆ‚"K\² ˜ûиÑÓ°r†ƒA\î\2U•IÞ\¹n"áìÈ `±Yø²×¶5;j»±9r³–~ÈßËWç’­s`Õ¼BŽ6·oÀ°rjšŽÅjÍZú‹ UËNµ@‘ÍD£‘¬¥o¼&“%ké«‘0UÅ9YK¿ªØN8jÜa/–ë(Š™lM™5™ÌhjöŒ¬È¨šñÇÒÆC(Íê„‹¨¥ÐeÉÚ9Pì¶d|BJ&1läÌN+æ'å ùÈOâSÕ²…®ÇÿgL +§D£a²ÕÞˆFBcšm”.šª¢(®˜d‹Å„Í^Ó@6™hí ‘­s µ'˜µÎ¬L`X9%Y" g-ýp8Œ,eONUËn•ϸíÖ¾Ðì`2™9ÖžÙ\ÇÚƒ˜M'wüh0¬œK½žîŒoÅ7oO7Š%{òD‚!ìNgÖÒ7 §çðe¯·Ójsðá®ö¬®igZ‰q¯Ç5¬œyùEôötgå"j]×ñxz°˜³Ó¬¡Pˆ¼¼‰y‘oºÜt~ oOÖ.tÏqäòþÎvT-óéGUvµsóªòŒ§) +gnA>ŠÉLOg;™nktwµc6›1™ÍY){(àÇl1c³Û³’¾QXq†ƒ—_ov&[˜,VŠÜVÞÜÜD¦Ï767Rì¶rÕ2ã^€mX9EÁ™›KkKj‡ÜÝÁ5»-¬^RÄšÅØÿzÐOéÕ÷QU €·§_oj$‚Fߨrº®£ª*áp$ ›Õš‘ª¦$K(² ÅdÂîp’—_xÊ—Œ‡Í‡}üÇÇ­l?Ü…Ç&Žd¦Ê«kèѾi}&+2ħáI’&Efêivn\YÄå‹‹Èɱý·µ1Ç*ç„«ƒ)Š‚ËéÄa·.,"UÑt ½¯-*É2²$c2)X,–I×þ3+f8X1c2MӇçì90áäŒ#Ë26ÛÉ[{T`CEI!¦@#݉îÃVmG#ÔPû )‚Ô %_ZskÇ*–R âJ.@ @ †ÿ›7Q;cçMIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/images/togglebutton.png0000664000000000000000000001631115074673150024532 0ustar00rootroot‰PNG  IHDRd¬tsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timevie 09 dic 2022 08:49:27ÚI)IDATxœíy|TÕÙÇ¿w&“d’™$“•„ì I‚(ˆl"»(¾jëRikµ¾µ¥VEܨҾµ¾õ­­…ZA‘U"–€aËdOÈ>3ï³d&™I&$p¾|îgrϽ÷œsŸáþæ9ÏY.@ @  O õ‘<AÏ£ïÎ̺Cìå!DF èØ•.‰Mg åu’ƒÇAï¡¥xè<æ}ðm‰ˆÔÆß-G ô,¶„D߯߶®k“Ž<ô-EC²Ød-ö퉌@ è=´ËM×b¿åùíâèƒoKPL¢bk#ônl ‹ÎÎÖRx,¯·‹“•°ç©È->å€7à x.Ƽ…¸½K‘hêJà*Ph›ÎâÓòZ‰v¦=qi),&ÏÄ$(N€ ˆþ|횆§ { z!&AŸBB¯×éËÒýô\ä×0D³À˜D¦]iOZ6ƒ,EEx>|ĺ5«?$<;}c × ‡ò³æü*33óP 4b“7c«™ÔжÄÅÒk1y,NÆÍðHIIýÅÚÕëõ5¯AABjš:ë¾Ç²²²U@iÂ:v¦=q±å±8cˆ©$;›³„Ç"ÜœHeáQ1Yb2&±åÁ´Bf/×›ÆÔò[½jå„°71zÍVþk6†Ž†ç_ŽuO0ØqRÚºoÙR`ðX”@lÞÙœÏ$Ðt¹þ ×¢×éJ#bâþ 8 Ôbð`L1˜–^+ÚŠ•Øê!2‰ŒF’ô^Ý;ÍI ô6$™LƒÁ‰P`Ø•ÑN‘£ã\ZŠ‹:ÑÝ,Üüè%À ëf‘i l›8â¹´'ÀY8-Á-ƒ3ÍϾ¥¸˜¶tMØkÉ»¥Ê /`ùÜ·œâc[ž‹­%Z Œ¬›×•½Ëé>ö„¥•ãÈð[“åB[‚[Ka±51Ù&öÄÅV?¶¥ÀÜÁÜ/·n§¶¶Öîñ±œ˜p]ê²ï@*……Ü;y"*U»ç766²~Óf󾓓C'áåéÑ“UíVvìþ†²òr$IÂÇÛ›þýˆ‰F&k¯U/è&Z>û¶´¡C]Ñ–[f"Ò­à¸|¹e;%¥¥vß7s:I×I\¾ýþ‡Ó3¸ãö‘¨—†ÆF>ý|C«t¹\ÎoŸ{†‘ÃS*·¢¢’õ_~EXhãïcNÏÎÉå@ê!n1Œ„¸8Ço¤ƒlÛ¹‡¼óç[¥‡†óô“; ÇʘéÔ:M™Ý"íæ——% ‡Nk#´jí¤¦æÙ_Íc@d$jµšëo‡6犵8ÂÃBøãë‹))+cãWÛØ¾kkÖo`äða•V]Sͦm;9<™ñwÝiN?ñ"›¶íÀÏß—„¸ØN܇£îcù[Kpqq¦°ð2_ïÙË¡#Gyõí?ò×w߯×Ç»Ëï;Ìzè1Æ à¥ùÏâáaðN+««Yö§÷9~2›Ÿ®ìJööV¡´Kg'ÞÍ¢þæ¿Õjwüü îßêÜ¢+œÌΦ®®ž1‘ÄDEY¯ºvôŒcTTV3$1žüÂ"jjk?¶ùÍÎÉ%çÌh¼¼HŒeÇ3š??»uÌ;S§sQ891$)?_«ã …‚~þþ<2÷>¶ïÚƒ¶Ik>¾}çnÊ+«˜;{2™ŒüÂBöøØè(¢¢"غc—ò‹X³~#I ñ¸8;“–žÀÑŒ,®]«aÂ]cÌy[¶Ø •¦&-£F¤pèH:å• NL ,4¸Í¿nnnô $%yï½ÿ7öHå“5Ÿ3ÿ™_´kìÜ3d?Áý3§sôØqò ˆcPÂ@*««É8–EeU)CÓ/  Cßmo!$¸?§²sxåwxýåH’Äâ7–‘wþÁAA]ɺSÏ{GÅ¥¹›ßq±ÆÖÊ¢F¶íÜÍ??YMSS“9mê¤ üüñŸp1¿€Wß\FIY2™ ggÂÃB?Æ .ÿçS6mÝn¾^íîNÕµkÄÇ À×B\,ÊÿdÍZ¾øj«!Y¯ÇÕÅ…—_ü ƒâm®zš‘u€;F4§mݹ‡ /1gúTd —.²æó ̘2 ?_¶˜Ä¥ €5Ÿo@.“á¡VsØ(.éÇ2I?–ÉÄx|½½ÛµÅ·ß$ëÄIV¯[ÏÕâÀÐT[´à…¶ãW-ì>wöLöH%çL®Cö8}:—Õk¿`ï¾™ó?æNÒ33)+¯0汎·_{…ˆÐP ýï¶7ñêï_dáÒ·8á¯,}I’8wá"þ¾¾,úý ÝñÌvHdDD¬‹äò¯Â×Û›w^[ÄÒ…/á£Ñ°åë]dž0<Ì+V}JIYÌšÁ_ß}‹éS&S[WgÎ#÷ìY6mÝN€ŸË–,fé—pUº¶Yîñ“٬ߴ…¡IƒXù·¿°táK446²bõ«óÎ]¸ÈÜÇæ1÷±y,ÿëßÉdDG„;toýùཷ™’ÌÆÕ+y`Ö &ǯž|€'}„«W7`€C¶¨¯o`ÔˆÞ]º˜ÉãÇ¡ÕjÙ´e‡Cuj®[?œœœ¸|¥­Vë°=üý|xçµE<ùè#ìÞ·Ÿ©“'²lÉbFO¡¾¾Áì­9z?½oo–.|‰À~þœ¿x‰s.âçëÃ’… ð÷õ½îõé´¸èo±öî;5íZ­–Ù3îe@L$ ñ±Ì™5 €Œ¬ãhuZ2²Nà¬Ppÿìéô dÎÌ©V¹¥Ëàî±wAB|,#’‡Z•ײüô,Ã5..Îlݹ›ã§N¡R©81ßê/Oî›1•ûfLeÂ]cÉd,}÷O¤Ë´™oó¾ušå¾åy–×¶g Ëë&Ü5†¨È™{—‹:dw$ƒèêêŠL.sØÃS’É´{&š¸‰ãÆÁý3§ërÙáûémÿär'œÎf»)œ(Š.åÙYÄ"O]äò•«øù4Ç:úb5¥eå”WT Õj‰ ÅY¡°™Gq‰¡G**2Âárkjj(+¯@.7 ˜NJhõ ÀËÓ“çÌ2ï{¨Õ¬ß´™CéG:xÃå9B{¶°…Z­F&“YÅ¡¸¤”††" ÍGía‰FãÉ•âbtúæ}VÛéû¹‘”•W°èw¸”_`ޱ\*(`ñËX²p¯ë»BJçÅåV‹¹˜hÑö÷4Ž),¼ÌÐ$ÃÃzælAþx¨ OqI :­Î06£E<Ä4îäò•«¶_EÕ2~¢‡~Æ oB\,?yðþö¯1eè骬¨ÄèPUU·Fc}E>z½Þfž–éíÙÂÖ}´ª·=Zœÿ¥1>5"yHÇìa¯\6ëÐýô^_¶Ü,,K.`ÑÒw¸TPÀëï¼Çò7—\×úˆ˜KIJˆ`ýW[8™CÞ¹óìÞ»™LÆðaÉ8991 :šòŠJ>ùl—¯\açž½Vy$ 4ŒÙðÕ²ss9›wŽc-Úôr〱rcàqDJ2r¹œ­_ïâdv/åsñR¾uõzt::Ž‹ù…|m,;ÞX¦ŸŸ¡iðå–휻p‘ÔÃG¬.÷P«È=›GEEZ㯺Zmk“yâ$õõ ètºvmÑ®–”r¥¸˜ã§²ùÛ?V°eûN‚û1sꔎ٣ôäýôyçÎjðR<=Ñxz²dá"ÂBÉ;áº×§ Í¢^&Û× ëŸ¸Ä±L¿g_mÿš—_0Ä{h.á¡Á€ž'y×Þy›·±qó6”J¥U~ƒã¹cÔm|wð^zõ ‹s åÅÇÅòÃát½¹Œ'}„{'ÞÍ“>ÄÇŸ¬áå×ßD¡PÐØØÈè‘·ñâ³O™ë˜wá"s~ú3«;}Ûp¦Lè™:qé™lÚ¶ƒMÛvhÕ «G­rgDò¥gð³_?ǘѣxî©y Nˆ¯7‡Ó3xxÞS<=ï Æ½£][´ïBØæ7¿_hµûˆæ=þärò"þíØ£­rl».Ž|·½‰ «þe±g¨›ÆÓƒåo¾f•v½°Õµd9Ôß´~‹+†5ÔÆmä™Ó'–_¯Jö§gpöÜyîsG«±$g~Ì#'÷,ÎÎ Æ °#†AzF&H1Ñ‘¼ðÒ"'%°xÁ‹€¡y‘~,‹üüÂÃCùþà!v~ó-o½ú2±1ÑèõzRÓÒ)..&1>Žˆð0ÀД:™Cuu5!!ÁDE„¡V©hll4wË‚aè¼—§'QaDE„[ÕíÜù d?‰¯¯7#†%³c×7ô dHR":Žƒ‡Ò¸Z\JxX(CºŒ«®]ã`jõ $%ÄÜ®-öø‚¢"¦LgèµnÃ&”nJ¦MžØÊ®_ïÞKY…Á[“Ëdöó',$”àþ­Îm˧sÏ‘u‚aC’ˆ6ƶvïÝGqi³¦Þƒ‹‹ µuulÚº_ƽÃáïöf':6áy ÃBÝU@ P‡õŠt­~-„¸Ü²Nœbñ›Ë˜2ñn»ã%¾þ'³sXùá_Œ#‚CgÅEt¯µµµìO=Äð!ƒ©­¯ã?Ÿ}`h·íxèÈQ4žžôëçOjÚNfç7 µJ-l-蓈˜Ëu çìY>üç >4îK’Äô)“’ÉŽ·l#;'×|Ÿ¯Oýì§; ú*oeÍ"à :.ñú6‹Äï©@ h s=‚ˆ¹‚AŒÐ=‚@Ð#ˆ€®@ èºÐò"ì#šE Gè´ç’!¯;ë!n2:-.·Ý9€êÊrJНPWS‹N×±ÕÄÍÈdr”J%Þ~¨<[1LؾûèŒýmÓ¥e.¯PYVJ`h8*µ§yyAAÇÑjµTWUR”žºÚ|ÚžÖ1ï 5ÕÕ¸(•¸©THÒ-ñ¶—C¯×£mj"ÿbî*‚Ã"ot•ú<—êÊr*ËJ‰ŽOÂÉI,ÅÛUär9ž^T*5¹'3qUºÙý­®,§¦º7µZˆJ7!IN r''®UVR]Y!<˜.Òé€nIñCÃ…°t3r''ú…„SzõŠÝsJНà¢T aé$IÂY©lÓþÇè´2ÔÕÖà®ò0,Ð,èVTjòϱ{¼®¶7w±€TOáääDmuÕ®FŸ§Óž‹N«1–B.—£Õéì×iuÂkéA$IjÓþÇã\A ÄE ôB\AÐŮ̶钸ˆŽ"@`>HeÏÞo9û〡 ÐßߟѣFâåÙw0ÕÔÔòåæÍÜ3i"/¯]‡IMKçÂ¥K€Áö> Ƀ™_ÕÚÛ)+«àTnÅ%¥2tð ы֋¸á1—Ý{÷²ïûï©©­åjq1k?_Ïô9p,+ËáeeåV韭ûœcÇww•­ÊÝøÕff?ø_ÆòËz¬¬žà`Z‡fPWWOiY[wîæ©ù¿ã´Å+NÚC§Ó±bÕ**­Ç…lýzÙ¹öÇêt•ßìãÅW^eïwÉ;?øKßý3:Ñ…Ük¸áž ÀÐÁƒyî™§ÍûÏ/x‰¬XÉûï½ëpŸ®]ÇœY3Ñhš=‡]ß|ƒÂÙ™Á‰‰ÝZ_€ú†žøÅ/Q(œyuáøÍot{׃øØ<úÐæý·ÿô>ë6mfá‹óÌAbóŽ]Lºû.<=šö8t…BA\Lt÷VØH`€?ï-]Œ—ÑSÌ/(ä……¯‘‘u‚äÁƒz¤LAÇèÝÖ/>,™í;wšÓöì݇§‡šaÉCÍç¬ødS§LÆÏ×—­ü7k×—§'?yèAöîÿŽ¢ËWØà%%%Œ7–ÈÃ;‚Ë++ùá‡4ÊÊËHJL$~`œ9ßÒã­ÑÐÔ¤åXV&nnnŒwînnVµvqVð‡ßý–ÄøFwÜÖËÕû‰ñÙàó~jZ:*w7ã›m´á«­Œ½ãv¼5^|±i3ÛvíA­R1óÞÉü~”’’2gdRV^Á¨)„ô ªºšcY'©¨ª".&’(ãwpìøI¼<cæÔ{P*•ÝZoAçéÝAññüü‰ÇÍûO>þ÷?ü_nÞÂÃÎí¶r ‹ŠpvvF­²îj 2»ù¶psw»igˆŠdîìf±}`æ4þûw/³{ï~¦M™Ômå— P(ZÅ®üü(¯¨´{«Òµ]ÛðÑ <=<˜5uJ·ÔUÐ=tÑsÑwÃÖ:/µÊ¡IIääz$I2þ’¶¼®­ýÖyûh4444PRZbu^iY™Ñ¥·]ŸÎÞG÷ØåúâîæÆÀØŠ®âY’$ÙŒ7uO)«¨°J¯¨¬ÄßÏ·Óù®Ý°‰Ü³g™ÿôÏ‘ÉÄ—ÞD¯kaìÄ…K‰Ž2tcøû“š–f>^__VÛ<žA’$ —¯X/ðãâìb•æïïGHpV¯YkNË;wŽìœÓÜ6<¥§n§O¡Óé)(ºLXH¾ÞÞdd0ohh´K"I†xÅ¥¥Vù8+œ).iNóñÖàÏæm_›Ó.pöÜ9w2N²yÇ.vìþ†E ^0wI z½¢Yt,3‹þï#jëjÉÈÈÄÇÇ—é÷ÞÀÌéSù|ãFž}á·„…sè°uÏ‘$IŒ1œeËÿ‡qcÇpïä‰D„‡sûÈüsÅ¿©«¯gèàÁŒ½s4 ^˜Ï‚—ñã¹<øvßw<÷ôÓøûù]÷ûî œÊ9êu_PWWϩӹh¼¼¸{ÌhÆß5†í»¿áõ?þ‰ ~dž8eu½$I ”ÀG+W1rø0ÆŽIpPÉI‰¬ûr3õÄÇ`Dò~þøOøãÿü/ó ðõñ!íÈQ{h.>šŽ÷ð|wð+WFRb<;÷|kNW©Ü¹oú½]°ˆ »°µÚ“d±ÉŒç8 ÀŸÿrÞ“ý‚º\I’P©TÈårär9þþþL›r?{ô§ÈdÇÊÃÃ{&LD¯×ãëëÇSóžd@t4QQ‘¸ÛðcÇ܉ÊÝggg¢"#Q¹«”@DD8MDEFàëëKÿ  &Oœ€““/O/æ=þ8£nauû!ÁA„…†Y¤HDGFà`ÿ>€ä!Cpµ1&£3\½\€ŸEº‹/âÒ åHÈpwS"—ÉËdøz{3nÌíÜ?cšÙöj•;wŽ èÑxixèþÙ„‡†ŒRi¨Ãˆ”dÜÝ”8+œ ÆÝÍ1Q„ôBÛØDXH¼5üý¸óöÛPÈðP«y`ö †&Y p”$üèhQG‰ðþøúøXÕ½¤¬”~þøz{ãäädÞ”J%¢º¾¸vC}]ûßj¼ñæ›;€K@ƒqkšq³ÙŽ·ÕHµ“¨¸n€Ú¸:­¶#å ÚA«mâra>j·Ýs¼ý¨¯¯½i'SÞHôzõµuxûûßèªô&l,vb3Ý G<ËŒÌ#òÔžž¸«=ù1ç•ååâõ—]D«ÓQY^Æ9ÙxxjP{Ø_ \åቻʃšª*…Ètz½žÆÆ®UU£R{ R÷â¯VϾEZ›8s±Ì\ h dNΔ_¡ðÒ9±8rÉd¸ººáåã‡JíB¡hóüà°Hª++(½z…škUè´Âö]A&—¡tu'8-…Ä–¨qú6¶ÞÓ£³ñwËs[ÑžH-þn)$-½!.A߯ÞK¸lí·<ß GÄ å9ö¼!,ÁÍ£ÛluDì+DE ¸9±'Í-ê¬0An-ÄÔ{@ @ ‚^Àÿh­n!®_IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/scale.rst0000664000000000000000000000016615074673150021664 0ustar00rootroot.. currentmodule:: gi.repository Scale ===== A :class:`Gtk.Scale` is a slider control used to select a numeric value.././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/spinbutton.rst0000664000000000000000000000313615074673150023002 0ustar00rootroot.. currentmodule:: gi.repository SpinButton ========== A :class:`Gtk.SpinButton` is an ideal way to allow the user to set the value of some attribute. Rather than having to directly type a number into a :class:`Gtk.Entry`, :class:`Gtk.SpinButton` allows the user to click on one of two arrows to increment or decrement the displayed value. A value can still be typed in, with the bonus that it can be checked to ensure it is in a given range. The main properties of a :class:`Gtk.SpinButton` are set through :class:`Gtk.Adjustment`. To change the value that :class:`Gtk.SpinButton` is showing, use :attr:`Gtk.SpinButton.props.value`. The value entered can either be an integer or float, depending on your requirements, use :meth:`Gtk.SpinButton.get_value_as_int` or :meth:`Gtk.SpinButton.get_value`, respectively. When you allow the displaying of float values in the spin button, you may wish to adjust the number of decimal spaces displayed by calling :attr:`Gtk.SpinButton.props.digits`. By default, :class:`Gtk.SpinButton` accepts textual data. If you wish to limit this to numerical values only, set :attr:`Gtk.SpinButton.props.numeric` to ``True``. We can also adjust the update policy of :class:`Gtk.SpinButton`. There are two options here; by default the spin button updates the value even if the data entered is invalid. Alternatively, we can set the policy to only update when the value entered is valid by changing :attr:`Gtk.SpinButton.props.update_policy` to :attr:`Gtk.SpinButtonUpdatePolicy.IF_VALID`. Example ^^^^^^^ .. image:: images/spinbutton.png .. literalinclude:: examples/spinbutton.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls/switch.rst0000664000000000000000000000107215074673150022073 0ustar00rootroot.. currentmodule:: gi.repository Switch ====== A :class:`Gtk.Switch` is a widget that has two states: on or off. The user can control which state should be active by clicking the empty area, or by dragging the handle. You shouldn't use the ``activate`` signal on the Gtk.Switch which is an action signal and emitting it causes the switch to animate. Applications should never connect to this signal, but use the ``notify::active`` signal, see the example here below. Example ^^^^^^^ .. image:: images/switch.png .. literalinclude:: examples/switch.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/controls.rst0000664000000000000000000000051215074673150020570 0ustar00rootrootControls ======== Learn how to use the most basic interactive UI elements from GTK, such as entries, buttons and switches. .. toctree:: :maxdepth: 1 :caption: Contents controls/entries controls/buttons controls/check-radio-buttons controls/spinbutton controls/switch controls/dropdown controls/scale ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/examples/label.py0000664000000000000000000000640615074673150024563 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class LabelWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Label Demo") box = Gtk.Box(spacing=10) self.set_child(box) box_left = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) box_left.props.hexpand = True box_left.props.homogeneous = True box_right = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) box.append(box_left) box.append(box_right) label = Gtk.Label(label="This is a normal label") box_left.append(label) label = Gtk.Label(label="This is a normal label with xalign set to 0") label.props.xalign = 0 box_left.append(label) label = Gtk.Label() label.props.label = "This is a left-justified label.\nWith multiple lines." label.props.justify = Gtk.Justification.LEFT box_left.append(label) label = Gtk.Label( label="This is a right-justified label.\nWith multiple lines." ) label.props.justify = Gtk.Justification.RIGHT box_left.append(label) label = Gtk.Label( label="This is an example of a line-wrapped label. It " "should not be taking up the entire " "width allocated to it, but automatically " "wraps the words to fit.\n" " It supports multiple paragraphs correctly, " "and correctly adds " "many extra spaces. " ) label.props.wrap = True label.props.max_width_chars = 32 box_right.append(label) label = Gtk.Label( label="This is an example of a line-wrapped, filled label. " "It should be taking " "up the entire width allocated to it. " "Here is a sentence to prove " "my point. Here is another sentence. " "Here comes the sun, do de do de do.\n" " This is a new paragraph.\n" " This is another newer, longer, better " "paragraph. It is coming to an end, " "unfortunately." ) label.props.wrap = True label.props.justify = Gtk.Justification.FILL label.props.max_width_chars = 32 box_right.append(label) label = Gtk.Label() label.set_markup( "Text can be small, big, " "bold, italic and even point to " 'somewhere in the internets.' ) label.props.wrap = True label.props.max_width_chars = 48 box_left.append(label) label = Gtk.Label.new_with_mnemonic( "_Press Alt + P to select button to the right" ) box_left.append(label) label.props.selectable = True button = Gtk.Button(label="Click at your own risk") label.props.mnemonic_widget = button box_right.append(button) def on_activate(app): win = LabelWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/examples/picture.py0000664000000000000000000000175715074673150025163 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class PictureWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Picture Demo") # Let's set a windows size so pictures don't start at their default size self.set_default_size(500, 400) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) self.set_child(box) label = Gtk.Label(label="Here we can see some nice pictures:") box.append(label) picture = Gtk.Picture.new_for_filename("../images/spinner_ext.png") box.append(picture) cover_picture = Gtk.Picture.new_for_filename("../images/spinner_ext.png") cover_picture.props.content_fit = Gtk.ContentFit.COVER box.append(cover_picture) def on_activate(app): win = PictureWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/examples/progressbar.py0000664000000000000000000000422715074673150026034 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk, GLib class ProgressBarWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="ProgressBar Demo") vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) self.set_child(vbox) self.progressbar = Gtk.ProgressBar() vbox.append(self.progressbar) button = Gtk.CheckButton(label="Show text") button.connect("toggled", self.on_show_text_toggled) vbox.append(button) button = Gtk.CheckButton(label="Activity mode") button.connect("toggled", self.on_activity_mode_toggled) vbox.append(button) button = Gtk.CheckButton(label="Right to Left") button.connect("toggled", self.on_right_to_left_toggled) vbox.append(button) self.timeout_id = GLib.timeout_add(50, self.on_timeout) self.activity_mode = False def on_show_text_toggled(self, button): show_text = button.props.active text = "some text" if show_text else None self.progressbar.props.text = text self.progressbar.props.show_text = show_text def on_activity_mode_toggled(self, button): self.activity_mode = button.props.active if self.activity_mode: self.progressbar.pulse() else: self.progressbar.props.fraction = 0.0 def on_right_to_left_toggled(self, button): value = button.props.active self.progressbar.props.inverted = value def on_timeout(self): """Update value on the progress bar.""" if self.activity_mode: self.progressbar.pulse() else: new_value = self.progressbar.props.fraction + 0.01 if new_value > 1: new_value = 0 self.progressbar.props.fraction = new_value # As this is a timeout function, return True so that it # continues to get called return True def on_activate(app): win = ProgressBarWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/examples/spinner.py0000664000000000000000000000176515074673150025165 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class SpinnerAnimation(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Spinner Demo") button = Gtk.ToggleButton(label="Start Spinning") button.connect("toggled", self.on_button_toggled) button.props.active = False self.spinner = Gtk.Spinner() box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, homogeneous=True) box.append(button) box.append(self.spinner) self.set_child(box) def on_button_toggled(self, button): if button.props.active: self.spinner.start() button.set_label("Stop Spinning") else: self.spinner.stop() button.set_label("Start Spinning") def on_activate(app): win = SpinnerAnimation(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/examples/spinner_ext.py0000664000000000000000000000573315074673150026044 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk, GLib class SpinnerAnimation(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Spinner Demo") main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) self.set_child(main_box) self.spinner = Gtk.Spinner() main_box.append(self.spinner) self.label = Gtk.Label() main_box.append(self.label) self.entry = Gtk.Entry() self.entry.props.text = "10" main_box.append(self.entry) self.button_start = Gtk.Button(label="Start timer") self.button_start.connect("clicked", self.on_button_start_clicked) main_box.append(self.button_start) self.button_stop = Gtk.Button(label="Stop timer") self.button_stop.props.sensitive = False self.button_stop.connect("clicked", self.on_button_stop_clicked) main_box.append(self.button_stop) self.timeout_id = None self.connect("unrealize", self.on_window_destroy) def on_button_start_clicked(self, _widget): """Handles 'clicked' event of button_start.""" self.start_timer() def on_button_stop_clicked(self, _widget): """Handles 'clicked' event of button_stop.""" self.stop_timer("Stopped from button") def on_window_destroy(self, _widget): """Handles unrealize event of main window.""" # Ensure the timeout function is stopped if self.timeout_id: GLib.source_remove(self.timeout_id) self.timeout_id = None def on_timeout(self): """A timeout function. Return True to stop it. This is not a precise timer since next timeout is recalculated based on the current time. """ self.counter -= 1 if self.counter <= 0: self.stop_timer("Reached time out") return False self.label.props.label = f"Remaining: {int(self.counter / 4)!s}" return True def start_timer(self): """Start the timer.""" self.button_start.props.sensitive = False self.button_stop.props.sensitive = True # time out will check every 250 milliseconds (1/4 of a second) self.counter = 4 * int(self.entry.props.text) self.label.props.label = f"Remaining: {int(self.counter / 4)!s}" self.spinner.start() self.timeout_id = GLib.timeout_add(250, self.on_timeout) def stop_timer(self, label_text): """Stop the timer.""" if self.timeout_id: GLib.source_remove(self.timeout_id) self.timeout_id = None self.spinner.stop() self.button_start.props.sensitive = True self.button_stop.props.sensitive = False self.label.props.label = label_text def on_activate(app): win = SpinnerAnimation(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/image.rst0000664000000000000000000000144015074673150023121 0ustar00rootroot.. currentmodule:: gi.repository Image ===== :class:`Gtk.Image` is a widget to display images. Various kinds of object can be displayed as an image. Most typically, you would load a :class:`Gdk.Texture` from a file, using the convenience function :meth:`Gtk.Image.new_from_file`, or :meth:`Gtk.Image.new_from_icon_name`. :class:`Gtk.Image` displays its image as an icon, with a size that is determined by the application. See :doc:`/tutorials/gtk4/display-widgets/picture` if you want to show an image at is actual size. Sometimes an application will want to avoid depending on external data files, such as image files. See the documentation of :class:`Gio.Resource` inside GIO, for details. In this case, :attr:`Gtk.Image.props.resource` and :meth:`Gtk.Image.new_from_resource`, should be used. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/images/label.png0000664000000000000000000014607415074673150024354 0ustar00rootroot‰PNG  IHDRìjA!¤sBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timedom 18 dic 2022 14:24:56àô IDATxœìÝy\TÕûÀñ ˈ"†  .©‰»©ˆä–Š©i– j*fän¤¹öSÓ´\Ê-#Å̾-fšû‚ûWÜ*·ú*‹€;Š€lÃï`†Ùíy¿^÷…sïÜsŸûÜ3ãárÎ= „B!„B!„B!„B!„B!„B!„B!þõ¬Š±¼¢.[!„Bˆ’,GÇ¿-bI£ÚJã§æ6i° !„Bˆ“´7Ôs4~šÄœFµfc\ýµú¿­Í H!„Bˆg”2ï§zÃ]³¯«Q¯“) vÍ;êÖj?µ5ÔmL D!„Bˆg\vÞO͆»RËzõŸz•2òàÚî¢[küÛZc½ÜaB!„ÿ&6{½P:G™c%ÏnB!„°œœ+ 4»Ãä/zí¨­Án¥å§zc=1<ªB!„"Ÿz[Z³»úÏÍl}ƒN5ﮫw1f°ªB!„â1õ¶´æ¢³óŠ®.1VÿVo¼ç=“]î¯ !„Ba‚ü¹ÔéšíîBl]]b4g7µÍ[ìT‹´×…B!„0…Ú¢>ë© ŸÅ^¨ÑnhЩB-ÆM™ÁÕèhÂ׬¤\™2&ïß/à=Ê•)Ëše‹ÍŽ¡_À{([µLg|VVV8W¬ˆ{•*tjÿ*¾­[™}L!„OžÙ v¹Á.„:¦¤3qÿ¢ˆAŸV-±¶¶">1‘óýÅÙ?þ òØ ¦Lø Ž,„âI°à»4Ù…ÿf9j?Kb“=wÝè÷†Rºti®üóó>ÿ’c'ÿËžƒéøªo[!ž?½ü‡P¯îK|4~,åÊ•àÁÇ,\²Œ?þºÈOëŸh<Ò%F!ŠØƒˆØògΟçÎÝ$Ê—/Kë–-Ø÷-ìlmUïKKOç³/VpúÜT(_ŽžÝºÒ¥c;ÕöGéé|»i 'þEJZ*/שÃð¡yÁÅŬ¸j׬ÉýXº2„]»÷«솎Ó? ïÍq°wàØÉSX[[óz玴hÞ”µë¿åò?W©ä\‘÷‡ ¦~Ý:(•J~øùW>Ê­;w¨êîŽÿ[oÒ¬IC3³*„ONµªî\¸x™Ÿ,`δÉXYY1ë“…\Ž¡ª›ÛÇüÇ3æÈ"‹,²ü‹—|Z¶ÙÙÚsâT/T®Œw‹WPf+ùù×ílùqký“““¹qã¼^æÆÍ[¬ ]ÇÉS§Uïùlér~Û¹›:/Õ¢EÓ&D=Ǽϖ¢ÌVŒA×¶–ÍšoÒqö<ÌésPÕÝ{II„oúžq“§“‘™‰³Sbbãøü‹dddB¬û– ›ÀÆÆ†& ð¿«×˜³p]¸üô¯,²È"‹åã)“¨âZ™è˜8fÌ]ÀŒ¹ ¸CåJ•˜9e¢ùe›Iî° !Dsp°gíò¥ª× ‰75ñCN=Ë€>½Uë*T`᜙X[[³ïÐa¾XµšßvíᕦM¸é3çh֤nj =#ƒ#ÇOŸ˜hö…BB¡ -íÙÙÙÄ\¿nÔqK³rѧX[[³qËØüŸŸéøª/£Þ `lðGÄ^çz|eË”açž}T«ê΢Oþví;ÀŠ5_ó㯿ñrÝ—ÌŠ]!žçŠ™;ý#¦ÏOtl.•œ™=}2•+UzâñX0èÔ‚_„⹑£õûðâå+lû}7Wþþ÷“““Còƒ‡Þk[ªVÖVäCëV¯ðåWkˆ‹'‡â®ÇpêôYz R ìä‡ËÑ÷}œ£_FF=Âõ¬m¬>޵µ*Ö—jÖÀÊÆJµ½vÍšÄ^çÁÃdîÜ»‡R©¤IÃXÛX“Cm¼[²bÍ×Ä^¿.ÿ!ž 66¥°³µS½¶-e‹­­íSù“;ìBQÄâ™õÉB*WvaLà0ªVu'ðƒ‰z÷IÏÈ ”Mî×r™¼GE6kÒˆ€Aý ¼×’»;çþü‹œœªW{ÑìãX[îMicóxÝ£Géd+³UëÒÓ3°²²ÂÁÞÞìØ…âI¹—tŸ™Ÿ, îz¼ê/qññÌúd!³§OÆ©Bù'ù v¹A"„Zû%^ºô7™™4kܯ—ë¡T*ÉÉÉyüþ<22ÈÈÈÄÎÖ–3gΓ““C5w7ÈÝݰ¶¶æòå¿)W¦,e5ŸõžWŽ2G©ÿûX-¾„Ä›|ýMÖÖÖôíÝÓ¤ãú·®u9Pͽ ÿ:Ëàþ}±³µ%êÌYrrrðx±šüÿ!„(ñæ,\¬j¬Ïž>€™sÏœ‹X­q}áví;Àßÿ»JVVV¡}ö8D³Æ iÙ¼)W¯Å þÝÙåµöDÇÄqü¿§p}Á…þoõâ庵Uï>d•œØy„ÿl݆ë .ÔªQƒœ%VVV Ð5aáìØ³Ÿ& P¯NíBñ<|kkkÜ\_à•&y«W÷¼Æúã8 ç1#o±“Cð# ‹ØLÔ™sœ:{–:µk1Ä¿n®/è(G!JŽ7¬S{•ûåT¾‹çý_uOŠ•–uÖyK)À6oQä-¥2@Ë¿/ýiþ|ÚB!„BüËÔªSpx¤iyKfÞ’(óóŸÃ.„B!„(v2èT!„BˆLú° !„BQ‚I—!„B!J0 f:B!„B7éÃ.„B!D &}Ø…B!„(Á¤»B!„%˜4Ø…B!„(ÁdЩB!„%˜ƒN¥É.„B!Dq“.1B!„B”`fßa¿sµ(ãB!„Bhavƒ½¥oÇ¢ŒC!„B¡…t‰B!„¢“»B!„%˜4Ø…B!„(Á¤Á.„B¥ÏÀA´jÛAçK@àH~Ùö›Î2ü‡ ã› M>¶¹ûý›º–P*•,úr]zô¢ß !\½vÍì²4ã”km¾ŒŒ Zµí@ÜõøBÛL­–Ös÷Ÿ1{K—¯P½NÏÈàÑ£GO4†¢*_ßõ(Jæ?‡]!Äs',t (•DlÞÂɨS,þt¾j»B¡0XFÛ6>Ôyé%“mî~¢xlýí7NEacØZ¬¬­)W¶l‘•-×Z¨[¾ØëqÌ™9ãi‡RbIƒ]!„Š£ZƒÜÎÞkM*cÄ{ïšuls÷Å#&&Ž—ëÔÁÙÙ¹ÈË–k-„i¤Á.„ÂdQQgøië6®^»FU77& ¢QC/ ÷OÈoöìÁÝ^àØ‰„„®ãjt4•œ+Ò¡];F/T¦9ûeff²rõ"áæ­;¼PÙ…€Áïеs§å¶këËC‡µÆ«YÞWkÖ²gÿ¥§Ó¶M‚F¢tiBÃÖ³ÿà!Ö¯ ÁÆÆ†ÔÔGô<„ÀátéØÑ¨8|Û´æPä¢c£ñôðäÃñã8}ö?oý•›7oÒ¬YS¦O¤B… ª}ºvîÄî}ûøçŸÿQÝÃàqc©W·®Öë¢/~MJ¥’ðˆMlÛ¾ƒ»÷’hØÀ‹àqPÅÕ•O?_ÌÏ¿n`û®]Ôðð üë5&å]Íkmè™r^ùfÍùeŽRu×6##ƒ7úôçõ.ù`ÔÒÒÒèÔ½'ß…‡1ýã9ô}»7¿mÿ¿.\`ÞÜÙ4mÔШëªïÚnèܲ³³Y½v¿ïÙCjJ*­[µ2*ÇÆ^£ÃGñÝfnÞ¼ÅËõê&33³Ðû’“2yÚLz¼Þ•­[6³ð“9´µÁòÝÏÖÖ–ªîî,˜;‡akéÖÕ9ó[à}ÇOœdò„qã]ôår¢cãX²ŠoBCˆgEHC ;+‹Í?üÀšu_S«f ºûùÇOE1õÉlÙ¸w·* Á›7X´`ëÖ„w=ž•kÖØgëöŒù>›¾]Oƒúõ3!˜‡jÍ›¾ø5…†}ÃÞý˜?ûÿX¿æ+ìlm=n"™™™L™4}ûЭKïÝU ±nJÞM¡ï™r^ù|}Zs*êŒêõ™óçÉÌÌäÐáÈÇëΣª›înn,þr]º¼FÈŠe4òªoôyºFú¶:·•!k8zâ$ŸÍ›ËúÐÆ5–ýÖíÛÌýxáëB©Xщ‘AãUýÉÍÉ»©ÞñïOÀ;ƒx­C;ïÝU¨±nÌw¾ï#}õÜæ^KIƒ]!„ÉztëJ½:uprªÀþܹ{—¸ë× ½ïÖí[dfeÑÚ»%eË–¡†§§Î»Ãæî÷V¯žÔðôÄÝÍ!àVÅ•¿.\,ð¿Î¨óRm½ñ¦¤¦ò˯Û>t0NN¨ìâBàðDr@“'N$t]GŽã·ßw15x’ÉqÔ®U‹ŠNN ìלœöë‡[•*¼X­*=ºúqîÜùûôéÝ‹†^^¸TªDÐèQTt*Ï®={ åÁPüê222ØøÝf¦LO͹1Ïš:…””>ªçʘ–wSèºF¦œ—:ï–-xœÌÕèhŽ?ÉþܾsظÜkòÔiZ{?¾C8lÝýü¨U³FŸ§¡k¤k»¡sKÏÈ`Ë?ñQðj׬IWWÆmtN‰½WnÔ¬á‰[•*L›Œ••{ö0;ïE͘ï]ßGEQÏÕYz=,!]b„BX¤Š«+ …‚ÔÔ´BÛ<ªW§YãÆ €·7otï¦úÓ³>¦ì—””ÄÎÝ{9ûÇÜ¿Ÿ»÷牺â‰E©T2eæ,¬° +;‹ÔÔÇwJ7j@§Ž˜4u:3§N¦R¥Çý»MÃã:ÒÓUë<=«“šV8ù¬­­iPß‹˜¸¸BÛŒ‰?ßõ„D²²² üT(Ô¯ÿ2×b¢u_©çk õkdÊy©stt¤i£FœŠ:ƒgõê=~‚ÏæÍåâåË9vœ~o÷æä©(‚FTícoogñyê»FšÛ [|BÙJ%uj×Vío¥÷¬-‹ÝÎÎŽF ¼ˆŽŽ1;ïEÍÔïõºSõ\¥×ÃÒ`Ba1+«­ë­­­Y¶äs¢ÎœeÛöL™6“fM›°ð“9zË3v¿ÔÔG¼;r Ú¾Ê𡃩ü ŒžlV¼esŸ‚òõW+©èä¤s_ww7”J%övÿnNÚþ£·2â¿kkì ÿÞØø23ÒQ*•dggcmýøív¶¶ØÛÛŒÁܼ›"ÿ:¯ŒŒ Úûu+°nÕKhØÀ+·[Ìé(|}¼!GIUw7^õmÃö;ñëÔ‘ø„7l 3sÏS×5ÒÜnèÜ232P*•(•Ê×ÉæÆngk‹­­­Iõ©8™ó’_wŒ­ç99Ú¿¿4Yr=,%]b„B»¦1ã£É¬Y¹Œƒ‘‡¹uûv‘ìwñò%’îßgôˆ@<=¢ó=×bbßÁ£FðùÒ/Tý‹2M))©^ÿyñžfşϽjî Â3çw¿Q*•\¼t™Zžž÷/ÎóÕdè¼ììì8¼wW¥aƒÜ‡¾>­‰:sŽ£ÇOàãí»ÎÛ›óþÁ¡#Gy¥YSJ•Ò}ïÒØó4ttm7tnªë¤ÑMÊF_#µÆjNN]¸H Oñµ¬¬,½ÛÍù1¦ž+D_‹1*FK®‡¥¤Á.„¢ØfäûÌýt!þC‡Qɹ"=^ïJ)µk§™SS®GQÒö©´Î[J¶y‹"o) ”Z¦¦<\\ìщ"×gà bãtOŸûÝ·ëùxμÏÇÕä?d];¿ÆàL:¶¹û=¯4ŸClì6SËzû !Ї|6K>C×H®¡PWÚ±Ìà8ðHÒò–̼% Pæ-*r‡ý_F¦B!„x¶Hƒý_F¦B!„x¶Hƒ]hõ,M;®y }Ó[š¢8 pd¡©©[6ofò”â–NÛmNžöôÒB!„(Ò`ZåOóëZùB¾^ÇÔYóÓæˆƒhàñ”ÁA£GÑ©cnݾEºÚ$ º»ŸúÔÊöööìÞ·Ÿ9óðr½ºT¯VMkÙùÓ[Wvq){hØ7>z”ù³ÿ{–­ aô¸‰|¦:·Å_.#hÌ(‚ÆŒ¢ªûã$ùSŠ;;;³tù †Ž Ÿ·X´`YYÙL™1‹•kÖ25x¢YqëblYùÓK+„„~ÍÈ ñü°1}¹œÛ·ï°.d™Y™Ì™·€!!…¦€B”,ëV¯zÚ! ]#¹†¢(Èc…VÏÚ´ãêtMomìÅÚ¦¦Î/×”)Å‹rÚîçazi!„B˜Gî° ƒžµiÇuÅnìÅÚ¦¦.¿SŠå´ÝÏÃôÒB!„04Ø…QžµiǵÅnéTÜÊÔºîñÚ¢œ¶ûy™^Z!„æ‘.1¢H< ÓŽ[:·)Š2îgmzi!Ò32x¤ç/@#ùeÛoOäX¦ßÈ0¾Ù°±(B+VÚλ(ój)mñ=+¹}R å###ƒVm;w=wî”â¾æše=ÉúdÎçX“f¾Š²|ÍkUñšJìÂ"ÏÒ´ã–NÅm câÖ7U÷Óž^ZK¬ßÀ' ?{&õ¬Ìñ$slmñ=+¹}RLÍGI¿æ–(îs³´|Íkõ4®…t‰yÖ¦·d*nS·¾©ºŸæôÒæL.ÄóBæ‹(>’Û‚$ÏŽ’p­´µR¬ó–R€mÞ¢È[Je€–©)?© …B<9–Ìg±‰•!k€Ü±*½zt/ôøÐ€À‘T®\™˜˜h‹æ Ðv¬qcFœ·@}Nˆ””†ÃkÛóîÁ…æ‹0”‹ììlBÖ®cçî=¤¥¥ÑîÕW‰:sš% x,,@·7ßæãSUì/^ºÌûc>àÀ®ªcuí܉ÝûöñÏ?ÿ£º‡ÁãÆz‚–®ޤzµjÄ\¿®5VSæc0ô^}yÑŸfnµÍ{ñ¬Î1kÎ'(s”Ì™9Èí¢ñFŸþ¼Þ¥3Œ@ZZº÷ä»ð0¦<§@>²³³Y½v¿ïÙCjJ*­[µbÇ®]lÙø-û4ëšç3f>m×Gýµ¡yL6}ÿ?oÝÊ»÷ðòªOð¸¨äì¬÷غꋡz /_êŸ=]ås>ÚrcÌwœ>¥ËLŽT -oÉÌ[²eÞ¢"wØ…Bbî|ïø÷'-5Øëqª†‹6E1o€®c;Bvv6Sgýµk×äÝ!ƒÍÊÅŠ5ü7ê4ŸÍŸKGGÖoˆ 6®ð#pµuû‚Çç6¾ØÄ˜ Áü¼9‚2eÊ{žÄĤ¥iï"aɼê4eÊÜ -[¼Âð€!Ìž¿€Ø¸Â“­“‹n~]X°h1]¸À½{I¬ûæ[ïoèåÅ/Û~#1ñ‰7nðÓÖ_ ½'4l=‡!))‰Ð°õ¤¦¥Ò¾­¯Áó6Ä”¼šz ´15¾¢<öÓäêú.•œÙ´y mZ·r»Ê4¨ïEhØz|´ô_ãê’¹9óæQmès_¾\9ÚúúòùÒeDÇÆ’’–Fä‘#¤¦>2êØšçf¨˜úÙÓ,ßÒyY´]‹‘Œcõ×a¦\“Hƒ]!„I&Á»UK>œ>“ï’üàaù ºvîDC¯ú `úì¹ZËÈŸ7 Ï ÁÄÄÆš7`È@–|±ŒŽ¯÷`TÐ.]º¬µÍc©ÏÐgÐ`FFê»!àá™œÝ IDATA4iÔˆ)3f˜5sáÄ ±4kÒ„ S¦1èÝ÷HÏÈÀÚºð-Ä1#ßÇÅ¥þC‡1vÂ$ܪ¸RJãi-š7eùªÞòÄù?ÿbÕK´>±Â˜k;WcójÊ{µ1'¾¢:öÓöªwîÝ¥aƒúªuí|Û˜xï-tî§^—¿@µªŸ&cINù\ø÷}›ßwïaÊŒYZ_úÜOŸLMOÞÄoõeãwßóàÁ}£Ž­íÜ ÕCù2T¾¡óÑG[y’“q®X|ݸä9ìB!D¹s÷.Ý{÷aÿÎí& f…ÂϽB<;:wïÉ'³g©æYÐÅÜç°Ëv!„¢ˆ\¾r…ªîULn¬ !ž]ñ dfeÑÈËËð›Í$O‰B!Ìt-&†˜˜Xš5iÌí»wYÊÀþýŸvXBˆ'¨´BÁ¢OçaWŒ¿¨Kƒ]!„0ÓÃ䇬 ßÀÌ9ŸPÙ¥½{ö¤WîO;,!ÄT¡Bš6®P¬Ç>ìB!„B<Ò‡]!„Bˆç4Ø…B!„(Á¤Á.„B!D & v!„Žä—m¿™½zF†Y“•”ò-‰ÃÈ0¾Ù°±HÊ×¼–^—g¶œ>ëç‘‘A«¶ˆ»nÚlº–Ös¥RÉ¢/—Ñ¥G/ú ÂÕk×Xóu§NŸ)²cˆ'GìB!ŠÔúð |²ð³g¶|KâhÛÆ‡:/½ô”"zö•”k[Xš‹­¿ýÆ©¨3l [˪eK©Vµ*{÷ïçÂ¥KEv ñäÈc…Bˆ"2â½wŸvBÇËuêàìì¬ZñMØÓ HXDî° !„(äðÑãøJG¿nŒ?‰˜Ø8Õ¶no¾Íɨ(Õë‹—.Ó¶“á›Xþ-»÷îǧC'>[òEr333ùbÅJú DÛÎ]é;h0Ûwî*ðsÊW*•¬ß°‘¾ƒóZ·7˜0e* ‰‰ª2Gòõ7áޤC××ywäh.]¾Â¦ïÀpýºñá´$%%§®8´ußÈ=ÆP:w琢˘<è3íãÙ|² àÑo6Fðá´ÖÍšó 3fÏQ½ÎÈÈÀ¯go¾\ù•j]ZZm:væz|<#Ù¾scÇO¢£_7Žÿ÷”Q±Ždó–ÿ8z,ýº1lÄh.\¼¨Ú~ìÄ GÒ®Ëë¼=`+W‡:'}u'*ê ÃFŒ¦½_7ÞögÏý¡Ú–™™É²•_Ñ«¯?~={3ÿ³Å¤¦îæaj.Œ©Sš¹ÈÎÎfÕêPzõó§s÷žÌ[¸¨@–äÂPLù>ý|17϶ßǧC'Þöž*æm;~7˜oQòÈv!„…ܺ}›¹ÏB¡p $ôkFç‡á888èÝïÿþ¤¥¦{=Ž93gÚnkkKUww̃½½=»÷ígÎü¼\¯.Õ«U3—®òCþáðѣ̟ý88سlU£ÇMä»ð0lmmøï©(¦~8ggg–._ÁÐÀôïó‹Ì#++›)3f±rÍZ¦O4§¡ó̱‰»ö0kÚTœ+rúÌ9*”/oq^kßž…K– T*±¶Î½÷yø½ßìYà}¾>­YüårÕë3çÏ“™™É¡Ã‘|0jDîºsç¨ê憻›‹¿\FИQEUw7£cݺ}Áã? Š«+ßFlbÌ„`~ÞANLž6“ Ñ£èÔ±·nß"==Ýèk p=!àñàZùB¾^ÇÔYóÓælmmYôårn߾úUdfe2gÞV„„<>È¢\¬þ:Ì`ÒÌÀÊ5œŒ:ÍgóæRÆÑ‘õ"TÇLN~hQ.Œ©çS&MÀ±tiîßÀô>,T¾¡|‹’Gî° !„(¤WnÔ¬á‰[•*L›Œ••{ö(’²ßêÕ“žž¸»¹1dàܪ¸ò×…‹†wÔ!##ƒßmfÊÄñÔ¬‘[SHIIáÐᣪ÷ùuîDíZµ¨èäÄÀ~ýÈÉÉa`¿~¸U©Â‹ÕªÒ£«çÎ/²8³³³ ßÀä‰ã©[ç%\*U¢ókP(—ߺU =JW½ÿÞ½$.]ùßÖ­ ¼Ï»e $'s5:€cÇO2d ?·ïÜ#6î:'O¦µw+Õ>ÆÑÝÏZ5k¨~A3&Ö>½{ÑÐË —J•=ŠŠNåÙµg/·nß"3+‹ÖÞ-)[¶ 5<=©W·®ÑyèÑ­+õêÔÁÉ©Cúsçî]â®_'%5•_~ÝÆð¡ƒqrª@e‡p òp¡2LÉ…±uJ3Wélùñ'> ž@íš5©âêÊø±£Uï·$ÆÆ$žOr‡]!„^vvv4jàEttL‘”—””ÄÎÝ{9ûÇÜ¿Ÿ»÷î’nÁ“*®'$’••U`°§B¡ ~ý—¹­uê!‘´´4êÕ­£u»%åÛÛÛÓ¦u+"Å«þËD=J‹æÍp,]ºÀûiÚ¨§¢ÎàY½:GŸà³ys¹xù2GާßÛ½9y*Š Ñ#Õʶ³8VkkkÔ÷"&.Žž=ºÓ¬qc ÀÇÛ›7ºw㕦M:Omª¸º¢P(HMM#&6¥RÉ”™³°Ê›¼=+;‹ÔÔ‡…ö3%ÆÖ)Í\Å'$­TR§vmÕ:õ)å=ªW7;æÔsñü;ìB! ²³µ-ð'÷œœ³ÊIM}Ä»#Çpëöm†Ì‚ys©U³V¡÷™R~fF:J¥’ìììB1ÛÛÛkÝÇJëºÇkSŸ‡“Ü~ÇšŠ¢ü×Ú·ãàá#Œ{®Pw˜|¾>­‰:sŽ£ÇOàãí»ÎÛ›óþÁ¡#Gy¥YSJ•ÒýwccMII-ðúÏ‹—ðôðP½nÚ¸3>šÌš•Ë8y˜[·ok=ž¾œjªâZG…‚ȼ_\ 16æÖ)Õ~j]«´1'ÅQÏ5!J.i° !„($âû¸xé2÷î%±lUÊœlÚú¶ ¡—¿lûÄÄ$Þ¸ÁO[-°oåÊ.œ>{žÄĤ©u1pv®HJJ ÿùé’’’ø}÷þ¾òO÷˜Z¾£BA×_gá¢%\¸x‘»÷î±dÙrœ*T Å+ÍÍ:câÔwžåË•£­¯/Ÿ/]Ftl,)iiD9Bjê#£Ê/_¾< ‰ª¿6h¾¶·³£Ok–|±œÆ âèè¨õ\\]_À¥’3›6o¡M^£ÞÑÑ‘õ½ [Zÿuss¶žC‡””DhØzRÓRißÖ—ÉÉüº}·nßæÑ£GD9‡B¡ \¹r…Ê0”SM¥J•bà€þ¬XʉS§P*•ܸySë/I¦äÂÜ:å¨PÐͯ -æ¯ ¸w/‰uß|«ÚnI.Š£žkË÷”³ØdVy¢øHƒ]!D!Í›6fòô™ô4˜˜Ø8V,]¢º ;fäû¸¸TÂè0ÆN˜„[WJ©u—éÚ¹ ½ê3 €é³ç(·zµjŒÈêuaô4˜ƒ‘‘´hQ°±aNù‚Æàݪ%NŸÉÀ€wI~ð¥Ÿ/ÀÊÔÛÖ&Ä©ï<óMŸLMOÞÄoõeãwßóàÁ}£Ê÷ïû6¿ïÞÔ³´¾èؾ'NÒÙ&ß«>>ܹw—† ê«ÖµómCbâ ¼[´°8-š7eùªÞòÄù?ÿbÕK°µµ%99™½2xx ]zôâç­¿2ö,ìí ÷•7&§šÞÄþ,ùb_ïÁ¨  \ºtÙâ\˜[§&¥Y“&L˜2ÁïP­jîd,ÍEQ×sÍc(•JâuÞñO¶+l·”lóEÞR(´LMy¸øI)„BˆÂbbã0t¿ÿò£Î;ìOB@àHÞìÙƒ7º½þÔbâYPÚ±Ìà8ðHÒò–̼% Pæ-*r‡]!„xFˆŒ¤yÓ¦Oµ±.„(~Ò`B!žQ»÷î£}Û6O; !D1“»Bñ Š‹çÊßÿàëãó´CB3éÃ.„B!Ä }Ø…B!„xIƒ]!„BˆLìB!„B”`Ò`BQdfÌžÃÒå+T¯Ó32xôèÑSŒ¨è•´s É/Û~S½ÖŸÿa|³a£Ùe Ýþm¹ÒV¿Jj222hÕ¶q×ãŸv(“»Bˆb³>|Ÿ,üìi‡Q¤Jú9i‹¯mê¼ôÒSŠHžMi…‚i“ƒUë¾ÙÁþÅÂOæh=ïü:f̵h×Ö—‡kÍuvv6«×®ã÷={HMI¥u«V:÷¬‘»BˆbñŽÒRÓˆ½Çœ™3 mON~Èäi3 =ŠN;pëö-ÒÓÓM:ÆÖí;ŸÛpù6bc&óóæÊ”)cp{hØ7>z”ù³ÿ{–­ aô¸‰|†­­-‹¿\FИQEUw7Z6oVèœL=ÿžŠbê‡qvvféò Aÿ>o±hÁ<²²²™2c+׬ejðD“r†snJîÔ-úr9·oßa]È*2³2™3o+BB 5ÖŒ)»ª»; æÎÁÞÞžÝûö3gþ^®W—êÕª©ö×Ì»­­­ÁýV„¬á¿Q§ùlþ\Ê8:²~C±q× ÄeN¹ÆäêzBÁã?Àµò „|½Ž©³>æ§ÍªÚ?pØ0ºûùQ«f  ßM6ç<ü:w¢v­ZTtrb`¿~äää0°_?ܪTáÅjUéÑÕsçΛ”sÊ]¾”ÔT~ùuÇÆÉ©•]\ÀÈÃf•ýV¯žÔðÌÍùp«âÊ_.Ø_[Þõí—žžÎ?þÄGÁ¨]³&U\]?vt¡¸L-ר\õèÖ•zuêàäT!ý¹s÷.qׯ]7²³³ ßÀä‰ã©[ç%\*U¢ókP(×UÍõ†®§¾XŒÑºU =JWåðÞ½$.]ùßÖ­ îk̵ðë܉:/Õ.”ëôŒ ¶QžUfßa ]ÊÜI˜"6oádÔ):_µÝ˜ kî <óüÓ¼ÆëÃ7uÇèI(©õÏPŽ,ÍaLl£ÆMäÝ!ƒùèÉìܳ—ñN!tå2jתeIèâ_Ê£zuš5nÌ€¡øx{óF÷nªnæ°¶¶¦A}/bââ n¿žHVVVϲB¡ ~ý—¹­ZgooW¬çááQ€Gjw]==«“š–fÔþEE_îbbcQ*•L™9 «¼ Ò³²³HM}hVÙIIIìܽ—³üÁýû÷¹{ï.é7´å]ß~ñ d+•Ô©][õ~mS¹›Z®1ç£©Š«+ …‚ÔÔ4êÕ­cT݈OH$--÷ýš,­«šë ]O}±ÃÞÞž6­[yä(^õ_&òèQZ4o†céÒ÷5õZ¨çÚØ:ð¬2»Áî¨Ö ·³·ÃÆÚGGG“Ê0wŒ žyþ•äk\’c+N›¶lÁ·µ7þ}ß`ÈÀ\º|™ˆÍ[˜9uÊSŽN<‹¬­­Y¶äs¢ÎœeÛöL™6“fM›èçš““cR™6ÖÖ8Øk¿®¾=3#¥RIvv¶êÏöv¶¶ØÛÛùy袭Aa¥e­©y0‡®Ü•q, À×_­¤¢““Ee§¦>âÝ‘cèÐöU†Lå^`|ðdƒûÚ/++ ¥RY †1ÌÇP=³²Ê½^ÆÖ‡“Üq666¶e]Ã×S_,Æz­};BÖ†1â½w9y˜ŽíÛÜÇÜk‘ŸëÌŒ ³êÀ³¢ØÏ(*ê ÃFŒ¦½_7ÞögÏý¡Ú¦ÙÕàØ‰¹ º¼ÎÛ±ru¨Ö2ÍÙ/33“/V¬¤ÏÀA´íÜ•¾ƒ³}ç.qŽdý†:cW*•¬ß°‘¾ƒóZ·7˜0e* ‰‰öß¾scÇO¢£_7Žÿ÷”jý×ß„8’]_çÝ‘£¹tù ›¾ÿÿÁtôëÆ‡Óf””dVÜú[Öá£Çñ<”Ž~Ý;~1±qÊX¶ò+zõõǯgo涘ÔTÃÝ,fÍù„³Aeddà׳7_®üJµ.--6;s=>¾À5ÎDµ{ï~|:tâ³%_¨öÑW¿ò…†­gаádgg¹_ o¼Ý_wì0+¿šõ/;;›•«CéÕן.=z1ÿ³ÅôøŽê¹¯†ê’:}uY_îõåHßvCõXÝž}èÔ¡}u:tÔûgq! ·1¥OÓÆ˜ñÑdÖ¬\ÆÁÈÃܺ}…Âèk1z÷MII-ðúÏ‹—ðôð0¸Ý½jUΜÜõD©TrñÒejyzšuNºÎÃRÆäÁ˜ø4Ê]¾*®•qT(ˆ<|Äèãë*ûâåK$Ý¿Ïèxzxà¨P`eÄmPCû¹¹»pÆÄ®DÆÆcl®t1T7ÜÜÜP*•\¸t©Ð¾–ÖUM†®§¾Xòª_­Z¶äFb"W££9}öœQÝaÌ­ùTyzÝÉž†bo°çÄøOÄê×™©³>&33³Ðûòíôx½+[·lfá'shÿjƒå»Ÿú`†akéÖÕ9ó«³ìü Úb û†½û0öÿ±~ÍWØÙÚ2zÜÄç¶øËetéò!+–ÑÈ«¾j}þ€£-7àîV…¡#¸qó‹ÌcÝšâ®Ç³rÍZ³ãÖÅØ²nݾÍÜg¾.”Š4^Õ÷yїˉŽc]È*¾ !>>ž!!íëÓšSQgT¯Ïœ?Off&‡G>^wîUÝÜpws+°ï;þý xg¯uhÇá½» r2¦~ 8€ì¬,6ÿð#kÖ}M­š5èîçW$ù]²†c'NòÙü¹„­ù +k«BôÕ¥|†ê²¾ÜëË‘¾íÆÔcÈízÿþ}ÜÜ ^›«U%%%…”'üç{ñì¨\Ù…ÓgÏ“˜xƒ4zò 9™_·ïàÖíÛ²¨®jcèzê‹´×/Í:hogGŸÖ,ùb96,ÐcäãXýuX¡¸Ì­ùÌ­ÏŠbo°ëˆ¡ÉÜÁG¦ìgÌ`uº6X:ÄÔG¦Æ­1eõêÑš59˜šž¼?&ˆ7ÞêËÆï¾çÁƒÜïVsëª.†®§¾X´Õ/Íúб};Nœ:U¨;̃ädœ+îŠcnÝP§^¿@µªnöz6<ÑÇ:ªÐdî Sö3u0ƒ®Ø‹t°’Ž,‰[“©eÙÙÙѨÑÑ1 mç¢/7šeZYY1 __ôë«ëÔŒ.ûÿþ¼ãß_羺ònh?¦LšÀ”I€Ü ›¿W}g™[.è?måîÝþ¸Û¤±u£lÙ2Ìšö‘ÖmæÖU]ë ]O½±h©_šõrÿO+Uª¯úìsëÖm^|±Ú˜S7Ôs­YÞ>LgyÏ’'þöüÁšÌ´cì~æfÐ{Q14à¨(â¶´,;[[lmm-xäëÓšS§£ðõñ†%UÝÝxÕ· ÛwìįSGâhܰÉåªÓU¿ÜÝsûåÙÛ=þk‡¥ù5w “¶8õÕå¢ô¥É”zìXº4Ž ±qqÔPë3™@ùråt>îN!ž–ËW®PÕ½J‘ý¥C˜æ@d$Í›6-Ð&>!̬,yy=ÅÈžM%n­¹ƒv ígé`uE=DŸ¢ŒÛè²ÔžF““Ã_.RÃÓìGê|}ZuæGŸÀÇÛ;w·7çÿüƒCGŽòJ³¦”*¥ûwHcQér-&†ð |0jŸ/ý‚‡sïL[š_s:飭.›{C9Rßnj=öõña§Æ3š÷8Hû¶¯<'!„(n×bb8y˜””¢ccYÊÀþúâ³{ï>Ú·-8¦°´BÁ¢Oça'¿D™¬Ä4ØÍ´cì~–fPWÔ@ô1&nÍÁº¶›ƒˆïàâ¥ËÜ»—IJU!(s²iëÛÆ¨Gúbqu}—JÎlÚ¼…6y#ÆiPߋаõøèé¿nì *m”J%s?]È ýЯ/õêÖU=ÆÒüå }uÙ˜ÜÊ‘ævSëñ€þ}ˆ>|ÿã4lðø©9í|Û°`ñR¼[´Ð™‡®;qäØqФqÍÿÄènøn3©©i èÛ€IãÆ2`h_ëHó¦M,Ê/ärYº|%¦LÃÆÆ†.¯uôtÒÆP]6”{C9Ò¶Ý”züRíÚ,Yø)_…®%,|uj×bÙâÏð¬þ¢Iç)DQÑÕ?רíÿfÅ™›§•w¯ú/³.de‘—+õÈtÕªºqd¤ˆ\" IDATßî§ÆsE[‹Â:o)Øæ-м¥4Ph™šòpñ“ RˆgÉ»wéÞ»ûwn—¾“B!„P)íXfpx¤iyKfÞ’(ó•Ó%Fˆç… tB!DQ*1]b„xV]‹‰!&&–fMsûî]è$„Bˆ"%wØ…° tâéHÏÈPÍœ/ p$¿lûMÇÅ/##ƒVm;w=Þ¬í¢øh«/B<+ä»*®NBýÖ‡o öz\¡Éš„ÐFê‹x–Év!„B!J0¹Ã.„¢MßÿÀÏ[·rçî=¼¼ê<º¢T* ØÄ¶í;¸{/‰† ¼TÛ ·KJß·{óÛößùëÂæÍMËæÍt®ÏÌÌä«5kÙ³ÿÒÓiÛ¦ A£GQº´ƒÞXvïÛϺðÜ9öî?H¯Ý Tà¦}<›Ò Ó&«Ö}³1‚?þüËà,Ú™™™¬\½†È#G¸yë/Tv!`ð;tíÜIõžììlV¯]Çï{öš’JëVç“0´ý؉„„®ãjt4•œ+Ò¡];F/K@àH|Û´æPä¢c£ñôðäÃñã8}ö?oý•›7oÒ¬YS¦O¤B… FÅ8’vm}9pè0W¯]£ª›“ÆѨ¡—Ź+.úêKhØzö<Äú5!ØØØšúˆþƒ‡8< wŽ -õE[½lÚ¨¡ÁÜé¢ïzޤkçNìÞ·þùÕ=<7–zuëu½@÷çÒÐçÈØz&J.i° !„( ·‘ýmÄ&ÆLæçÍ”)SÆà1õ}.õåÅÔz&J&é#„B%;;›°ð Lž8žºu^Â¥R%:¿Ö…BAFF¿ÛÌ”‰ã©YÃw77fMBJJ ‡U•8lÝýü¨U³:×§¤¦ò˯Û>t0NN¨ìâBàðD6‹1Z·jÁ£Géüuá"÷î%qéÊßøæÍ´lŒ·zõ¤†gî¹8·*®ªòÒ32ØòãO|<Ú5kRÅÕ•ñcG«ö5´ýÖí[dfeÑÚ»%eË–¡†§'õêÖÕ‹_çNÔ®U‹ŠNN ìלœöë‡[•*¼X­*=ºúqîÜy£bW/³ÎKµqrªÀþܹ{—¸ë׋$wEÍP}±µµeòĉ„® ãÈÑcüöû.¦O2X®¶újLî4s=ûôîEC//\*U"hô(*:•gמ½©ï³`(/¦Ö3Q2Év!„*ñ ‰¤¥¥Q¯nBÛ®'$’••E—^R­S(Ô¯ÿ2×b¢UëìíµÏA ¹>&6¥RÉ”™³°Ê›Ç/+;‹ÔÔ‡c1†½½=mZ·"òÈQ¼ê¿LäÑ£´hÞ ÇÒ¥.#))‰»÷rö?¸ÿ>wïÝ%=ïI#ñ d+•Ô©][õ~õÙ m÷¨^f3`h>Þ޼ѽ¯4mjT\Õx¤v§ÔÓ³:©iiFÅ®MWW ©©iE’»¢f¨¾4nÔ€N;0iêtfNL¥JÎËÕV_M͘~=­­­iPß‹˜¸8ƒÇÔ÷Y0”Kê™(9¤Á.„BåáÃd”J%666¶ef¤£T*ÉÎÎVu“°³µÅÞÞÞäc•q, À×_­¤¢““I±ëµöíYƈ÷Þå`äa:¶okô¾©©xwä:´}•áCSùÿٻ︪êÿã/PÆSq2ô§82*¨ˆ¸Å•6¸1#g82MSKM³rå ¥@Í‘Ù4ÓJMœ‰¨•£o%¢bŠ+².¿?€ãŽs.}?ûxxÏ9ŸÏçýùœs¯‡ó9÷¼kÔ`ò´éºõi©©hµÚ<·äfj½µµ5+—½OTôivíÞÃŒYsháÙ\Ñ=âúÒ”[åZj*vƒõZeêþ]˜±+ ¦Ž—®®.hµZìlí ncŒ¹cgÎþ,cm½½É6}LKaŽ3QrÈ-1B!t\\²NvÎ]¸P`kÍšDŸýï¶ ­VËù ©ï榺-g§ê8h4DDVKŽôôt£m´ööæŸë×ù;&†S§Ï¨º¥ãüŠܽwñc‚p«S«\gʺñÈuJn¦ÖçðlÖ”Ù¯Ogýš•üÉÍøxÅ1š»…»¢`êx¬Dv›6oå•qcxù ò¬7u¼@áÇÎØþLLLʳíoç/àV§ŽÉ6}”Œ‹©¸DÉ''ìB!t*V¨€Ÿ¯/ï/_ILl,‰ÉÉD>LRÒ4úôìÉ»K–qîüyn߹ò•«p¬T ¯V-U·U¶lY† Äêu¡?y­VË?7nèNJŒÅP½z5N>Ëõëÿœ}+HÅŠ‰‹»NffÖ•b;[[Úù´eÙŠU4kÒÅñU©R™ÄÄD¾øêîÞ½Ë÷{÷ñ¿?þÔ­wÐhèåßÅK–òû¹sYO"Ùø‰âõÿÞ¿Ï·»÷p3>ž}FC… T¥ÚØ•(ÌØSÇ‹V«eÁ;ï2tð @£§žâƒ5êÊë;^ô1wì”ìÏÐð Š<ÌÝ»w ß@Rrý|M¶iì³`j\LÅ5cö\6mݦngˆ‡Nn‰B‘ÇÓ§±ôƒ•¼4|òIÕm›[®(íüî;NFE³%ü#¬¬­©ðÄ|¼a±W¯0Îl“åÛ·óáÉõ-ˆM› ´›ÌôÅ»ÿÀ4å4´hÞÌ"q!„âÑ%WØK°µ³¥ŒuÝ{¬­MïÆ1/½ˆw«–ªÛ6·\Qº|ù O7lH•*U¨ìèHÙ²êþî4šVžžE]Á1ÓïÖá 4°Èb˜✵³tâáÍré›-´´ü}‘cÄ|Æfb Q2#œöøSgi™=ž=o>ËW­Ö½Ws€1r…ýÍW;wñ÷¥KÔtqáÕIÁ4mâdxÏöíÃ3½zpôøqBBÃø;&†ªU*Ó©CÆ.P§9åÒÒÒX³n=‡sãæ-jT¯FàðaôèÖUQ?ÒÒÒøpýGì;p))øµkGðøq”+gÏ;ï/åëow°ûÇ©[§ݺv&lÓ'ì?ð3ýúôfÚä`ƒõçïS¯g_àÍÙ3u'ñç/\äå ¯pðÇ=Fû¼ië6½íæ®__¼›>^O`ÐX^x®½ü»›ì3@FFë> ãû}ûHJL¢mëÖŠÇRɾˆß² {{{“±‰ÒÇ!× yîY;5Ƽôb¡ã°DâáÉ=[ø°È1òpéÛÇ[7†_@BGNØ!}zõ QÆŒÀWßìäÊÕ«¸Õ©“g»›ñ7IKO§možx¢þp ŽŽ•ÈësÞ*–DsÇJ S}NIMeÇ—_ñáª4¨W€ÉÇóÕ7;Õ¯d_ôëÓ‹zuݘ5}Ï e߃thï[¢ö‡x¸ŠbÖ.·ÂÖ¡d)0h,ü|9x(Ro? ÕkhV)4|~>Ćõ!”)S†¤¤ >‚ ÑtïÜYQ<¾íÚr(â01±1¸ÕqãµÉ“8uú _ïü–7nТ…'3§M¥R¥Jº2=ºueïO?ñçŸQ»N¦MšH£§žR¿1Z­–M[·±k÷nß¹K“ÆL›ô ÎNNg ÍÝ/Jå?FLíOsú>wþÛh3µº /©©©<Ó=»wã•qcHNN¦kï¾|º)œ7ޜπžã»Ýßóû¹s,\0ϦMí{cûÑÔú¢š‰Í¡tFØ”¢Ž3§Ò0{¬o&Þ\rÂþˆrvrB£Ñ””\`]ÚµiѬƒGâÓ¦ Ïôî¥èžn5åîÞ½Ë{÷sú×_¹wï·ïÜ&EÁ=\—ccÑjµÌ˜3+¬HÏH'))ÁdÙ¢`îX©aªÏ×ââÈÐjiØ ®Œ•ŠúÕî [[[š6ö &ær‰Ûâá*êY»ÂÖ¡téØñLŸ2‰êÕªíGc³J#† fßþŸØþù— xõaS¿^]zûû(Šç—“QÌ|m*UªTaùªÕŒ àþϳdñBÒÓ3˜1{.kÖÄÌiSuevîÞôÉY'ÏŸlÝÆ„)ÓøzûVÊ—/xÁÜY±ÐðD9¢yoaooÇʵ!ŒŸ4•O7…+ž-T³_ÌelšÓw_Ÿ¶,ý`•î}ôÙ³¤¥¥q(2BwÂ}æ 5]\puq`é+ ž0Žà ã¨éꢸϦö£±õE5›CÍ>6¦¨ã„Ò3{¬o&~î³ÌªK~tú³²ÊÔ»ÜÚÚš•ËÞçýE‹°µ±eƬ9¼6Ëô­$JË%%=àű¸Ïè‘ÃY¼põë){*Ky‡¬{"?þp _~º…/?ÝÂÎÛÙ¿[Ý?RSSñéÔ5ÏëÌÙ_ nŸ™iÙ±RÃTŸÓRSÑjµh³ï9VÃÜ}akcƒÅö‡(rfí+1bH·nßæÊÕ«¶Ë?U×ÍÍàÕ_CÌ­ãù~}©ë憫‹ #† ÆÅÙ‰ßÏϳ·®4|²É~À3^£GÇѱÕ«U#ht #"¬…éS§Îá#Gùîû™9íUÕñ4¨_ŸÊŽŽ 8ÌÌL† ˆ‹³3ÿW«&}zøsæÌÙVŠ“\aŒy6kŠg³¦ 4€Á#_äf|<ÕªV-t¹ó/p÷Þ=Æ Ò-³RxIØÙ©: ‘‡y¦w/UýIOO×ýÛÖÖ–Èý?**§ÑØsé2^-ZÜÆXŸs·kS}v­™5}}æ,-=›«ª[ñ¾ÈõKff&¿Ÿ;O»¶m µ?Ä£¥(fí,Q‡Ú$cýe³|Íš6¦kçN¼:ó æÌœNÕªÿÝï«6ž:ujð ×l‚›[m’’õÇY»{pùʳâ×çjÜuÒÓÓóüÀS£Ñàîþ4—.Ç-«¹³¬jåÞŸæöÝÁÁϦM9[íÚ9vœ÷.àüÅ‹>zŒ/<lj“Q«+cgg[ µ}6¶ó¯/ê™XKy˜q>n³ÇrÂþú÷þ}~ŽˆÄ»UKž(_ž¨è3h4*T¨`‘rUªT&11‘/¾ú†NÚsì—“üï?¡«þû+V¬H\Üu233)[¶,CbõºPœœhÙ¼97ãã¹}çŽîþ|}ªW¯Æßìäúõ¨X±‚¢§\ähâáÁ7»¾Ã×§-XÁW;¿UÜç´›ÃTŸ4zùwgñ’¥¼õÆLœœÙþùëË=žJ÷ÅÖÏ>çÉ ¨Q½:›¶nC›™Ÿo;Eû#w{VVV̘=÷§1,`ê±%›©Y»¨èÓìÚ½‡³æÐ³9ï¾=_qÝæÔ‘3ƒÔɯ=£G§zLž6Ýì~@Þ¯ÊŽŽ·suuA«Õbgûßý®æÄ£ïdÅJÁ)Lkkìí Þk«4þüÒRSÐjµdddäyT°­ vvvŠëó÷‹¹rö§©¾§¦¦ÒÑ?ï…‡µ+–Ѥ±¾>m9y* _Ÿ6©¥¦« í}Û±{Ïøwí̵¸8š5il0sûlh?æ_oªo¹gb•<깨<¬8Ío}³Çj>'ÅIn‰y Ý¿Ÿýføè º÷éÇ×;¿eѼ¹ØÙ¼b`N¹Úµj1~LëÂÂé?t8?GDàåeøYî^àû½û˜1{.Æ2bHËV¬¤sÏ>Œ žÂ… ÆÖ£[Wšx¸3807æ-P8Y&Œ}™jÕª0r§¼Š‹³e³ïm5Õç´››©>O žH‹æÍ™2cÃ_ʺZ^«¦‹Þºr§Ò}ÑÒ³ÓߘCÿ¡Ã¹{…ÕË—éžoo*¶ÜíiµZ®Å]çf|¼Ùc!J/ÏfM™ýútÖ¯YÉÏ‘fjêÈ=ƒäV§âÙº™¼³ÿÝŠ£Õj9á"õÝÜTÕU”ã`Œ©¾ç̼æ~5iœõcU_Ÿ¶DEŸáÈ±ãø´i“µ¬MÎþö+‡¡U O£9?”öÙÔ~4´ÞTßrÏħ‡§âcLÏìq]7Óãii…‰¹Â^ê ÀðÁ–‡­[[`YîûŒs¯wuqaé; µgn¹aƒ_aõnÕ’/¶mÖ½·²²bðÀ 8@ïö³”›â«yÚL-Öeþû[µ²£#K/ʳÍð!ƒÓ}Ö×nþ}¡/Þüۘ곽½=3^ÂŒW§è–½>|öå—4iì®[ÖÁ·‹—.§——ѲJûll?šZoªoSƒ'²|զ̘…MYzûû癉ý÷þ}ªT.üíù÷‘ÚãÏTœJÛU2Þ9³Ç‰II4kÒ¤Àì±±8s··hÞ›\‹»NõêÕTWn]9|ôƒiÞLÝïÐrÓ÷)´Î~•l²_šìW9 <à”˜°ÔìV…(&oÜÄÁC„…¬-Öûü„B©üÏ"¥“©ýXÔû¹[ï¾¼=o®ÅM,Ô)çP~ p H’€äìWZö+Ðf¿täŒE<6222¸pñ¬^¶DNÖ…B<6®ÅÅ‘–žNSà ÃDÉ&·ÄˆÇF™2eX¼à­âC!„x¨Êi4,yg!¶*nS%‹œ° !„B<Â*Uª„g³Jņ(¹‡]!„Bˆ‡@îaB!„â$'ì¥Àk³fóêëoX¾bÍZzö{žÄ|)¬c¯\¥mÇ.ü{ÿ>#F±qóݺ”ÔTäKÝ4–ov}GqÉß¾¾ó÷Cm…‰GmÛB!„–$'ì¥@ëV­ˆ>s­6ÏìŽ !1‘ãÇɳüä©S<Õ°!žx¿v>4|òIݺ ›6óö»ï=”¸Í¥/Æüýx˜Š³m!„B9a/¼½Z’ÀŸý¥[KòƒdztëFäá#y¶ÿ%ê­½Z0æ¥ñV™¥®$*Î~<*c(„RE=ëfªþÔÔTZûuâÊÕkE›¾Ùò×õ05s>çùûN²DýJÈ {)àêâB­š®DEŸÑ-;zìm½½ñóõ!âèÑXELìÂBÖ²14„k×®±:$ĬŽ?Áô)“ôŽ—±¶îßO`ú¬9ôéÙƒ;¶óîÛó騾Ùq!J™+Z2¾ÊÉX=z䄽”híÕŠèÓ§ÉÌÌ$%%…³¿žÅ»UKìlmñjÙ’È#Gøåä)Z¶ð¤L™2ªêïÓ«6Äѱ#†pëöm®\½ªw[ÿn]iP¿>•2p ™™™ 8ggþ¯VMúôðçÌ™³…î³)ýŸëGªU­JðøqTv¬ÈûöØ.1)‰o¾ÝÅè‘Ãqt¬DõjÕÈÁˆH³ÛöïÖ•†O6(0^¦Úº“´ôtÚ¶ñæ‰'ÊS×ÍFO=evB˜ËÔL±Y7­VˆÍ[0t8]z=Ô3‰»~]·^ͬde!^».”~èÖ»/ ß]b4öÈ#Ç>’Îþ½˜8ùU.Ç^Ñ­S:›¦o6/--«×ÐÈPüºõ`ÀÐáìþáGƒq$&&0<6lÔÏÆedd°f](ýнO?½·”þC†évÓãªtæÑÜÙV53•¦¶566jfZwÿð#'¿Jgÿ^ûå¤ê8K‹¹óßfö¼ùº÷©©©ø÷}ŽÖ|¨[–œœL»ÎݸzíZ±2ö+ìì»ÚÏ>¦¾S€ì™ü‘tëÝW·ÞTÛ†úfêÚ”=T IDATQúd¨~%ýQK'•žÍš‘”œÌ¥˜þ¹qƒ† ž¤|ùò´o×–mÛwðòèQür*šÖ…ü«ÚÙÉ FCRR²ÉmëÔ© Àƒ”Ý27·Ú$%›.kIÖÖÖ4v÷àò•+Ö]ŽE«Õ2cÎ\¬²S¤g¤“”¤ÿj¼Z¹ÇËT[ujצE³f ˆO›6<Ó»­<=-‡JåÌôG×θ“”\ŸaøoÖÍ©z B>cæÜ7ùjûVlll ßHä‘#,š÷ööv¬\ÂøISùtS8666ªãY²žQ§xoáÊ;8°aóV£ÛߌgÁ›sÑhì ý˜±Á“ù|Ë&ìííYòÁ*âão²–´ô4æ/\Ìê³uÑœ”LìÕ+ÌŸ3[·¼¦«+‹ÌÇÎÎŽ½?`þ¢Å<Ýè)jת•§|FF3ç¾EƒõxqÄpƒ±æÌÆU¯V­À8®YÏ/Q§xoÑý޽¢ÿB‰R;wïaÚäWpvrâ“­Û˜0e_oߪûÿÂXßÁø~W:¶€¢m ±øò[úÁJ‚'Œ#xÂ8jºº(n»´ñõiËÒVéÞGŸ=KZZ‡"#xeܘ¬egÎPÓÅW—å}ÆÌ=rØØØ(þÜbê;eÓÖmüðã>æÎšI•*•9}†J+šlÛPßL#J¿“ Õo¬?æ’+쥄F£¡ic¢¢OsøØqÚ´öÖ­kצ5þý7qׯ} / LƒYYe*ÛNﲂK33•ÕWe¬­±·³/°¼¼Ã|üá¾üt _~º…;¶³·å~ð’3^¦Ú²¶¶få²÷yÑ"lml™1k¯Í2þ’–¦d¦ÇЬ[jj*[>ÝÎŒ©“©W× WæÎœAbb"‡"hѰ”ÔTv|ù¯O›BƒzõpvrbòÄñFËôëÓ‹zuÝpqvfÖôiXYY±ïÀA‹Ì¦=߯/uݲú5bÈ`\œt·êdf²äƒ•$&%1kúkFë34—’’Âç*û­„Ò™GC íw5c«t[Cc£FШQôö÷§~½ºØÛÛÉŒjIÐÆÛ‹ïßçï˜ ëwl#†ëŽî¼'OѶMëeÍùŒåP:û®èsc€©ï”ŒŒ Â7mfúÔÉ<ÕðIªU­J·.Ðh4fµmê)Ìx)é¹ä {)â}ûÿûïÌK·¼bÅŠ4öxš°ŸP©b½]ç–žž^Ô¡æ¡ÑØsé2^-Z(.£$ÆÄĤ<ï;‘C þ±âìT†ˆÈÃ<Ó»—âÌ¡´-ÏfMñlÖ”!ƒ0xä‹ÜŒ§ZÕªE›9ÔÎôäžEºwôôôFë¨^½_|³“ë×ÿ¡bÅ º¿P‹R¾Ùõ¾>mÁ ¾Úùmžõ+V$.î:™™™XYY)Ž14|5]]hìþ4;¾úš¤ä$:úù¨³lÙ² <ˆÕëBqrv¢eóæÜŒçö;4jXð Í®Ý{˜1k-<›óîÛó –É™EJKMA«Õ’‘‘µõ“´¶66ØÙÙéÞ+UKKME«Õ¢ÕjóÔ§†­ 666yf¸*;:ª®')é/Ž@'¿öŒ9œê5j0yÚôÛµôô$ær,Û?ÿ‚q/¿¤ªœqLOO7«ßjg+ Í<*¥oöÐÔØš»”ÎìEÛ¥¯O[NžŠÂ×§ dj©éêB{ßvìÞóþ];s-.ŽfM(g‰ÏX}ûHéçÆSß) ÷¬ûÂóÿ>Ïœ¶M#…/¥ß‘jÉ-1¥HƒzõÐhòÜ“Ã×§-Z­V÷üuCztëJwòƼEjƾLµjU 9ЉS^ÅÅÙ‰²¹î ðßïÝÇŒÙsUÅèÕÒ“UkCx>`(gûµ+–éî«Ë_gà°¡ŒÀ²+éܳã‚§páÂE½õæ/«–±¶îß¿Ïþƒ?3|tÝûôãëß²hÞ\ìlmÑjµ\‹»ÎÍøx³ÚB-ÏfM™ýútÖ¯YÉÏ‘ŠŽ=ך5¬{hshµZÎ_¸Hýì 9³jJèêSóCõ\'­™™™ü~îçÉ ¨Q½:›¶nC›™Ÿo;Õ³iùgóªT©Lbb"_|õ :´çØ/'ùßB×®Êz{µbtàæ-ZL¸[]jÕ4~+¢¾qTÛoSã ÆgõÝÔl«š±U»ô1w6Øm—TNN5¨Vµ Û¶ï`Æ«S¬[e»{¾ÁàŸ•k…™}Wò¹É?sÿ;ÀØwŠ••~¾¾¼¿|%óç¾AÕªU9uêžÍ<µ­¯oÆŽµŸÍüõ+ùŽ4‡\aBˆÇŒ±™%¦O Mko^{cC_äþ¿ ,±î2µ³jSƒ'Ò¢ys¦Ì˜Åð—‚Œž·ôlÆô7æÐèp.Ç^aõòeº+‹jfÓòÏæÕ®U‹ñc‚XNÿ¡Ãù9"//ÃÿÁJó¦M™1{¶Y™s÷{è‹/‘’š €µµþË“¦ÆŒÏ<ë»jÆVͶúf6¸°m—dí}|¸uç6M»ë–uðmÇõëÿÐÆËË`9SŸ±ÂŒ·’ÏMþÏ|þ÷¦¾SÞ˜>znuxyB0Ï4|òIÝû ›6óö»ïcD_þ1x””¦ýYšb}\©ý¬<Žû´¨¿O䱎BñóÒ‹ÅB±“1Bù¬˜VÔc$'ìBñÊÆ~ÓÖm„mú€ý~¦_ŸÞL›üÐcJKKãÃõ±ïÀA¤¤à×®ÁãÇQ®œ½.æ/<Çw»¿ç÷sçX¸`Þ-[˜,gHî18zü8!¡aüCÕ*•éÔ¡ã‚F›ŒyͺõD>Ì›·¨Q½Çѣ[W“ý5Öž’±èàçËÁC‘ü}é5]\xuR0M›xÜŸ…©3ǶÏ>çë;¹uûîL›ô ÎNNfïC±jµZ6mÝÆ®Ý{¸}ç.M{èÚ2&0h,=ºueïO?ñçŸQ»N¦MšH£§žÒ­×w kï·æ£±³cÖŒ×tílܼ…ßÎ]`ñ‚· uüù¶kË¡ˆÃÄÄÆàVÇ×&OâÔé3|½ó[nܸA‹žÌœ6•J•*1ëÍy”Óh˜5}ÚqlÙʯ¿ýλoÏ/Ô¸˜ïüŸsŽ¿‡­4~Ÿ#·Ä!ÄcnXÀ ‡ ¥K§DîÿÑâÿ¹¦¥¥“œœ\à•ß’V{…°µl áÚµk¬ ɳÍÒVÒ½{BV¯¤©‡»âr¦Ü¿ŸÀôYsèÓ³;wlçÝ·çÓ±};“ålll¨éêÊâóÙþ½zø3Ñbbbc Õž’>;~‚éS&ñÅÖ͸»?Í̹o’––fp¦N@wB7wÖL6‡„—.TªXQqÝúŠ54|#ûdѼ·Ø°þClml?iª.cvîÞı/³í“ 4voÄ„)ÓHHHЭ×w k¯[çN:r­ö¿Çbÿy˜n;ªï¿œŒbækSÙ±e3®.ÎŒ Ã?7þaÉâ…„­áÊÕk¬Yÿ]:v$âÈ‘ÙGÇJŒÀ­Û·¹rõªÞö [gFFá›63}êdžjø$ÕªV¥[—Nh4‹íƒ©©©lùt;3¦N¦^ݬq;s‰‰‰Š9;9¡ÑhHJ*x¥Ñu^‹»Nrr2žjh‘º¹wôôô>m°··çÜ… ë{:µx’¢[ææV›¤ì«Çvvv´kÛšˆÃGðpšˆ#GðjÙ‡råT·•{\,1Þ¦Ž?KzÔ¿O ‘v!„Å®¼Ã|üá*;:y¹ü¬­­Y¹ì}¢¢O³k÷fÌšC Ïæ&ï NJzÀ‹c'Ðɯ=£G§zLž6½Pí™Û'+«Lƒë [gBÂ} ë^ç2eÊX¤nCÒRSÐjµddd`mýß¶66ØÙÙ©®¯Œµ5öv†ï?VÒ^×.X¶b%ã^~‰ƒ‡"yö™>€eûn¥wYÞ¥]:v ä£pƼô"?GDÒYáí0ú䌋¥ÆÛØñ÷°•Öï£uš]R!Ä#%==½ØÚvvªŽƒFCDäá‡RÎÏfM™ýútÖ¯YÉϑ܌7ºýù‹¸{ïãÇáV§ VúμT´g©>åÞŸ…­ÓÅÅ­V˹  ¬³D¼¹cu­Y€è³guË´Z-ç/\¤¾››Éº“ò¼ÿíüÜêÔ1¸½’öZ6oο÷¸øÇœ¿pïV-˦´ööæŸë×ù;&†S§Ï(¾ KaÇÛù>Qÿ}bŒœ° !„ zõjœ:}–ë×ÿÑý€kÆì¹lÚºí¡´_¶lY† Äêu¡?y­VË?7nè=A´D¹üþ½Ÿowïáf|<< *ú † *-W¥Jeùâ«o¸{÷.ßïÝÇÿþø³PíY¢Où÷gaë¬X¡~¾¾¼¿|%1±±$&'qø0II ]wþX4úôìÉ»K–qîüyn߹ò•«p¬T ¯ìecBÃ7p(ò0wïÞ%4|IÉItôó5¸½’ö¬­­éÔÑ÷—€Okolm³n¥°Ôñ§”­-í|Ú²lÅ*š5i‚ƒƒƒâ²†Æ¥°ã­|Ÿ˜÷}b46³K !„xdôèÖ•ÃG180æÍšóÞÛó¹wêÕ«=´‡ ÅÞÎŽe+VrýÆM*;:2,` ¼oÚår»ÿ>ûþÌêu$%&ñµj±hÞ\ìlm–«]«ãDZ.,œµ¡¡xµl——é“Sí¶Où÷ç’EoºÎ7¦Océ+yyBÖ#"6¨Oýºõ(WξPuë‹uJðV‡¬ãµ7æžžŽw‹–,1V ¦/¼Zz²jmñ·náááÎÚ˰±±1ZFI{Ý;wæ³Ï¿äÅÃó”µÄñ§FçŽxmÖlæÎz]U9cãR˜ñÖG¾OÌû>1Fßž°Î~•l²_šìW9 <à”˜°ÔìV…Qý‡ %öÊ5ƒë?ýdoÎ_˜çyŸùŒEn]>d°ª¶Í-g jÛÎÿÌÓüRRSÉÔj±·7þìT€€áôîÕƒ!¨ŠYi»ùû¦ÕjY¶j5?ü¸J+ò΂·Ø»ÿžÍ›Ñ¢y3³ÚMMM¥}Wvlù„š®.yÖ™«üÔnoéòBaŽÇá»çrìÅ÷ß|©ø ûã0.¥E9‡òS€c@$g¿Ò²_é€6û¥#WØK ðÐõýœÕ­Ûwp"ê$KßY¤[¯ÑhLÖanŠÜâLÕmé¶7lÚLìÕ+ÌŸ3Ûä¶íÛùðdƒúEÖnþ¾íüî;NFE³%ü#¬¬­©ðÄì?pM9Ù'ìB!}#"héé©êvQúÉ { äë„ÜÖΖ2ÖeT0ÍM‘[œé‡‹³í±…È>¦Dþ¾]¾|…§6¤J•*ºe[7†i B!J¿½ûâ¹¾}Š; ñÉNK±¨¨hFOGÿ^ õ§Ïüª[4–ov}§{ôøñ¬TÂÝ{òÂ࡬Yª·NsÊ¥¥¥±bõúŠ_· :œÝ?üh0îÀ ±ìþáG&N~•Îþ½8öËI½mgdd°f](ýнO?½·”þC†qåê· ƒœÔÈ{÷À§SWÞ[¶ÂèXæo»×³/p"*J÷þü…‹øuõ79.†ÚÍ]ÿ;ï/eËöÏØõý÷øtêʰQ/é¶Ùµçû<ãºr͇ô€ßçXôÞR’’þ{¶sFFk×…Òo`Ýz÷eá»KŒö1w½JöWä‘c Igÿ^Lœü*—c¯ä©ÃXlB!,/öÊ5þøßŸøúøw(â!“+ì¥ØÕ¸8¦M~§ê5ù8Œ™sßä«í[ ü¸&'Enðøqtí܉›ñ7IÉ•˜Á¥år§æ¶³³cïO˜¿h1O7zŠÚµjé­{é+ ž0Žà ã ÜocuÈz~‰:Å{‹PÞÁ ›·{%o5Cc0,`ÉIÉŠo‰QÃØ¸(iwÆ«Sp(WŽ{÷þå×_3ØÎ’V‹°µ¤¥§1ábV‡„èÒ<¯ Yω¨S¼·ð¿ñQBéþºÏ‚7ç¢ÑØú1cƒ'óù–MØÛÛ›ŒM!ŠCغµÅB‘ªUÓ…Ã?íU]îQ—Ç\a/ÅúôêA£† M¦67E®šrjSsçOœ_JJ Ÿù¯O›BƒzõpvrbòÄ‚™Í”Ž%EÊáüL¥GNIMe‡‚ñ1DÉþê×§õêºáâì̬éÓ°²²b߃OC.„Bãä û#ÂXZ`sSäª)§65wþtÀù]‹‹#C«¥aƒºe¦.õ°R#EÊáüL¥G6g|rS»¿lmmiÚØƒ˜˜ËOC.„Bãä„ýb(-°¹)r•–375·1éééhµZ´ZmžTɦKœššJGÿ^y–­]±Œ&=ônŸ™iÙñTÃTzä´ÔT³ÆÌß_¶66ØØØX< ¹B!Œ“[b#æ¦È5U®°©¹õqqu úÌY[—;5²­­-‘ûÌó2t²®ÑØsé²ÑºKaS2›J¬K%mÆø(Þ_¹þ`ÉÌÌä÷sç©ëVç¡§â¥SJj*òÍÚäÿqwi£¯O%ÕìyóY¾jµÞu­ý:ñÛïçrD¥Ó£x듚šJk¿Nyê u=œº”’öÇ€¹)r•–375·1 ½ü»³xÉR~?wŽ;wî¶ñUuèK¬T¾ÙõׯÿÃõþá«ßêÖ™—´›ÃTzdµãS±bEâ⮓™™©xmýìsÎ_¸È;wY¹6mf~¾í¥nÎÝ<ܔԢdذi3o¿û^q‡aQbŸ„q²ÏEI!·Ä<ÌM‘«´œ¹©¹M™<‘å«Ö0eÆ,Ê”)C÷.°¶Vvù^_ºk¥&Œ}™ï¼KÀÈQT­R™>={P6ûé;¦Æ¥0íæf*=rîñ±±)KojÕÔÿÄ€/°xÉ2þºt‰Å æ)Ú_-=›1ý9$&%ѬIV/_FÙ²eÅ–»½EóÞ|è)©…BˆG‰¾3ëìWYÀ&û¥É~•ÊÞI‰ KVBܺ}›ÞÏõçÀ»Mþ±¡Öˆ—^¦ÿóÏÒÛßßôÆB”riii¬Y·žˆÃ‡¹qó5ªW#pø0ztëªÛ&0h,ü|9x(’¿/]¢¦‹ ¯N ¦i“¬ÛÈ´Z-›¶nc×î=ܾs—&=˜6霜شukBÖY¿ùè×§7Ó&4–ÚµjqùêU½u¦¥¥ñáúØwà RRðk׎àñã(WÎ^Ó€žã»Ýßóû¹s,\0ï–-òôíèñã„„†ñwL U«T¦S‡ŒËNŒ¦¤~C}6Ô§ÂÔ™cÛgŸóõÎܺ}wÝ8šªÛ˜ÙóæS¥re&M(øô¨Ö~øhíjÜŸnT¨qWŸ¡~;–rÚ÷m×–C‡‰‰Á­Ž¯MžÄ©Ógøzç·Ü¸qƒ-<™9m*•*URÔ'cÇIŽ¢:Žs3G¯g_àÍÙ3u58á"/Ox…ƒ?îQ|l’‘‘ÁºÂø~ß>’“hÛº5{~ü‘[>¡¦«‹É}¢¦.5ãñ8ÄUΡüà$ÉÙ¯´ìW: Í~éÈ-1¢Ô¸øÇÔtu¶øÉzjj*—b.ãê¬ÿê´šÜÏâßþ½zø3Ñbbbcólwìø ¦O™Ä[7ãîþ43ç¾IZZ¡áÙà ‹æ½Å†õbkcÃøISIKKcXÀ ‡ ¥K§Dîÿ1Ïóùsr'è«sÉ«ˆ‰½BXÈZ6††píÚ5V‡„ä‰ié+éÞ½ !«WÒÔÃ=Ϻœ }zö`çŽí¼ûö|:¶o§[¯¤~C}6Ô§ÂÔ èþ“Ÿ;k&›Ã?¿K*U¬¨¸ncÒÒÒINN.ðÊÏÜqWŸ±~;–rür2Š™¯Meǖ͸º832h ÿÜø‡%‹¶>„+W¯±fýGŠúdê8ÉQ”DZš8Œ1vl³&d=GŽŸà½… Ø‚½&ïIª’}¢´.5ÇÉã—¹ä„]”X—._æçˆH‰‰eMH(C ²x;Ÿlû”:µÿ¦~€*Ä£Hɳøý»u¥á“ ä9HMMe˧ۙ1u2õêfÕ1wæ 9yÄh»†r'(}¾¿±Ær$(­ßPŸõ)l„oÚÌô©“yªá“T«Z•n]:¡Ñh,’ïà󯾦£¯/súÜÕÄg¬ŸJ%ÿn]iP¿>•2p ™™™ 8ggþ¯VMúôðçLöðMÅf‰\…=Ž-‡šã5‡©<j>ߦêR3C\…!÷°‹+á~a›63gþÛT¯V•çúö¥_ŸÞm###ƒ ÿÇêeKT?QˆÒLí³øsç9¸wôôt>ù¤n½F£ÁÝýi.]ŽQCî:•>ßßXc9ÌÉ`*·Caë¼wääd=ÕÐ"uç7¨ÿóo‰QÛNþqWŸ±~šs,Õ©S€¹2o»¹Õ&){öÀTl–Î¥aÎq\Ôqc*‡š}bª.uÇÉ£WaÈ »(±<ÜŸ&,dM‘¶Q¦L/x«HÛ¢¤1÷Yü9yÒRSÐjµdddäùC×ÖÆ;;;U±äÔi‰çûË‘`nýÆr;¶Î„„û@ÖïÊ”)c‘ºÕ2·5åŒõÓœcIßï¬r-5[QäÒ0ç8V‡¡| ¦â0ÆT5ûÄT]jÆãqˆ«0ä’¢B¨)g¬ŸJŽ%K÷IMn’¢<ŽMÅa,ˆc_™ÄºÃ ,7•ÇCÍ>1U—šñx”ã²ÈgµP¥…B”:–È0%x«CÖñÚsHOOÇ»EK–¿¿«ìKõæä#0õ|SLåH(lýúúTØ:ߘ>¥¬äå YˆlØ >õëÖ£\9{£ukµZ‹å70·jÊë§©cÉÒ}R“›¤(cSqˢĿ÷ïS¥²þÛ=LåñP³OLÕ¥æ8yã²ÔgUžÃ.ŠÍk³f£Õfòþ¢y–¯X³–ïØËg[?ÁA£Ñ-½r•ÃF°ç›/yyB0=ºuaøÁ@Ö¯¸3µÚÙ@c÷FL˜2„ýÉR ›ºjR_¥þÏõ£‰‡ÕªV%xü8*;VäÇ}û lg‰ÔåùJsý0R} !„B?y¬£(VžÍš‘”œÌ¥˜þ¹qƒ† ž¤|ùò´o×–mÛwðòèQür*šÖ…¼ßZiÚf0úúa±¶¶¦±»—¯\)°Î©ËQ“nÛÒ)¶…Bñ9aÅJ£Ñд±Qѧ‰‰¥MkoݺvmZóöâ÷ˆ»~¨èS¼2îåB·§$m3˜N}CmÚhs”±¶ÆÞξÀò‡‘º\iºí¢Hõ-„Bˆ,rKŒ(vÞÙ÷±=vœvmZë–W¬X‘ÆO¶ñ*U¬€«‹‹‘ZÔ¥¶sÒF+‰111)ÏûßÎ_À­NÛ=¬ÔåjÚRšê[”.ý‡ ¥µ_'ƒ¯˜ØØ?bÎ/`Ä(6nÞ¢ºmsˉ’ÇÔ1"„0LNØE±kíÕŠ#ÇŽ’’’J]7·<ë|}|øv÷¼Z¶2Z‡ÚôÑ–`*mtÅŠ‰‹»®» ¯4ÆÐð Š<ÌÝ»w ß@Rrý| Ô©6¥xþxÔ(lªoK¤eÅ'˜*—žžŽV«E«Õbm­|’ÝÜx å‘È¡47†;¹%F!D±0÷¹ý¦Ê¿x»÷î1~Lnuêà Ñ`¥ï2²Jrøú´%*ú GŽǧM›¬emÚpö·_9tø­ZxR¶¬þëc†ò.˜ÛSå\²Á}æ¬éÊTÔkª?BˆÂ‘v!„•©çö¶\•*•ILL䋯¾áîÝ»|¿wÿûãO³bU’ïÀɩժVaÛö´kÛȺU¦±»¡áð1pÿ:λ`nL•sÐhèåßÅK–òû¹sܹs—°Ÿº^SýQBò5a˜Ü#„â¡2öÜ~K”«]«ãDZ.,œµ¡¡xµl—WK³ãU’ï ½Ÿ}ù%M»ë–uðmÇâ¥Ëiãåe°nCyÌ탒rSƒ'²|զ̘E™2eèÞ¥3ÖÖ†/á+ÇX c$_ƒÆÉsØ…BˆbPRò.ܺ}›ÞÏõçÀ»MþÑdLIé%™<‡]!„ª]üãjº:êd]Q´ä–!„â1réòe._Ž¥EófÄ߾͚P† TÜa !Œv!„â1’p?°M›™3ÿmªW«Ês}ûÒ¯OïâKa„ÜÃ.„B!ÄC ÷° !„Bñ’v!„B!J09aB!„¢“v!„Fõ2”Ö~ ¾bbc Ë7»¾3XGÀˆQlܼEuÛæ–+j)©©è;~ô-êYêøš=o>ËW­Ö½7µŠú»Jž#„¨ðÐõ ÍúýÓÖí;8u’¥ï,Ò­×h4&ëðkçCÃ'ŸTݶ¹åŠÚ†M›‰½z…ùsfw(¢ÒwüÈ1U²™Ú?Eý]%'ìB!ŒrÈuBnkgKë2888¨ªcÌK/šÕ¶¹å„âa*êï*9aBaQQÑ|µs_ºDM^LÓ&@Á´õG'$4Œ¿cb¨Z¥2:t`\ÐèušS.--5ëÖqø07nÞ¢FõjFn]óÔÛÁÏ—ƒ‡"õÆ«ÕjÙ´u»vïáö»4iìÁ´I¯àìäĦ­ÛÛô ûüL¿>½™69Øä¤¥¥ñáúØwà RRðk׎àñã(WÎ^Ó€žã»Ýßóû¹s,\0ï–-ôމ±Øµ3wþÛh3µº«„©©©<Ó=»wã•qcHNN¦kï¾|º)œêÕªY$fcŒµ’þfddòQ?ìÝGrr2Ú·'*úËÞ]LMW‹{~‘GޱõÓíܸq“§5bÚ”Iü_­š&÷¾ãÇÉ©†Þcʱ¥G·®ìýé'þüó/jשôIiôÔSŠ?+ùÛðlÚÄd9SûÅÜzõ'‡±Ï¡9Œ}æsÇeÎwœRr»B‹¸ǴɯðÅÖ͸»?Í̹o’––V`»û÷˜>k}zö`çŽí¼ûö|:¶og²~¥ålll¨éêÊâóÙþ½zø3Ñbbbcólwìø ¦O™¤7ÞÐðì?pEóÞbÃú±µ±aü¤©¤¥¥1,`ÆҥS"÷ÿ˜ç?ncc°äƒUÄÄ^!,d-CC¸ví«CBòÄ´ôƒ•tïÞ…Õ+iêánp,ŒÅn¬_Ÿ¶œŒŠÖÕ}ö,iiiŠŒøoÙ™3ÔtqÁÕÅÅ¢1bl¬•ôwuÈzŽ?Á{‹¾þC¬¬­ˆ½rUW¶¨úp3>žoÎeSX(•+;26x²îgcmê;~ S–Š}çî=Lû2Û>Ù@c÷FL˜2„„ÅŸ•üm()gj¿˜[¯±þäPú]¤”±Ï¼>æ~Ç#'ìÂl+×|Hÿ!CMn·lå*úJJJÊCˆJQ\úôêA£† qt¬Äˆ!ܺ}›+W¯ØîfüMÒÒÓiÛÆ›'ž(O]7·hÔ(zûûS¿^]ìííÿ¿½ûŽ‹ºþ8þY( †–nSqkîÌr›Š©å(wšš–3s‡#Ôœ9Z¿,K+G.påH+E+¨ˆ8Öq÷û8ïð¸Êûùx|É}¿ßÏúÞ]o¾|¾ïO¶õd×vSõ4jÈ£¸8®\»À±ã'د1÷îkƒ©“§ÎÐ$ q®·ÙsÇ:»þ&''óíw;xâ8*W¬ˆ·—cß©=//ûЭK'*V(·7S'MÄÆÆ†}š]§)¹ÙöÝ»QËߟ’%J0zäŠ{¸±gß~À¼ÏŠ¡:ŒgêºX[®9ýó¿‹òеßqÆÈ”‘çÒÒÒHU¥¡V«M,„x.x{y¡P(P*ŸØWîÅ©_§}@×Îx©^=“eZrÞƒøuï~þøóO>|HìýX’dxÐmïͨhT*•Þd …‚5ªs5òš½²ÌÈë×Q«ÕLž>›ŒEÆUi*”Êx½sÌ.ßšz\\\¨W»6§NŸ¥ü‹/rôø ÌÍÅK—?vœ^¯wçä©ÓŒ9û?íþ™ÉS§S¿^]>™3Ëhyæž§T&ñæðQ´jÞŒ!ƒPªtiÆNœdv{SS’Q«Õ¤¥¥akûøÑöö8::š,ÇP™®.EX÷ÙJŠ{xXTFnר„SgN5e|}hÔ”Ý?ÿJû¶­¹EZ5‰Š¾“§mëÇ:³¿*• µZZ­Ö;?S^».{{ìíís­Î¼l{[[œ¬þ¬˜:ÏÔu±¶\SýÉNvßEyÅÚï8£eæbû,²aíöíÚɾ];2h µkùkÞ·k'e}}sTþÆÍ[˜óÉ‚\jíó/°U[ƒÿÖ©T©­š·Ðþ¼pÉ2B×­·¨Œ‹—.QÕÏ/Û2Eî³4-—©ïù2®^Ú|ðþ$Ö¬ áБ0îÆÄäÊy/EðàáCF¾=ŒòåÊá¢P`cèö^6|ˤ?8xöüyíkjµš‹—¨T¾¼ö5•Jev™Þ^¥pQ(8n~C¬`N=AM8}öGŸ 0 ýµ€Îÿõ'‡ÃòRýzØÙÙ=•6›;ÖÙñɈΞ;opžöA£Ñù§†¿/\¤Bùrf×ièý£ûZn¶=!A©÷ó_#(_®œÕŸS発.Ö–kª?yÍ’Ï´éÔ•wÆNàÂEý¹f†æº_¹ɸIïór—n¼Ò£7‹–}ʬyóõ)x–9Bï‰ô T«âgä }÷bc‰‰‰¡ªßãà1k™"÷½=ôM½Ô ¿›ñÜ{Ç»ænL IIIœ>{…BA±bÅråžöÑ,ŽŽLüžöøM[¶ò×…æÏþȬ´eæ~ÞL¥û2'}œî6cu›Jó•Ý~Sm( âââØð+BW£LPòBٲ̛9GãsqÍ=ïŲeùö0V¯ßÀªµkiØ > Zö‹Ø¸Ñ£Xºš÷¦MG¥RѨ~–.œMÆí¾íÚ~ì8}ƒƒ©[§.‹æÍ1Yfðýqrtdɲ¢ïÜ¥¸‡oôéE5?ó™7‡9õ4 äëï¾£VÍÇYEZ5eþâ¥4l˜ã6?Š‹Ã³¸ái}z¾ÎüEKøïêUæÏžir¬M?ú–._ɸÉS)R¤/·i €­­Mžõ A½:Lš6¥’:µj±béììì̪ÓÐûÇÐk¹õžiØ ËW…sïþþ5Xµl öööVVÌ9ÏÔu±¶\cý1E­Vs+*šR¥Jš<6+K>óÖ~ÇchÔl36;À>cSdl΀+ÐH™¿ØêZ³Ø´uÇŽŸ`å²%z¯¼h 11÷˜úÞRU©Ìš;Ÿ^(«ÍM:àÍ¡tíÜ™>=_gÙŠ•\‹¼Îâùé«ï­þ|½Ñ©6oÛί{ö1uÒD<=‹sæì9‚P(|»ã{êÖ®…££#{;@èÚulÛ´^;§>xØp 'FA©’% ]·žÃGÂØñÕ¶'Þ0ÁÆcckËÔ÷& P8ºv¿Ÿ9Ë·[7ãääd´OS`«¶„íßóÄ¿ Yùûä»/·j¿X“SRè3 o/–/Y¤=îPؾޒ¼Lš6èÛ·YºJû—•JÅk}úÓ²ycF=ù$yV­:tD©L¢šŸ^^¥8v•JÅÂy³µwŒ>Y²”ÿíøJ+P¶Œ/‡Ž„“––ÆgŸ.£NíšÚrtç°*aáG©\©¾>Þ„;NJJŠEsØ×¬ÛÀ?ÿ]aþìøûÂFÏÞŸ~Ôö7üØqœœœx±l¢oßá½iÓy£Ooí/,k7läÒå´óݲ–qé2¦LeôˆáÔ¯[—®üGQW½;ò9}‡¬üŒ“§ÏðÁûïáêâÂÆ-ÛØñÃNƒsؽ cî‚Eìúîmÿ‡ŒEŸ¯Óºe “ŸK?oª´4&ŽM€¿Ø¶wÿÂ÷_mÃÕÕ•Õë6vô(ÓߟŒ““#!«B¹tù¾Ü¼{{{ƒ»±ºM}ÏÚoª B<Úu~…93gäøA;kÜ‹¥s÷øuwޤüìCn*(ÏÒåÖu)(ý±–³‹ë8à8(ÄŒ-5cSêŒM«ÀÎ;1•ÎÈÞÞžIãdzvýÂc×/{˜2q‚Ye§¥¥±aó&KU¿*”,Q‚vmZi—×ÎI:0Cr#õ“Z­fIÈrº÷îGÏþ˜¿x©v_÷Þý˜öÑ,^ëÓŸ>‚9xø°ÞÏý}€˜˜{Œ?‘®¯÷¢ý+ÝYñÙj³ÆË{û"zwAx¥K'Îÿõ7á‡ÿlóf~Ä”÷Ò¯ý×ß}Àí;wØñÔ/WŽ «?cÞ̘4n _lÿÒ`y‘×o~¯Ò¥Yº’g}ĸw-ÀóÂ¥KTõ{üdü…ˆKT©\Y¯¿M7¢^ÚxzzR£z5üªT&%5EïÝà[·LµZÍ3g1aô;´iÕw^ªWOïxÈÙû89%…oÌHɦ?«¢R©øóï¿ô/í+ÿ]!Ђ´q–|Þ²K÷emª>Kê6%'é…xVÜŠŠ"U¥¢¶þLá»tù2e|½sæwžG¹q] ³;%ÆœtFujפmëVL˜2éS&Q¢„§YeߊŠ&11‘jU ÿI)'éÀL±6õÓ‰ßçÏ¿/ðÍÖÍØÚÚêå4¾}›e P¶Œßÿø#³>^ÀæÏWãUº4_~ó?–­XÉê!xx¸óÞø±øúøð(.ŽACߦYP 5kX¾Ð…1e||HNN&>>¢E]õö%(•ÄÅÅçÊïööÚ ¸uËé‹+DFðïWP«Õ4nô’öO”mZµfî‚E\½vÕ`yW®¦¿žùÀ€[17‹Ûqé2=»wÓþ|1âU³<ÈxóÖ-ö8Èň>|Äß#xUg:ÏňK¼Þ­«Á2Ïž;OB‚’ À@£íÈÉûØÜ”\`ú³jooOËfA ;J-Ž„‡€““"",NfÉçM7ÝWn¤êËiz°ÜJ(DAæ¬P°èã¹8<¥Àìjd$‘‘ש_·1±±¬ ]K¿Þ½sTæÓîÃó(/®KaV`vsÓùúú V«qt0ÿîl||~§²H‘"zûršÌÖ¤~z¡lYîÞaÁÒOiÑ4—t–¶±±¡l™ô) mZ·&dÕjí|ض­Z°ykú¼ç"EŠ’’º›ˆ¾sµFMLL¬Ùí6Wìý¸¸¸<¬¸8;ãììDÔíè\­3óûŒ@;11=0MKKÓ9& ›lS쥥¥ÿõÉÙYau;bbîqïÞ=ü*ë܈ Ÿ^ÚŸO9Ëœù Пw†¿]^멽CžYFÕŒ‡T³–ùûé3T®TÉèƒÙ9Ok—bvJ.sÞÇmÛ´bɲF¼5”ƒ‡Ãxµk³Ï5ÖNsd¦ûÊ­T}9I–›é…(¨ÜÝÝ©WÇý©ÕÏúÍ[˜>k¥J– û+¯è=Ïd§Ý‡çQ^\—¬ÀN‰1'ÑÕÈH6oÙÆ»#ÞfáÒezËÒBöéw||Òƒ|COZç4˜A9LýàãíÍ7[7óR½zü°k7ƒ† 7¸‘}–_@ìtæÄF\ºÌô™shØ £GÈ•?õ%&¥è-÷«ÑhØýë™óW£juvþ´‹””½óR,\681)‰äŒ2Ž?‰F£Ñ¦u*_îÂÂi ?~FCåŠõÊQkÒÇ1óAàÌyë Ê‹ÚtñR¥K•ÂÃ#ý‹>9%…+W¯Q¹b%í1ë6n¢×ë¯Ñ¥c¼½¼¸ríÅ=<(Y¢„Á2²þüèÑC4ê4ŒÉµ´vf¤ä2ç}Ü n]ÅÅséòe.F\ÒfbÉ‹”kÙ¥ûÊiú¸ì˜Jó †ð IDAT¥»?¯Ú Daæ_£:ëCWrà—]|õÅ&‹’ëW¯Ê—ùÞyu]ò«?ù­Àì¦Ò©Õjfü ýûö¦o¯žT«Z•OW~¦=ßXú·bÅhÄÂ¥!\»~„ÄDŽ„‡£T&å8˜!9Iý”)!!¸¸8ZµhÆ´I¹~ãñ –“—ÿû7·bT«ê‡­-Ñwnk÷ÙÛÛ?¾K­óoSi­bbbxgüöìûCGÂ?y W®^eä[C³=çí¡o}›á£Ç²wúy“¦MçVT”Þq¦ê~ðàƒ†¼Å‡³ç1aú®}{ö Bùò4jø7oÝbÐa|8k. —~ŠƒƒÁÞЖáîæÁýû]»ooj×òçú› 6œ³æ°hYÈõk×ňËzsÉããâHKKãêµkÚ÷á»w9÷çyîݻǹ?ÿdUèZªêLÏúïê5Š+¦ý…,k™~UªpæÜyŽŸ8IrJ çÎÿ©]RdÝ3¶,¨)µ j»Ä³ŸîK!Äóí¹Kë(òßÓLku!"‚øøjf,âQPSjÔv QÐõ8˜M[¶æIÙÉ))$É€ô,KII¡qóVܸy+ÏëR«Õ,ú4„—»t£WÿÚÌYÖÈkbMÁÆóÃO»ò¨EBäž›%F俼Jk¥Ñh˜¿h uëÔÆ«TinFÝbõºõtîÐ^û@hAM©UPÛ%DA×¼i ^:ËÜ´qó£ X óìܵ‹S§Ï²uÃçØØÚZ<íRW~\yˆç™ì"[y•Ö*%%…"EŠºv÷bc)[Æ—×_í¦}!/ëΩ‚Ú.! º·‡¾™ßM&DFÞ ºŸžžæ­i"„xz$`O£££vÙy!rÓúÕ«ò» Ï”í_Ë÷;wr/ö>þþ5˜8æ]¼½¼P«ÕlÞ¶ŸvÿLìýÔªé¯ÝéÓ‚š6áð‘p®]¿FùråyoìÎüqŽïwþÈ;w¨_¿S&ŽÇÝÝ]{ŽîóÁÆӢy‡qåêUÊøø0aÌhj×JŸn–––Fèçëùuï>iѬ§ÏžaÉ'ó)ãûøáçÍÛ¶³~sz£ýÑ­Kg&Žm²™RSSY¹z GÂùs÷¥K•$xÀth×V{Œ©¶f-ï³5Ÿ³ïÀA’’“iÞ´)£GŽÀÙÙÉì~¯þ|=¿ìÛ‡2AI“ÆÍ¾ž^}?˜¢}¾æbÄ%Þõ.÷ül²î.æû`÷ž=T(WŽÍëÖ˜õ^èùzwvíþ…¿/\`îì™\º|Ùà5ÉIûL]§ìÞ¦®‡®©ÎÄY¡`꤉Ú×6mÝÆŸýÍ'sf™}„È 2‡]! ¡Ì lÆÔ)lÙð9íÛ´ÁÝ-=sÔÚ ›Øà óf~ÄÆ5Ÿá`oÏÈ1ãõÖ\øýÔi¦¼7žo¶nÁ×Ç›AÃÞæöÛ,š?—õkB¹qó+×|n´ ÇOœdÒ¸1üoÛjԨΔjëXº†c'N²`Þl6¬ù [›'Ò—¼Ñ§7Áoô§M«„íߣ½`N =m__æÏžÅÖ ŸÓ©CûôU“¯_7»­º}ºœk×o°>t›Ö†rëÖ-V„†š]ÖÊÐ5=q’sg³qm(N ó4GvuOž0޾={Ðéå— Û¿‡ÍëÖæãâOCxùå6„®¡¶l¯INÚgê:eW§9×#S›–-9rô¨Þ'GÂÂiÕ²¹…£,Dî“€]! ™´´46lÞ¤ñc©êW…’%JЮM+ )))lýò+&KÅ åñõñaÆ”É$$$p8쨶ŒöíÚR¹R%Š{xЯW/4 ýzõÂÇۛʖ¡K‡öœ3±ðVûvmñ«RwöëýØXnܼIrr2ß~·ƒ÷'Ž£rÅŠx{y1ö‘f÷ÏÜ>dz­Û+T(Ÿ~ÜÀ~}ññöâï Íj«®¥’~ü‰!ƒàááN©’%6$˜ƒGÂÌëwJ ßä ßæ0§™ÌÇaƒÓ¹}{*U¬íJÒ¹Ñ>s®“.s¯G¦&’””¬-óþýD\þ‡ &MrÔ'!rƒL‰BˆBæVT4‰‰‰TÓY°+ÓͨhT*•Þ¢ …‚5ªs5òšÁòÊ•{€¤Œ×Ê—¥Å¤²ãíå…B¡@©LäVTij5~•¯?`I–zKûðàÁ~Ý»Ÿ?þü“‡{?–d#ÙFtÛª+òúuÔj5“§ÏÀ&£Åª4Je¼¡bž(+§ý¶TvýÈdî8::æÍCøYÛgéu²ôz8::Ò´IcŽ„Å¿FuŽ=JÃõqqvÎýÎ a! Ø­Tò=÷8˜íÚ0 __‹ÏMNIA£VëÝ ÉÍ>uXøÝê»ñVKó^JNU£Ö€Â!ÿÿèSÚ"D^ˆÒÓø)RDo_jJ2jµš´´4lmìíqtt4Xž¡ ÒÆŠPÓÆF€J¥B­V£V«õÚ`.Kú T&ñæðQ´jÞŒ!ƒPªtiÆNœdv[u¹º¤gUY÷ÙJŠ{d¿è[ve¥¦¤ä¨ßž…ˆú‘Éš÷B^µÏšëdÍõhÓ²¡Ÿoàí¡orèH­e:Œ( $"y†å$MÚÆÍ[˜óÉ‚\nÑcmk¥º¯ù]µïS¾ŽÊ³öX¢ µEˆ¼àããƒZ­æBDÄû|ˤ¯|öüãé,jµš‹—¨T¾üÓiŸ¯ozLL©Ñ¥R©´ÿ¶¤/EðàáCF¾=ŒòåÊá¢P`í¢³Þ^¥pQ(8nÕùÚv[Ðo] …×®FZu®ÑöXù^н&9mŸ¹×I·Nk®GãF¸Í•k×8óÇ9™# ØŸao}“F/Y¶ÜüÓ2®CI‚ª¸äw3„¸+Fó  . áÚõë$$&r$<¥2 …‚.;òÉ¢%\¸x‘Øû÷Y²ww>¥ï…‚Ní_fþ¢Åü}á÷ï?`ý¦/²=¾T©’œùã<ÑÑ·ILL´¨žžÅIHHà;~àÁƒü²wÿ\þתvÛÙÙѯooV¬^ˉS§P«ÕܾsÇà/FÖö{ø»cX½nƒÁókùûóÃO»ˆŽ¾MôíÛìØù£UýÐmµï…¬×$§í3ç:e­ÓœëáææFTT´öM›°dÙrêÔª…‹ËãÿMþ`›·m7»ÍBä¦|sìÄ B×®çʵk”ð,N«-1l@ž¤3–ÞiƬ9¨5jí‚ )))tíÑ›Ž/·ãÝo˜˜HÛίðåæ œ>}–;2˜šËœÔ^YSa5jPߢT–¦IË”]ú«œöI׫ˮÒ'Àž ݵ?¿\Ó•=ÅóOt2/x:0ãU/”W°úÀ=Vîàçsqôjì·¯z‘ªÒ°øç»ì:÷ˆ¤5mü‹1¥Ki\m´e ò໓9w=‘ehZÙÅh]€Ñr³kËáˆxÿÿw’)Y´jcBÇRf½Ï…(ˆ¦MšÈâOCxkTzê;¿Ê•¨T¡"ÎÎNŒ=Š¡«yoÚtT*ê7`éÂùØX{ëÙ ãG¿ÃÒå+7y*EŠáå6­°µ}² Úµ%üØqúS·N]Í›cv^,[–‘ocõú ¬Z»–† êÓ°¡õ¿˜¿Ñ'GG–, !úÎ]Š{xðFŸ^Tó{òySý¶··£sûö”-ó8壸8<‹žÞ1jø[Ìþøú L ÏâtéØ;{{«ûXý^0tMrÒ>s®“¡:M]>=_gþ¢%üwõ*ógÏ u˼7õfL}_[¶Z­æVT4¥J•´dø„È5†>q¶›`Ÿ±)26gÀh¤Lˆ_œ“ŠãââéÜýuFAÛÖ­¸s—äädªU­ Àêu;z”éïOÆÉÉ‘U¡\ºü_nÞ€½½=ÁÆ£P81ö‘xzz²tù öìûÞ=^£G÷WQ©Ò˜üÁ ükTgÊÄñ|¼h 11÷˜úÞRU©Ìš;Ÿ^(Ëı£Ù»ÿ7ºœ];¾àÄ©S¼ÿÁ‡÷pãë-éÁíÑãÇY¶|Û7o xØpììì7z^¥Jºn=‡„±ã«mØÛÛ­ Òƒë·n2zÔªV®B_œœœLž§ËPÀ®P81zäJ•,ùD›t­þ|ý+Âå´Oº ìÎŽ6LéR/7{–þr—½ÅqhJ%ìílXúó]®ÝKaI?_m|ÍG*æöð&5MͤíQ”/åÀ‡¯ziËŒ¼—Ì”®¥ñ÷Uð‚§= [“u™*7k[%ªi2ë2Sº”¦sbÜ~˜JRªšše½ç…Ö»Kçî=8ðën ñJÃí:¿Âœ™3´¹ÌE~ƒ¾ƒóËßéÝa"78»¸ŽŽñ€HÌØR36 ÎØ´òmJÌݘ»¤ªT4 hDÑ¢®T(_^¬çEZ1Sé5äQ\W®¥?ù~ìøIöëC̽ûÚÜ¿'O¡IÀãE,ºtê@5?¿'ÒO™›J*k*,KSPbIÊ.CrÚ'c^©çF _'<]‹ðVËâÄÄ©¸v/Åà±qÉj¾:~ŸwÚ–ÀÓµ^nöŒi_‚=Æé7æåR¼ÖÀ?oG½‡D³«ËÜruÝ~˜JªJM‹ª.SØRÙËQ‚u!ž²K—/SÆ×»Pë·¢¢HU©¨íÿä‚M"÷{Ž£ÇOþZ@çÿú“ÃáGy©~=ììLyÖ¦öÊiJ0KeM¹eÌÓh[ªúqïëa‡«£-¿ýmÝüì˜[®n[25ªàÌü^>|9ª{ÿŠãöÃ'—%BäÿÕYº’¿ìâ«/6Ñ»ÇkùÝ$Q”-ãCøo{síÆ”¹%ßöGqqü¸ûgîÆÄ””Äé³çP(+V,OÒŠ™“ÞÉË«4%Kx²ý«ohš‘{ÕÅÅ…š5üY»a#:ó×sZWnžg C)·ò³mÞîvœüWÉÍû©(SÔØ±aHKOìºCØåÒÔ¢¤òç ë¦÷hûaF¹YÛòP™Æ7'pûa*‰)jŽÿ«ÄÙÁwçôg$Õ—B!òR¾M‰‰‹‹cÿÁC¬]2AÉ eË2oæ íEy‘VÌœt[Íùú»ï¨U³†öµAM™¿x) æj]¹yž¥ ¥¿2%/ÛöJ}7\L Ó¢iXÁ…ÕƒË2¢U œìm™½#š[TxµcX‹âø—ÉÙŸ¦ÊÍÚ–^)Í/çãX¸ëñÉÊ—p`ù_ím%Õ—B!ò\¾¥uB!„¢0±6­c¾.œ$žO•'^Èï&<5—TËï&!„â9'»ÈuÄ !„Bäž|Ï#„B!„ÈžìB!„B`° !„BQ€Év!„(Ä4šœ­†,„¸œ¤$Ï$»BB†G÷ïs?ö.‰Ê„ünŽB<—Î.x/I1î° !D!£Ñhˆ¹EB\¥}ÊRÌÍ=¿›$„Ï¥GpûÖuRR“(QÊÛêr$`BˆBD£Ñðð~, qqT®V3¿›#„ϵbnîssçò…óØÛ;Z]ŽY´Dïü÷§Ï`Ö¼õ^ÛøÅ&¼?РV§±aó¼Ö§­:t|¢}í»vãä©ßµ?_¸AÓVmôú»ë—_1z,-ÚµçøÉ“OôÍXÌœÉÔ?Ô›’’L»Î]Yºb…öµÄD%-ZqóÖMʆÍ_0hØ[4kû2ý æì¹sÙ^ CmËzŽ?ÆÀ!C jÓŽW{õayh¨Áò²»F²ôÍz° !„XRR×oÜ fê9*gÓ–mü¸k7M›Æ¶Mèж-înnzǤ¥¥1yú‡T©\‘!ÁõöÙÛÛS¦Œ/ æÎæËÍèÒ±͙ǵÈHôëÃàoжuKŽÜÏ{ãÇèß¶U+‡‡£V«µ¯>Fë–-X½~ûüÆüÙ3Ùüùìíyû1¤¦¦šÝÇEË–Ñ¡}[Ö¬\NíšþOì7VG³À@~?uF{ìÙsçHU©8tøˆöµ3üA__|}|8vü“Ççû¯¶ã_£:“§M϶½¦ÚöèQ<ߟF—Nùéß²pÞlZ5köÄqÆ®‘x~IÀ.„…F#Û³²]¿q Fƒ›»‡Ñã2oâúY¥Jcýæ/˜6ö/_&¨I’“SزíK&O˜@Å éå8u <ž^vÖ÷m–÷26øM:·ï@¥ŠqttÒ;ÞT6äQ\ÿ]¹ŠFáÇN0°__bîÅyý œøý4µõux¹~U*ãîîÎÀþý¸ûøØ¬×ÆPÛtÇëÎÝ;¤ªTP´¨+ÊW ZÕªze˜sd+¸[NHÀ.„B`%KxpóæM«Ë¸…R©¤ZÕìpܹk7?üøŸÌž£ƒƒÁcIÀ.„B`nnn÷ðàèñV— 7%«—ê×ÃY¡àËo¾1¸_©L$ø­á܉aHð@ÌC¥ŠÙ?ôjH›Ö­8ÀÁ#Gh“1&%5µZMZZšÞñvö8꺚ܦ4§ŽfM8uú4·ïÜA£QSÆ×—fÍ‚;vŒ‡r+:š:µke[‡ÕÍÃÖÖ–K³øã±wpཀྵ0qÊT½cL]#ñü’€]! %lÏÐÖ·wO¾Øº›·n9.ëu}ü³¯7jµš ³=×Û«4³¦ÀæmÛ9pøðÇ\Œ¸ÈÃG5ü-*”/‡‹³B'@}\ŽJ¥Ê¶Í•«W8söš6ih(ã›>'üì¹?´ÇªÕi\ˆˆ Rùò€…BÁի׌ô9kÿõ7sêhÖ4Sgÿ üØqš‚8ÿçŸ ã¥zõ°³+b¤¾ìÚ`þëõêÖfƔɬ]¹œƒ‡p7æ®Ù×H¶‚¾YOv!„¢€ëÛ³~~Uðæ0¾þßþýï ‘×¯óóž½θcíæîÆ­¨hƒw¡ÝŠ£EP /ãZd$ J%‡ÃÂQ*õŽkÜè%†Ä̹ó¸~C ާgqâãøö»ïyðà?ïÙË?ÿü«wL©R¥8ýÇ9¢£o“˜¨_6€£ƒAMX´l9uj×Â5#‡¼‹³3];uäã…KøûâEbïßgñ§!ww§QÃÔªéÏ?ýDtôm¢oßfÇ?X4†æÔáåUšR%=ÙöÕ×6ÀÕÕ…šþþ¬^¿¦M O‡É ãâøq×nîÆÄ””Äé³ P((V¬˜ÞqÆ®‘x~IÀ.„Bpvvv¬\º˜¡ƒƒÙ³?CGŽâÍ·FðíŽïIHHŸîÒ·g~Þ³—IS?0XÆ´÷'Q¡By†Ž|—.¯õ`Ëö¯xôèÑÇ ðuk×fÒ´izóÓ_|áF ‹Ðuëy½o>B£—èÛñå¶Ô®YƒÞ1õ£™ÛѺeKNüþ»v:L¦ñcÞ¥I@#&N™FŸÁÄ=ŠgÙâØdÜÆwÄÛ”,Y‚^1rÌx|¼½±w°7{ Í© Y`SbcïQK'“KË  ¢£oШ‘EõY">.Ž}ÒðÚvêÊ÷;wòñ¬ ÎUÏî‰ç—¡ÙV¶›`Ÿ±)26gÀh¤Lˆ_ü´™—>˜9‹=û~Ò¿ËúúÒ­kztmÁù}æÄ©S¼;n"mZµdö ý/ãàaÃyõ•.tíÔH_Z£Vãää”+u[:F¹]¿%²ŽEN˜êGNë2T~^]NË7t~nŽyvú L‡vmЯ¯YÇ›jS~¾Gó“F£A¥RñÏ…óT¯ÝÀô BäÈë×é30˜_v~«‹áUZ…xýýÇïÔh68ÄJ 1cKÍØT€:cÓ*8i>êÞ­+ûvídÇ—Ûè×·«×~ÎÆ-[ó»YzöìÝO£õ ?v”䔣Çnܼ…9Ÿ,ÈÕú-£¼¨??äu? •Ÿu>Íó­Õ¼i ~:™rêyy ñ,:xø/Õ«'Áº€p°·ÇÅÅ…%<éܾ=C³ýëoó»YZ©©©üvè0#Þ†MŽŸ8ùÔÛPÐÇH<ßÞúæz9•ß_ÉVX·=û÷Ó¢EP¾·C6Ùžþf=»ýœªS»&W[ó9û$)9™æM›2zäœÓÿÌ~ìÄ B×®çʵk”ð,N«-1lˆÉ}Y;qWWüªT¦ÑKõùíà!š5 4xìæmÛY¿ù ö8D·.™8v´Ác‡…óùÆMlXýYŽÇÈTýjµšÍÛ¶óÓ½ÿ€Z5ý™8æ]¼½¼ ô7û±15æY™süö¯¿åû;¹{ÿLó.{;`Ö8†=ζ/¿âλT¯V‰ãÆðBÙ2tzõu>ü` /Õ«ÀňK¼5ê]îùÙà8yy•¶j삇 §Eó ãÊÕ«”ñña˜ÑÔ®¥¿’^NɃïÅ TIDAT¯±÷ÖéÓgÙ±ó'ƒõ[rͲû¬eâ’––Fèçëùuï>iѬ§ÏžaÉ'óµ™ ²k“%Ÿ!Dîº~ã&—ÿù—f†ÿ&„0LvîÝ»‡§§§^@±øÓFÁèQ#´Á¢O—sõ¡«HU¥2kî|V„†2qìhâââ™4u:£GŽ mëVܹKrr2€Ñ}†üºoŸöiõ&³$d©©©ØÛ?ù°Í}z“¨LäúÍÌšnøÁ£L†´´ìsòchŒŒÕ¿vÃ&ÂŽeÞÌprr$dU(#ÇŒçËÍôúajlŒ¹!¦Žß¼m;¿îÙÇŒ©Sðô,Ι³çpws3{ïÆÄ0ûÃ(N„®]ÇðÑcùvëf“s£³+ßÚ±;~â$“Æ¡TÉ’„®[Ï”²ã«mzc›ÓkclLnFE1qì»x•*ýDý–^3CŸµ¬V„®á÷ÓgX0o6®..lܲí‰l ٵɒψ"w•-ãËÑûò»BzD‚RùÄÏ9£ì¤¤¤°õ˯˜<~,+”Ç×LJS&“Àá°£zÇScž•©ãÓÒÒØ°y “Æ¥ª_J–(A»6­P(fõ  [—NT¬Poo¦Nšˆ û4û|SÌ»öíÚâW¥2î ìׇ{±±Ü0cUDK®1]:u šŸßõ[zÍàÉÏZVÉÉÉ|ûÝÞŸ8ŽÊ+âíåÅØwFšÝ&!„âY#wØIŸ±ýëo±±±ÁÇÛ›Þ=^çµn]õŽqtÔO«yý:jµšÉÓg`“‘lG•¦B©LO¯UîÅ©_§}@×δS#ŒíËêpØQll4T«âGbb"Î +”ç·ƒ‡­J/uùŸ4ìm½×^îÒ €À&,š7ÇàyæŒQvnFE£R©ôT(Ô¨Q«‘úKNScž•©ãoEE“˜˜ht©nK888P»¦?×®EæJy`ÙØeÊ\;k~åÜ*ßÝú-½fðäg-«[QQ¤©ÕøU®¬}ÍÔâ‚–ŒIa‘ƒ#…B§]bØØ>]û¢X±b4¨[WïuooªU­ÊoàææF”ÎrÔ¥J•äÌç³]:“½½E]s?nÖú] ºtìÈ'‹–p!c9è%!Ëñpw§a–T}ÆÆÆÔ˜g SÇ»+Fó  . áÚõë$$&r$<¥2ÉìqÜöõ·\Œ¸ÄýûYŠZ“Fó ¦Ôò÷營v=^F{çFÇ)§c—×ׯÜ1ÑeÎ5³”‹BA§ö/3Ñbþ¾pû÷°~Ó•ai?ž'666¸¹yp÷vT~7E! »·£ps³þ/Í2%&‚ßè“£#K–…}ç.Å=]{÷ýF»6­ þÙ¿m«lÙþF¿KŸž¯3Ñþ»z•ù³gÒ¡][§op0uëÔÍv^z@£Fy²Ì²¡úÇÅŠÐÕ¼7m:*•ŠFõ°tá|½å £ãÆÇxb,L?mÒDÂ[£F“ššŠ_åJTªPgg'³Æ±A½:Lš6¥’:µj±béììÒ?V£†¿Åì?¡Ï Á”ð,N—ްә.c¨üœŒ]^_›ìÎ7ÅÔ5°ÆøÑï°tùJÆMžJ‘"Ex¹MklmÍkúñ<°±±ÁÆÆ—bn¤ªR¸rù"%K{ãZÌ-¿›&„Ï¥øG¹{; gWW\rð]kèÿn¶›`Ÿ±)26gÀh¤Lˆ_lu­B‘‹îÅÆÒ¹{üºû‰_|…¾ôt®i¤¦¦¢Œ‹ãÑ£X’ÌÈ%„ÂrNÎÎ+Vç¢E±··§˜›û8à8(ÄŒ-5cSêŒMKî° !žy—._¦Œ¯·ëf°±±Ñ>díêæ†ÂÕµZƒFBBˆ\eƒ ¶¶éß¹™›µ$`B&tEXtCreation Timemié 14 dic 2022 23:10:40 ]Ê IDATxœìÝw|õýÇñ×¶,ï=;{ï0V™Z6…PF”Qf™-«…2ÚÒöW(” -mé Ê&ÊJHÂÎðÞKûôûC¶b›,%ŽÛïg÷°%î>wR¤·¿ßï݈ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÈ0dìÆåõõ²EDD$y±­ü¾KvåKÞèõ³÷c """/Æ–ƒC¬×ϤìÌ—|ïpÐýv÷ßÍ)HDDDú”Õù³{è*¶2¶*™Ñ»ÅÁìösKÁÁ–L!"""²[D;öÖîïþs›ì;¸ò-µ2˜½~7{ݯ‘gcs`èúiÿ®ÞZhØnˆØ‘ˆÞ­ ½C‚Í¢{pìÀ²EDDd÷ Ó38tMQz†Šî­ÛíÒØ^ DïðÐ}²±9<Ø, H<;°lÙý"€hj†ÎûlÄCD”øw}÷.®ïþ­†ˆý’ïì+¶é@Ù Ï?{Ƹ1cŽÀ ˜ŽÀÙcĈÑòùêÕÏrè÷ë€f67Dz=Ãb;¶õEoÐsŒC÷Ö†®)˜X¾æó{‰ Ù³5—Žwð PC<”XLãDDD ׎wð>ЄØ"ºº5z¥Ñs[[4=®0‰Š´wþtÓÖ®þìqÒúdcDDD¤ßÄ eÔ˜ñ'Aâƒ-#?»¶Üb+ÄŽjÙ½ £«õ!÷¹gž>MáADDdp2 í¹gž>øN6oì:šr›¶ zŸë¡÷ø‡¼qãÆ¾«Å‹ˆˆÈÀéü.Ïcó÷{WƒAïó=}ɶŽÂèÝѵpa˜F*±>»&‡ˆˆˆô3Ã4R‰it°yìC”ø÷~Œž'›êaGÎÑûÜvÀ³b†ŽÕ¼b±˜xéÙ}Ñ5móPÎ-ˆÞ×¼è=¢kê»k‚ŠˆˆÈ@éþÝÞ{ D÷Ÿ=¾ö·5ˆ²wëC÷® ]çBDDdhèþݾ¥KSlÑÖº0¶t¹î^§°VûƒˆˆÈÐýÒ[8¹Åq[ëÂè}öIGçäLLÊ"}®®¾€œìì®DD†g·©ûY)mlùÊ€.x%Òo.¼âÖ–—`š&9YYLŸ2‰“Žû.Y™øÎùÑ嘆ÁCwÿ—˹Íåƒ!¢Ñn·Óìß^ÅîÛbÙYYrèAû³pß½ûµ; Ô!²söš= €ÏV¯æ…W_ã“ÏWsÇÏoÀét2rD ¦a`wØ·ûì®{îåµ7ÞäÎ[ndÔÈ‘»¿ð-Øoïù˜¦AEUïô+?ø€×ß|›+~tþ€Ô#"ýgZ !D’ÿ?óÃsÎ Í磣£ƒË®¹¼ýî2ì3ŸÛn¼îKóooyÛ¸ÖÍn_ßygž†×ëàóÕ«¹ù¶_óæ;ïòâ’%|eÿ…ý\“ÈÐvÔ §2iâx~|ÑIK‹Ÿº¥­[+>ú„<þ`¿Ö£. ‘âõz9pá¾<ò翲±¢€ã…Ãáäá{~€eY<ù¯ÿðêëoPWß@éÈÌQ¼øê^{ã-.ºüLÓäÉGï§¥­ïyÆá–ë¯à=Ê¿žyŽ_|óçÎæøEg±ïü½ÈÍÎæù——ŸŸËÏ®»Š@0È#ú+o¿»œv“'LàŒÓN"?7w‡¶gܘ1œzâqüòwwóü ¯$Äö–{ü¢³ØgÞ\Ü.7o¾³ Ó4ùêa_aÞÜÙÜ÷à#|¶z-9ÙYœ}ú÷˜2qBb¿üíŸÿfÉÒÿQ[_OIq1'ómæÌšÞw/ÈfDI1ò×Üt 7\u9†apÝM·²¶|=%EEý^ÏÎwœÆ4iÒ”ÔÔ¥Û}‘H€¬ÌŒ-ÎsÏðÈŸÿJ$e¯9³¸Ýnö7‘#J8âƒ9þ裶¾ž-Ü~åµ7øË?ž"%ÅK鈃_üò7<ýÜ L?–y³g±|å*nþÅ/±¢Öm 1˜?'Þ=³¡¢"qßv— ¼¼d)ï­ú€’â"›šxøOáÂ˯&“™Áú ¹íW¿% 'öË£Oü ›ÍƬéÓX³v7Üz;}üÙÀ¿Îš4í¦é'W\BaAåë7rÍ·pÍ·°¶|=y99\{ÅÅ;¿ì¤‘`YkË7ðü˯`·Û™6iÒ—æ©ohà¹_¦¨ €_Ýr#‡£Ção¼õ6ë7läðCJz „išÜ|íUŒ;€µë׳lÅ*æÌšÁÅ‹Ï  ñÆ[ïPQUµÃÝx<<~€h4ÊúM›vh¹))^~wûÏ1M“Çþú$O<ùO¾²ÿBÎ=s?¼ôÇlØTÁ¦ŠJR}>ž{ñeF”sûM?Åf³ñü˯òÛ?ü‘¿ÿûi&OŸÔ¾,²³²¸ñêsõ?£|ÃFrs²¹þêËÉËÉé÷zvaå.Ä‘aì{g—øÝ4MNÿÞ‰äõø?#ƺ °,‹™3¦vªìù.Öíg¬Ç­ÍËèyÏæû<ãÆŽJÜÞ¸©€eï­ä¨Oí±žÖ¶¶­þuþë …äçbÚÌ^®iÚ0Lƒ1Ɖ‡Ãf$7f 6UÐÒÖJ}c#–e1kú4L›IŒ ö™ÏoÿðG6lÚ¤Ï&Òl6;NÇæ#´v‡c@Þ÷jégóçÎ!Å률 ½÷šËˆâÂ-Îç÷ûã¿XÉ0D£Û<…ý—ø|>æÌšÁ¢“ïñX2Ù¬úð#b±¥#Fîôr·tHªÍ¶ù¾@ @ÔŠ&î C†ÛåÚáZE›Æ¦f®½é6nªH´Þm¬¨àº›nåú«/'3#½_ëÙù¡/²SÎ;s©_¬À–ÿ/Å (¿€e+Vqj(Œ³W†Ýf ½µ-± —Ó…alÜTA¨ó9ápdËëêöûÈâ"LÓä³Ï¾ Í—Ú³¾­ÕØuçc•U5üñ¡Ç1M“cþÄ’\îVöCïÛ]ëÝå+ùÞñÇât8X¾b%±XŒ²‘#ôÙ$CÖ ·Þ‘×_}9×Þx +*¸á–Û¹ãæëûµµ@ˆì¡F••2eâ>üäS.½ú§Ìœ>•õ6pÜ1G1qܸø—%pïC²×ì™ûíoát8SVÆk×rùµ×“™‘ÁÊ>Ü239üàƒxæ…¹âº9pÁ¾ÔÕ7Ðî÷sÉÏÙêóî~àal65µu|¾z ‘H„SO<ŽQµíìr·edI ³¦Oã½UïsÉU×2º´Œ·–-ÇápðÝos§–)2¬]WΨґ\sùÅd¦Ç[®¿úrn¸åvÖ–¯ï÷zt‘~·#CŸã_~áy<øø¼÷þ‡<ûÂKä …€GöÖ­ßÀÛËWð⫯³ïü½U:’óð}îº'>Àãqsæ©'q÷ýoa½=k8ãÔÉÉÎäå×ßàɧþCA~.cG&³0Œ-_OgÉÒÿaš&Eùì5k&ÇõõÎðÛ‰åî`1.=ÿxü –¯XŲ•+™0n,§žð]Š òw`ߊ Nôþn·âïóÌô4î¸ù§=îë/[úTè~ÕÍ®k`x:'/àæñé‡wôW‘"""²{Œ0åGÀ[@Ðø;§pçaó51tYnIšQŠˆˆHÒ4BDDD’¦. Iš.ç-"""IÓIšÆ@ˆˆˆHÒ4BDDD’¦!"""IÓ JIÚ. ¢T„®Ô…!"""IÛéˆMë×öe"""2ˆìt€˜¿ð+}Y‡ˆˆˆ "ꑤ)@ˆˆˆHÒ DDD$i Òg®¹þ~ù›ßnñ±½8˜?ú¸Ÿ+’¡î„SOç¡GÛ£× …»¹"‘þ§!"ƒÖ öcÂøñ{ôz|øQnºõ»¹"‘þ· ÓX?8óûÃj½"{áp˜ßÿá>^|åUÁ ,XÀç‹×ë`ÑYçpìwŽæégþËGÌÍ7^Ïü¹s¶û¼.×ÝpVÌâ†k¯  ñÍïÏW?ŒóÏý~¿ŸC¿þ-þüðäåæîÐr»üé/ãŸO=E}C#S§NáÒ Ï'';›ßÝó^ã jjëÉÏËeÑ÷NáÈÃMùô3Î^|>¯>ÿlbù;óþßÚk‹ÅXtö9Ìœ> Ÿ÷¥íÙêÂ>Gðûý_šz»ý׿¡|ÃFî¿ûÿxèÞ»©¨¨à·wßÝcž;~}‡~wÿö.fL²ÃÏX¸ß¾,[¾"q{Åûï‡yméë›ï[µŠ’¢"Š‹Švx¹@â õº«®äÑîãˆC!#=‡ÃAIq1·Üx=p_;ònøÙ-”oØÐãùo½ý—ÿèBž|üQ¦L™Ì•×ý„p8ÜcžÖÖ6.¿êZ¾ñÕ#yê¯OpëM7pÐþ vxÿíèölo=÷>ð/½ò*?»þ§<ø‡ßãt88ï‹{Ôûî²å\yÙÅüõ±G).*ä´³~@uM5·ßr3÷ÿán6nªàw¸/éÚ’Ù_Û{mvf½O=ó,‹Ï9›?=ò Ó¦Lbñ.¥­­-©õžrÂñ,:åd9ø@–¾ô<—^tÁV××[²ïÿm½–†a›““q"}ABúÔßþñO:âk_šºkïèà_ÿþgœö=233ÈËÍå¬3ñêëK{ÌwÖé§óõ#Ž`ì˜Ñ¸Ýî~À>óçÑÒÚÊÚòrÞ|ëN=éêêÙ°qï,{}÷Ù;©åF£QxøQ.¿ø"&NOnN‡r0€cŽú£G¢¸¨ˆSO:‘¢Â>úø“Ë8â°C™0~™™œzÒ Ô74°qÓ¦óÔÖÕŽDØwŸù¤¦ú=jTâ¯ßíÕ›Ìölk=¡PˆÇþüW\|cFÇ·éº+¯ ½½×–þ¯ÇöŒ;–¬ÌLN:î8b±'wE……ŒQÂ7Ž<‚U«ÞOº¶dö×ö^›Yïw>ŠéS§’›“ÃçKVf:Ï¿øRRëÝɾÿ·õZüâæ9íä“v©&‘îÔ…!}êøï³Å&Ò½88ñûú °,‹+®½€H4BGGÏ¿î\.gÛ;ú<€””fϘÁ²å+UZÊÿÞz›_Ü|#Ÿ|öo¼ùÇ}çhÞY¶œ Î;'©åVTVá÷û™4q·¿©©‰ç^x‰•|@ss3 ·1¿° ÇCGGÏVš²ÒRæÌœÉ‰§-b¿}öá›_ÿZ¢¹{{õ&³=ÛZϦÊ*"‘HÁ‚‡)S&³n}ù·§¬¬€@0˜¸oÔ¨R::[¡’©-™ýÛ~mvu½¦i2mÊTÖoܘÔzwE²ïÿm½–"»ƒ„ô;_J*üýïÈÊÌÜmÏ[¸ß¾,{o9 ÷Ûb%ÅEì¿pÏ<ûGú**+™9}•U5;¼Ü¶¶V >6Àf³õx¬£#À÷ÏYÌÁìϧ}¼ü|.ºôòíÖi_¾²­išÜuçm,_±’ÿ<ó,W\u-sfÏâÖ›nØî~Hf?mk=áP˲ˆF£˜ææÆJ§ÃËåÚò¶lñ¾Í÷îìkßcy[Ø_°íצ/Ök3MÜ®/—ØÖz·%–ä·· Ûz-EvuaH¿+,È#Åãáõ¥oìÖç-Üo_–¯XÅÿÞz›ýöÙ'~ß>ûðþ‡ðÚÿc¯9³±ÛíI-·¨¨˲øøÓO¿ôØ'Ÿ}JSs3çýà,F••‘âñ`lé5 ³gÎàš_Î~wK^_Jm]ÝvëÝ™ý»¥õ—”ññ#],Ëâ“O?cì¨Q;µ=;ûÚïˆm½6;³ÞööŽ·?üäSF••%µÞ.‘H¤ÇmÇMùºõ;\ ìø6léµÙ ¤ßÙívN:ñx~{Ͻ¼½l–eQ]S³Íày^AA>¹9Ùü鉿²`ß}xׯ´)S¹÷ÙoŸ½“^nzZ,\Èm¿¼‹ò h÷ûyý7èèE{{;Oþã_455ñß^ä‹ÏWïÔ>jimåßÏð þ:`aRëÈËË录ïSUUP<}êTþõŸ§©ªª¦ªºš<õïínßö¶a[¯%À×\ÇÃÿ)éý*²5ê±蔓q»\Üù«»¨ª©%+3“SN8ŽI¶Ýœìóößo?þò÷¿3}Ú”Ä}.\À-wü’}æÍÛ©å^}ù¥Üñë»8{ñ„Ãa&ŒËØÑc(1‚ó~p÷Üÿÿwï½Ì›;‡yóvî‹¶µµ•—^]ÂoヌŽöFŽÁÏ®¿—Ó¹Cõîèölo=?º`1¿½û.»úZ"‘óçÌå—·Ý‚± M+;ûÚ½6^¯;éõΛ;›ßüßÝÔÕ×3uêþïWwâp8’^Êo¾Å‰‹1kæ,nÿÙM,>çlnüù­œpÚéädgñ¯‰}+Ëîn[Û°­×Ò²,**«ÈËËÝ¥ý+ÒÝ–>ÌÎÉ8:'Oçä|ÀüŽö¶;ú«H‘þ´¥ó<ˆ UÞ߀·€6 ðwNáÎ)XS‚º0DDD$i """’4IšQŠˆôrÿ=ÿ7Ð%ˆìñÔ!"""IS€‘¤)@ˆˆˆHÒ DDD$i """’4Iš„ˆˆˆ$MBDDD’¦Iɰ‹Åº¤v劤"C„ ½ƒB×mÙY]¢wP°áBB†¼X,– –eõ¸¯ë¶H²LÓÄ0ŒS… dÈêÞÊFˆF£X–Õ À²¢Y¢ V†i˜˜f<8˜¦™¦iv΢!C›„ IÝ[º„eYD- +MÜŽD"]ª B†a`·Û1M›Í†ašØm6LÓ$‹%‚Dï– ‘¡DB†œîáÁ²,¢Ñ(áH+% ÒÜÜL]]mm­„Bá.W!Ã0p¹]¤§¦““Mjj*‡›ÝŽ£3X¨KC†:’ºDWxˆ„ÃÔ×7ÐÖÖBvV&ãÆŒèe°3ÀÀ ¹¹…uëÖ‘ŸŸOjj*v› Ã0°Ùl\¤Èî£!CJ÷Ö‡®ð…hjjfㆠLš8›i‚޾]ƒ1ÒR}¸=nV½ÿ!S¦LI„ˆ®î ‰¡JB†”î]‘h”H8L  ²²’©S'³,¤¯9ìvfΘFEU N§34B†8‰R†Œ®Ö‡DˆˆF ‡Ã444P\˜OL‡lÊndn—ƒööÂáp|ÀnâˆÅVzÔ!CN¼û"~„E(¢¹¹…ô´PÛƒìF†¡P˜X¬·Û…ÝnDzٰ,K-2$)@ȋŰbñ1‘H„@0@4ç@W&C]($ƒH$Òy¨°ZdèR€!%Ñdluˆø8ˆX,¦öÙí,Ë" ÆßVÌêqB3µDÈP¢!CF÷ꮣ0"ÑH·“E ÍѵÝúrx–%ëvÆS!LB†ŒDpè:„3& Åû¥­Ø È±XŒŠªj>ÿb5PÔ“&Ž'+#c‹óG£Qž|ê?Œ=ЙӧõK5µu,_¹ŠH$‚Ýn'-5qcF‘›“Ý/ëß“Y–EØŠ‡‡D£Q¢Q »=¦r dXˆ1(òå6r×Ý÷RßÐHfF:õõ \vÑÉÜJ€À0XòÆ›˜†ÉŒ~ ë7nâGÿÄøqc …BTTU‘“™Å§žÌ¤‰ãû¥†=Õ`x‰ô&G„X±ê}ü~?÷ýöNLÓ$‰`3MZZ[‰D#XQ‹p8Ljª_J ¦ipÙ…‹IõÅ2©¨¬Âãq1M“¬Ì ´ûýØL@¯ÇCFF:oõhhl$ áv9ÉÌÈÀ4M**«ðz=øA¹9Ù¼´äuž{ñeLä­£ƒÓN<Ž93gpÙ5?¥° €öŽößoŽ?ú¨x‘]û±sŸåpÜÑGqßC…innáÁÇþLccþ`€‰ãÆræ©§ðß^æÕ×ß #=ƒÊêj òrÉÊÎbÍÚuøýN?åöÛ{/¾úϽør¼; á¤caï¹súeÿÏ5“×þ÷¿üÝ=ÌŸ;›§žù/#KJÈÉÎÚ±÷Ï x‰ôHJd²ï¼½˜9m ÿåI®ûÙ­Üù›ßÓÞÞ@CC—þð\Î9ã4>øðc^ãÍ/=?2{Æ4~zåeL4‘·Þ]–x¬©¹™ Ï9›sN?•êš:–­XEcs3÷?ò8Ó¦LæêË~Dnv6¯¿ùV|üH$ÊÈân¼ú ŽúÚ‘Û¬{Dqþ@€H$Âò+ÙXQÉ•_ȱG}‹×ß|›Úúúø645qÉùçpÊñßáãÏ>glY?»î*œNËV¬¢¾¾‘‡ÿ3,ؗ믺œIãÇò÷§žéÃ=¼mS'Mä'W\BM]-ýåIÜn7‹Ï:ìÌÌ~«Ad°P „ ±Î{ºÌÌt~ôÃsøæêµ¼´ä5^]ú?î{äqŠ óqؤ¥§29e<¦ÍFM]]·mÚ¼}Þ”|¾ÆŒ)ãíwßK`Ô¨‘Dc¦i0rd1™™‰5ôþÙõ{SK3é©>ì;5uõT×ÔpÃ/n ¨ ŸP8~ÕSÓ´‘žžFYéH ÃÀãu“šêcü˜1Ö®_i˜”AJŠ—Y3¦óÎòýöÚEcõ M˜†‰Ãn'fÅhkï 'G'ƒéMB†‡AÒ…á0 ƒqcF“••ÉGŸ|F}CEù„#a¡0µõõÄ,‹Œ´´žÛÔëwcóýݺŒÎééØLÓ§LæÔÅ4mØl6\ç–—Û]çr[ÛÚyêéç˜2yN»ƒœì,€´Ÿ^»w—¯àw÷ÞϨ‘#8pá~ü ~ÿǹø‡ç—“Ó?Eˆ  "{üûiž~îEJGŽ ®®žêÚZŽ;ú(*««iimãòënH\(lÁ¾{ïòú2ÓÓ9ô yîåW0 “0~Ü9`ávŸûûû" ñá'Ÿâq»¸â¸ó±ÛíL?—ÓÅu7ý‚y³gQ×ÐÀEç½CõŒ*ɨґÜÿèc¼³l9ï¼·‚“ŽûÎ.nåŽ{ÿÃÉÊÈà’ ãóz™ˆr444`aàóùp:8Nl6;v»-qeN‘=ÍM7ßü_`Â@¤s²ºM_jÇÝÒ»Ùìœìl žÎÉ ø€ùímwìŽ ÙY]×¾…ÃZ[[immå‹/V3uò|¾”.q§=ù¯ÿðìó/qÏ]·t)² Ÿ±šhÌ  ?ŸÏ×$\¸\Nl¶xˆÙÓxS|?ÞÚ€Àß9…Ù(º‚D‚º0døc ¶k(lÃP¦×G†&É(Ê­˜0vtgsáàÝZ dXÜñ&OšÈäIõ6ˆÈТ!ÃÃ`O28Ä˫ŠIDATØòÈ2‘!HB† %éJ2|hH°ˆˆˆ$M-2,¨ýAúƒÞc2œ(@Èð‹Å'é 2,ÔVUÒævnF‘]ÐÒ܈/#{ Ëé 2,L›3ŸŒôô.cF©¨¬dÃÆM´µµáõz=ªŒ‚ü|Eq¼÷Þ{465 t"ýBBDhkoçÅ—_á•%¯±©²’ææ,Ë"?/Žý_9ðÜݯª)"Úþ¤:ü~^zåUž{áEZ[[Ió¥’—›ƒÓá`íºuüîž?ðêkK‰i‰ˆtR „ˆ°aÃF>ýì3ÒÓÒ˜·×\öž·™¬^»ŽÇþüK^_Ê¿Ÿy†éS'SXX8ÐåŠÈ@BD¨ª®&fŘ9cí¿?ééiLš0SN<ʪ*Ö¬]Çû~¤!"€º0DˆF-<^%ÅE¤¤x÷Œ*I鈑øý~°JÙ“¨BDð¥xÉHÏÀ4âGbØí›?œN'‡ò ˜={ÖV)"{!//—šº:š›iii%7×Õãñ½çÍeþ^s0 ]çADâ D„ü¼=ñ/¿²„@0ȇʉÇ~›ÍÆ5×ßÈùçþ€iS§pîQ\TÄGŸ|BÙÈRŸs6…ùüúwwóÃsÎÆérò‹;~I$jQ¾~=ûï·/g,:€?ó_žúÏÓ¤¤¤ÐÜÜÄ­7ßÈ›o¿Ã«WsÉ…$¶mÍÚµŒ;¯×KKk+Û= ûYD’£!²‡[öÞ bVŒ¶ö6l¦ï}áp˜¿üýœîÈHOçž?ÞϜٳ0Mƒp8Ì‹ÏŲbü䯛8åĸãÖŸó—¿ý{þx??¹úJö™7¯q MM\xÉeì;>cFê±ÞhÔbß½çsÑóðãóÆ›orÌQßê1O0âìïŸNzZ·ÞùK**+ijnæ³/>ç?»‘––V®¸æ:À`ڔɌ()éñüƦ&Ö¬]Çßÿùþ6mª`ñ9? ¸¨pwïVÙE: Cd7zT)¸?«Þÿ²²R òó)ß°å+VðóÛîàÊë~ÂÛËÞ%ð“MnNÅE…2~Ü8ÒRS™·×6lÜÄ/ßýâ+¯òø! RßPÿ¥õ:NJŠ‹ðz=Ì™5“ææ–/Í“™‘A~^.99ÙŒQBmmåååÌš>ì¬,JGŽ -ÕÀ˜Ñ£™3kf盦‰Óáä„c¿ËÙß?1cFóŸgŸíë]("»Z Döp™™Œ*+ãì3ñà#qà¤ùÒ˜:y7ýäZ<ObÞM‰ß ÃÀfšÄb1ì6;±X ¿?ÀÅ?¾šc¾õ Ÿ}UÕ5‰y¶&~äÇÖç1 ³s]Q+F(Ú±mKO'=#'Þm1rD +V¾¿CÏ‘¥‘AbîìÙdefòîòäädápØyów±,‹úÆFÂáð-§ÃßA}}=#F”ÐÒÖFmMMŸÖYVVÊÿÞz›Êª*ÖoØHKk+ú)Kß|³Ç¼£F•ñégŸñþûP]]Í+K^gá~ûöi="²{¨Bd0M“o~ýëüûé§Y¸ß>œýýÓùÍÿÝÍ-·ßÉü¹s¸èüÅ;´œì¬,N<þ»\òã«().¦¬¬´Oëœ>e «¿XÙçOéˆttø1 øèãOùbÍjöÛ{ïļ%ÅÅœvÊIÜùëßÐÔÜÂi§œÄÞóöêÓzDd÷ØÒÙZÌÎÉ8:'Oçä|ÀüŽö¶;ú«H‘F‰D"„Âa‚­­­´¶¶òÅ«9ø+“‘ž>Ð%;­mm\|Å•üîWwbß'ÀÚS¼÷Þ{465QŸÏçÃçóátºp¹œØl6LS¾²çñ¦ø~¼´€¿s wNÀêœôn‘> …ø|õï,[Ƥ †ExnÔ…!"}* óŸgžå¥W—0gæ ÿàì.IDvéS>_ .>— Ÿ;Ð¥ˆÈn¤. Iš„ˆˆˆ$MBDDD’¦12lD#êêªiihèRd±Ùmdfç’™½ë—7L dXˆF"ÔÕT‘–‘Ié¨qÆ–N"’¼Hç{«ºb#–emÿ "C„º0dX¨¯­&5=“¬œ<…éSv»‚¢\ní­Í]ŽH¿Q€a¡µ¹‰ìܼ.C†°ÜüBü]†H¿Q€‘¤)@ˆˆˆHÒ DDD$i """’4àí·ßæØcå£> ½½Ûn»½öÚ‹n¸–––®PDdÏ¢!ÃZ$á¶Ûn㦛nbýúõzè!jjjø×¿þE]]÷Þ{ïW*"²gQ€aoáÂ…<öØc%îûïÿËé§ŸNaa!gžy&Ï=÷ÜV("²çQ€aÍn·3þ|RRR÷jkk)(( ¨¨ˆ¦¦&ÚÛÛªL‘=Ž„H/˜¦‰ÃáÀétb·ÛikkàÊDDö "½äææ‰D'»Zrrr²,‘=Š„H/v»±cÇòÑG‹Åøä“O˜6m6›m KÙcèjœ"[°hÑ"}ôQÞ{ï=Ö®]ËI'4Ð%‰ˆìQ D:ÝrË-‰#1ößFM]]Ç{,ÅÅÅ\ˆÈžEB¤Ó¸qã¿ÛívÊÊÊ(++¸‚DDö`!"""IS€‘¤)@ˆˆˆHÒ DDD$i 2,¸=ÚZuEMÙ}Z[šp8]†H¿Q€a!;¯€ºš*üºž…ô-˲hkm¡¡®–ÔÔô.G¤ßè0NÜ/.‡êÊM„CA Œ.I† ÓÀår“›_@u]tt tE"ýBB† 77eû3ŠˆÈv© CDDD’¦!"""IS€‘¤i „ –eÑÑÞF0àèRd1 ·×‹ÛãèRDú•„ ±M uØmvròòAGaH±¢aêkk ƒèjDú„ ÍÍd¤¥“•›7Ð¥Èc³Ù((AÕ¦øý:ψ !ÃB{K YÙ]† aY99üê“áCB†ËŠb³Ùº Âlv;±˜5ÐeˆôIš„ˆˆˆ$MBDDD’¦£0D¡P8ÌúõëimkÃn·SŸONv6±X Ã00ŒäSµ,k‹Ï³, ÓŒÿ±©¢Ó4),(è³í‘ÁK-"ƒŒeY¼ðÒK457STXHZj*Á`Ã0XùþTTV&½Ì÷V½OCccû‚Á ï¾·‚`(@‡?ø]DD-"ƒL[[•U~È!=Ž,ñûý446b¾”RRRhni!ãr¹HOKÃ4M:ü~b±¿‡Ó‰Í4ihhÀëvãp8HKM µ­ÆÆFª«kÈÎ΢0?³s}---¦I À0 ÒRSéèè  áõzñ¥¤`¡p˜––,Ë"-5·ÛM8&ŽDÈHOO´rˆÈà¡!2È8].¼+V­büر¤v~á‡B!ííí´ûý¦ÉÆM›ˆÅ ¦®–)'Q\TÈú Y½f y99äãõz ƒ´¶µá÷û"  iniÆçKaͺuø¼)Lœ0žU~H(&77‡êêj rr²!£¦®žù{Í%ÕçãÃ>Â0m³X»®œÙ3gÐÜÒÂÿÞz›üÜ\223HKMU€„ô¿Vdq»\}Ô·hkkã/OþW__J{{;ééédggSR\LQAi©©LŸ:•™Ó§1fÔ(ªªªË(ÈÏgîœÙŒ()!;+‹¬¬,ÊJKÉÏÛ|¦Îì¬,2337v,Y™™_ªcDq1Ó&OföŒÔ760yâDfLŸŽÇ㦩¹™@ @m]“'N`Ú”)D"‚ÁxHfFsçÌfüرØíú;Fd0Òÿ\‘AÈír±ÿ‚̘>O>ý”ÿ½õ6û/دÇ<í¬]»Ž`(HcS3©>_â1»Ýžô@ËÞºžŸ‘‘1ˆÅâ‚HII!fY´¶µÑÐØÄ[o¿ƒaD£lvã§ÞÕõ‹ÈÀR€¤ à #=Ù3g²äõ¥D"ˆÅ_äë7l LŸ:•Šª*jkë¶¾°XŒ-] *‹%}¨®Xê󑑖Ƽ¹sp¹\‰ÇÛÛu½‘¡@]"ƒLKk+o¼ù7m¢®®Žå+Wâñzp¹\¸Ý.jëjiooÇf³Q[[K{‡Ÿ 6í´¸%†iRWWGGÇæk9˜¦I(¢¾¡ž@ ˜t.— —ÛŧŸßï§®®žh4ºSÛ,"{‘AÆãvSTX@uM kÊËÉLÏ`î¬YØl6&ŒÝá |ÃJGŒ //—Ï>ÿœÜÜ\JŠ‹ÈÊÌ 7§ç…Å&OœH dã¦M‰ûÓ§LaSe%5µµäçå%ÆB’‘žÄ[BÆ›8"$7''10rÞܹ˜¦Éª>¤±©)Q¿Î%!2ø© Cdq8”•–RVZú¥Ç dX0L‡Ãišj>gšfü’äº>˜ # 2l†¡An²[èÊ¢2)@Ȱ¢z‘¾¡!ÃF,# ‰„ºB ÃÀápbw8º‘~¥!ÃC,FKS¡`§Ë¥–é3–eÑÒØHJZ›+É„ m-ÍØm&%¥£¤ÏÅ,‹5ŸBÀß1Ð¥ˆôHJ†…†úZr Šd·0L“ü¢ÚÛZº‘~£¡.—‹XLm̲{¸Ün¢Ñ&®.E¤_¨BDDD’¦!"""IS† #ê¾é+ 2l µá@€†ÆFÂá0N§“ì¬,œN'±Xl—‹véZNUu5Y™Y8:×ÁÖ µ÷—Èö¨ CdŠF£üñÁ‡øÛ?þɳϿÀ“ÿü5µutøý¼ôê‚Áà.-ÿý?bÉÒ¥‰Û<ü5µ5»Z¶ˆ !j„>ýüs6UTpí•?Æáp‰D°Ûí457óβeÌŸ;—kçøbõjÊ7¬ç€ 8ÿ¼sqïÂòDdèQ€adè´1Ûí6)_¿žQe¥‰®…ç^x‘×–.¥¼|=Çç¦M›Â?Ê¦Š ¢–űÇ|›}æÍãÇ×\KAA›6Uà8éøãÙ{Þ\ Ã`ÃÆM<ûüóTVUD9÷¬3¸ö†9ÿ¼sYRÂ…—^NNVUµ5”S\TćLk[‹N9™¹³gQ]]Ãýuêïɾ4tÞ_";BB†¡ÔG=fÔhö_¸€ßÝs/©©>Ž<ìPöš3‡C¿r0ëÊË9ïì³HIIáîûþHqQ!g.:uååÜtË/}û(b1ÈÍÉåû§Æú øãƒ1aÜX233)).æˆC¡|Ãz.\¼8¾ÂX|ŠÅâ—®þîÑߦ°¨ˆŸß~}>®ùñå,yý î{à!f͘ÁÃ=ΔI“9ôàƒXúæ›üþ¾ûøù ×C Ü7W]~)Cê5JÛ"²# D!Ó49þ;ßá;GÅ‹¯¼Âm¿ú5?8ã æÌš™˜'²zÍZκñzLÓdê”)Œ9‚70¢¸_J “'N$3#ƒ†ÆF233·»n¯ÇCff&¾”ÆŽMnn^—‰ãÇq_m-¬-_Ï’7ÞàÞû jEIõùÏŸ±, §ÓI÷}ÔµœÍºßî\G·Û]Ç}8]N¼7·ÞtÆëõüÞËJ†â6‰lŽÂ„ÊË×óüK/QQUEeU+W½Ï„ c±Ùl´¶µQW×€iL›2…[ïüUÕÕ¼øò+DÂaÊJKxö¹ç©¨¬ä¿/¼ˆ³ÈËÍI,ß—êã‹5kikkKúôßN‡ƒùóçqû/ºšÖ¶6**+ûtûEdà©Bdr8,[¾‚ûx›ÍÆ×8ŒC:§ÓÉ öåòk®áë_=’Žýmþ.ùñUŒ)+ãç7]Çã›ôÊk(-Áå]Ôã¨.à•%K¸ìêkøÙõ?%55›Í@ªÏ‡iÆÿöðx<8ñœ6›ÌŒ Žþæ7ˆY—]}-Äàû§žBQa!©©©-"2Ømél3fçd“§sò>`~G{ÛýU¤ÈŽˆF£D"Bá0Á@€ÖÖVZ[[ùâ‹Õ”ç3wï]âãŠk®åk‡ÎÂû t)CF4áùÿ>ÓBA~>>ŸŸÏ‡ÓéÂårb³ÙÁKdOâMñýx h:çîœ"€Õ9%¨B†õQ™öIßѾ”áEqXd*).Â×íÈ‘d©BdZüƒ³ºä dØHöh‘dèý%ú0dH3 Ã00m6¢ÑÈ@—#CX4Á´ÙW0ÝÕ+¢Šìé dH1 £óà"Ó4SZzuµ\ euµUxÜ^LÓÄ0ÍnAb€ ÙMÔ…!CR÷ð`ši™ÙD‚ÔVW’“§Oué3ÑH˜šª œ.7^_*íña:lS†4rLÓH|x›6‡ƒòuë00hmm¢½õ-b±XbÙ]Ýcv»¯/ _ju õ¤¥¦b3m 2ä)@ÈÑõÞõ¡m³Ù°ÛìäååÑÔÜŒ¿£¿?@("‰`E£X–µý‹li³Åßcv;Áíx¼^|>6[üý×Õ•Ñ5‰ % 2dtÿ 6:„ÓéÀ—šŠiš<ü‘p8 ,K-²ÓººÈìv;§·Ë…×ëÅíöàtvžyÒ0dÈR€!%Ñú`š8,ËJ´2Ø:»3"‘‘H¼õ!¦³ÊN2®_9\.7.—§Ó‰ÃáÀf3] 2Ô(@ÈÒ½û"#â¡Â†ÓåJt]¨BvEbŒCWW†ÍŽÓéèl‰V …Š dÈ0 #âÜN§+ñ!îp8ˆö  ²³º·éêÊèjå²Ùì‰û»æj dHé>ê=þ` Èx‹uµÐEDvcUDDD’¦!"""IS€‘¤)@ˆˆˆHÒ DDD$i """’4Iš„ˆˆˆ$m·Hªçub‰‹Y–EÔ²6ŠD"D"Âápüg$B4! ‡imk£²²’p(Ìܹs™2eòî*YDDdÀ|øáG¼ûî»8œ Iõùp8â—ˆ·Ùí8ìvìv;‡{çï¦ib˜æV/â¶;O§®IšNe-ƒ’ß ¾¡ž¦¦f:üÁÄc]iÛf³a³Ùp»Ý¸Ýn2ÒÒHOOÃáp$úpUU]MUU5N§“”/©>iiiØí}÷‘P[WGeU56Ó$%Å‹Ïç#-5§ÓÙgëØtµ²†#šššhni! …ˆF£D¢ì6;v‡TŸôÔ4¼)^¼6›m ËÙi 2(µ´¶òáGóñ§ŸRQYE}}Câ±x“¸\.Ün7¹9¹äæf3~ÜX&އÏçÃétëñÅê5¼úÚRÒÓÓ().btY)c\®> ëÖ•óêëKq:œ”RVZʘ1£‡d€ˆF£ttt°fÍZ>ýü ihlÀðxݤ¤¤P6r$ãÆŽ¡¤¨{^g ËÙi 2(…B!êêëÙTQAuM-­mm¤úRIIñÒ à ‰R__OskKü²Þ†IqQ!…Cî‹,~¿Ÿ†Æ FfF:ÁP¨Ï¯ThllÂår’‘‘F0²¬>]Ç@ŠÅbX±@€êêj**«(/_OUu@h4J,faGhoï ½£¿?@(Ö•aeÐS€AÍétQXXÀ(·›ñcÆR:rDç»…¿#€?`ÍÚu¬Y»–Ï>ÿ‚ººfNŸJFzưi©©Œ(.&-=œœ|>¦Ù·C¢|>Å……8]NrrrHõù°Û†ÎGN ˆ„Ã455±|ÅJV½ÿ‡—ËEYéHòrsÀ01Mƒ¶öÚÚÛÉLO'ÕçÃét ë0†Îÿf–ìv))^r²³˜8a<“'NHõÓÚÖN[[;‘H„ú†ZÛÚ¨­­#';‹éÓ‚¤ZVŸiY™™Œ3oJ ÙY™¤¥¦öi÷@zz:£G—á°;ÈÊÎ"==½Ï×1"‘MÍ-TVU³aã&6UT0ª¬ŒââBF—0¢¤»ÃÃn§©¥…¦¦&œ¾”<ÿ CÀÐùß,Ã’a˜¦‰Í´a·Ûq:‰Am¦ÍFŠ×Ëøqc°Ûí¬úàVnÚDCc#`€h4º[qÚ“ååçár»±Ûí¸].\î¾ÿ›“ƒÓáÀ4L\nn— §ÓѧëHÁ@€›6²fíZÂá0ùùyLš8™Ó§‘’’BJJ fçûÓív“•‘Í4±;8;ÃÌô–A/"lf¿êx ° Ã0YW^N[{;D"¬Î aFb}Àï' &ÎK‹Å—ßu,¶×ãÆíö`ômmí´¶¶b˜ñy-Ëê\FËŠñ£BâËðàp8:Ï!  …âçF‰ÅâÇyÛíx½¼^oâ¸nˆ÷»‡B!ü¡`P8B4Á²âýé¦iÄCÛÝù…íŒï‡^LÓÄn·a·ÇTéÝimm%àpÄ›ÛÃá0ápËŠbY±ø2l6<^^'q\zb†‘Xö–Ö …hmm% át81M“P8L$&Ÿ'Æì<¾=¾oç:l=ö},#ツBa¢Ñøkg§›i#‰‹ÅðùRHñ¦`³Å÷kKk+­­­!Ô†ÛßžíµNƒA6UT²®|=PRT(:zô—æÕ`IŠ dÈ3 có W:[Lcóï]]ÍÍͬ[WÎ¦Š jëêhii%jYØìvr²²ÈËËc̨2JG–b·÷ +ëÊËY¾b%§ƒì¬,Áõõ´¶¶â÷w€)Þrss7f ÙYY4·´ÐØØHeU5555;ƒKFF:éŒ3†ñãÆâé –eQßÐÀÚu먪ªNtÍC!bV ·ËEZz¥#FPRRL^n9ÙY_Ú'«×¬á½+IOO§°°Âü< p»\@üÌå+VÐÜÜBNN6v»úú›šiïè  áq»ñ¥¤0nÌÆŒMZZéi©‰/÷òõX¾b%.—‹¢Â ò)ÌÏÇëõÐØØÈò+©©©%''·ÛE}} Mtttþ¿½;mnëÊÖ<ÿ?ó€ƒà(’â kòNß̺·:ntG}Ÿþpq£ßߪ¬ÊÊ̶ÓéA²-‰â q&1gî€)‘’E§m Ôú9V p2¸ì½öÚØ¶ã8ÜZ_gc}R±H±X˜<Æx¶©Ñl²µ½Ãóý}ŽGEµqcµZ ×qh¶ZDqÄG÷ïsçöm' Y?áï_þçÏ$ IDAT~‰ãº n®,³¾¶†cÛ¯ý½òƒ€ƒÃCžïísk}õµ5Ê¥Ò?ýû*Ä´!®­dôŽÞ÷}úýišŒfìÞaÈ`0àðð'››l>ÝâäìŒv;{®jÕR™Ù“S ]§P(âå\ïqzÖà¬Ñ¤ÛíÒï÷1F]÷?@QUn.-áy¹ÉsÏ<ìòý£Çlïìp||L§Ó%NbL#{^¶e±·¿øx9•ået]Ã2Möö÷ùüï_R,˜©×q‡å¥¥×ˆl&(äôôŒã“>¼w—……yt]§ÑhÅqÙ–bC70ÌléÂ0LTõý[6×q팷Çù¾ïûlïìòàáwt»=–—–˜ŸÅ¶-ÔÑ D³ÙâÉæ&Û»»ì¢&¿ûøc ù:áùÞÍV‹|ÞccmõÂõAH·ÛeqažÛÜba~Û¶9<:âó¿É7ß>àÑãÇ †C>þð>µz•ÕÕn®¬Lê&þó¿ÿ‰§[Ûáûžç±¾zÛ¶Q˲(‹ä yfÎmÁì÷ûì<{ΣÇOøÛ³çœœ³¶v“;·?@U”Ÿ ¢(¢ÛëQ,æ¹±¸È·ná:q’ðÕ7ßðÍ·ØÜÚbgg—å¥%Â0¼0ÛñSÆM˜r®ËüÜ÷ïÝtiüêÛo…Íͧ<ÝÚbnn†?üþ÷X–…¦iœ5<üî{vvwi¶ZÌÍÍqçömn./¡½N—o¿ÿžv§Cœd3c®ëR«VñòÅbç'ê^£ú•0ŒŸ½½}=yÂññ1G''Ù2 KK7X]^&ŠcŠ…"š¦£iïw7T1ý$@ˆ©æû>GGÇloï°·¿Ïÿþëß÷ç €0Q5•r¹Ìòò Vo®°0¿€mYÙÁnqL«Ýf{g—v»Í·nñÁƵj Ûv²úRÖVoE1»Ïž±óì9¶Û—^O!Ÿgnn†å7¨×j 4]§\.³¾ºÊ ?àððˆ$I¸±¸È>`vf†¼ç‘¦)Q±0?ÏÆúíN—ÓÓS:qœ¼ð7W–IÓ×u']5ÇÁ0MtMãÙóçt»]|ßçôô Ë´(‹W~}Çfvv–•åeæfg)—KºAœÄ,/Ý IÎ ¾>¢×ïÑît(À•¶(š¦Éìì Ë7–˜ŸŸ£R.c: pcq4Miµš<üþ{zý>NÓ4°mû…Y¡66X[[åÆÂ¥R)Ûý`YÜI?ÀÐuŽŽ8=;{á±EáæÊò¤ÀÕql*å2æ%…§cI’àûƒQ³(ß÷yº½4Eayi‰µ›7Ñtn7 ±V“‡?ü@Š‚ëæ¸±8Ÿ=Î{Ü‹DL? bªAÈáÑ1GÇÇ|ÿèñ ïã("Šc~÷ñG|üÑG¬Þ¼Éï>þhRÅ1aÑn·yþ|8Ž©VÊ,ßXÄ˹0Úia™&s³³DQ̳çÏÙÛߣÓé^z=ž—cqa…ùyª• ù|~òµ›ËËt»]¾úæƒóssl¬­ãºÎd©#ŽcææfY»y“?æÙî.½^ï…Žž—#—s/œxk™ÙÒiJµRaÇÚÅ÷}Í&•rùg½¾YÝF7©×ë“Ç17±L‹o¾}Àp8¤ßïÓív±,ëJ»LÓ ^«±´tƒ™™:¥Röiš²8:‘ðÁÇ£Z–>Ý^ÇÍf(šÍ&;»»Y@[[åÞ½»TËåI¡fš¦ ,Ëä‹/¿¼ôñ—nÜ`éÆ7¾Þ$I‚ ˆ àùÞ>šª±¾¾ÆÆêjV0:7ËÑqö»ùç¿ü•/¾üš¦g£–9i©.Ä´’!¦še™Ykêù9æ™­Ï’…¿ÿž‡ßÿ€ifEkÙtñSÆa޶u£ˆV«Å—_}ÍÉÉ)ŽãLþ¸ÇIL¯×£Õj³½»C†£¹7§ë:¹\ot<ïx<ŠãÉLÈ‹m[”JELÓ$Šã¬%2?Þ&Žãli¡Û£ÑlÐjwèõz †CâQÓ¬í݆þ ‰£èo!­ª*–i’Ëå°,kôœ²z†¬…ó?ߦYQÌQ(²-;ÛNŠ’m}õ}TEaèûDqŒa  ùü…m«/þÔÿyªªb˜Y1¤¦iF€Ö×VY[½ÉÊÊ2ž—½.•r˲88<âàðÛv8<:¢Z)³¸0¹ÜO>žï* bªY–E¡P V­ò/¿ÿ”ûwï’ŽÎ'øþãÿåÙó=,˺t­9 ³z…Þ¨/ÄY£Á—_}Ńï¾CyiÈI’„8‰ ÃUQ&½Þ”®ëä¼sb|Ÿ— ¶¶m¿ ^z¬ìp@£Ñ`sk‹gÏ÷8:>¦Ùjáû>Ý^“Ó“l>ˆ£ˆ4ýeĸÃórØçšPEQôÂrË?Ë4ÍI_‹q0ˆ¢xrÖÄ`˜53 ƒÂ(@üÚuY_ÓÌNu5 ™zõµ5ÖVWX^ZšÜÖ²,*• §gg£‡GGÔjU‚—j1„˜6 ÄÔËú:(“†Eišbš&óss|xÿAðãÇÔªU>¸u Ó4²mœŠŠ¡èZVu_«Vùäã¹±¸ˆ¡¨ÚË!i’’¦YˆPPøðÞ½ßüy&IÖ¯âÙó=>ü޳Fƒ8‰Ñu••eÖuUQhwº|ûà‡ÇG×¶ÚÜ»#M’ K9¿I€u=Õu]Ó±,gÔÙó2–iRÈçét»´Z!¡¦%® bê)çÂÃùâ½ùù9>º|ý5ß>|ÈÍ•e†þ\ücwGÃ0²° ªT+þõàÓO—uq¼¤nü'ßÐ_¿ÕïÂ5rµ©tå£]Ïžïñßÿçÿ¢Ûírcq••en./3;;ƒëº´Z†Ã!~`™¿~€PEIùUÇm%EQÒÉ‹8ÙGú›†ˆñïŽ9:çÂÐu,Ó|a&æe¦iR(ä9>9uô ¯Õɤâý$B\Kã@°±¾Æî³ç€B£Ùbsó)Q173ƒ®k£ýÿ6¦a¦ N—n§ƒmY“ÂÆw…øt:=Í&­vÓ4¸¹²Â·6¨Öª LÓ$ BŒQ/ƒëºMÐ0 lÛ²mTUÅšÍ&­VÏËý&ʼn†aP*•¨”ËøAÀþÁ^Þc¦^¿pÛq½M’$8£6ãïëAnâúß`q-©ªJ¥Rf}mZµŠa4[-=yÂÁÁA¢ë:®cã86–idˆ§§1ßöS¸À÷}š­&­v‹þ`µxÞXçÞÝ;,ÌÍ‘Ïç³FHº†¦ª(¿tõà;Ä0 rž7ê*ªfÛU ÍæoV[`:ÕJ™jµÂp8d÷Ùs:Î¥·ŸûÅ1®ëÊiœâZqmºŽ¦ªÌÌÔY_]%M?Ù¤X(²zsǶQUB!ÏÒÒ Ù?8Èβ²õm×u1 #+fm ãxrXÕoi¼L£( QÑï÷G­Ÿä=UÓè÷ûÙ§gt;]‚ øM¯ñ·¢iÙB±P`~nŽ0ŠØ|º…¦ª$iÂl½>9°ìì¬ÁÓ­mÚ¯èݱ·0ù¹ÛvÖ/£\.cüÄi™Ùó´[mŽNNxòô)µj•J©<Úq“c02ô‡<{öœ§[;är.‹ ÌÎμ¶×„Ó@„¸¶Æ‡gÍÖkܽý77ÙÜÜdnf†A@\(¢ë*ÅBµµ5Â0bçÙsšíùbÏ˦£u]Ç÷}†Ã!Cß'*åòo 4M›¬³'IL³Õb{g‡|>Ç…LÓäðø˜íi6³]ב¢¨ºN©Xdey‰ÝÝgüðø1ý~/ }ºëº }ŸÍ­m¾ûáÎÍ ÷“¦)Û;;üù¯%ïy“†_^.÷“¶,n,.2 y¶¿ÏãÍMÊ¥ù¼ÇÂÜš6ÏÉég›[Û<~²ÉÝÛ·YYZbqAÚY‹é'B\kŠ¢P­Tù`cƒÓ³3†Ã¬3ã³çÏÑ j%;¨jcm•4Iˆâ˜^¿ÏÞÞ>qâyÙ²@E¦8NvĶmÙ¿ùÉ‹†aËå¨U«¬,/gçkìï„!»»Ï±‹ápÈY£Iœ$äó×·QÑø8õj¥ÌÝ;·1 ƒÍ­m:.ß}ÿÇ'§8¶=jUÞ¢óÒl̸4$MS:.{{‹yâ$anf†ø  àR.³´tƒµƒ› ý!QòèñcF³õ‡ÃÉ1ãËK‹¬,/1?7K±X|eÁ¥ÓB~ƒÅµW®”1M‹'›OÑuf+;<Ë4 ¼\ŽB>ÏÆÚ:Žã ë:O··9<<à‡G?Fqœb9×emm•µ›”K¥ßdËày¦‘m?]\XàÃû÷x²¹Éóý?ÙÄ„–Ë¥l‰eNve\gµj•?ü0;Ÿ#NØ}þœ¯¿ý– Ñ4 ×q©×ª(£sO€sÅ¥ÙŽ ß÷év»hºF.×ÏŽFƒ-–º®S,²Œà# …<;»»|ÿèq¶ f8ÄvlÇaéÆ"ÿå`õæMfggȹ®Ô@ˆ©'BL%ǶY\Xȶә&ÅBá…¶Ñ/ßÖÐ ÖVoò/ŸýžB!OµZÉMÒ²­œº®3—Ì!¶m³¿¿ÏÉéiÖé0Š'¢^«Q*•.LU«U¹ï.^.ke}Ù;LEQ(òÜ»s‡j¥ÂâBv&Çù$ëDiS*•X[½É0XY^Â0ŒÉöÁj¥ÂínáØ6ù|žV«Mš&X¦E¥RÆór¤)èšF¥R¦V©’{©ãáL½ÎG÷ïS.•X˜Ÿ§X( Ÿ»ŽB>ÏÆú:³³3,.,P­T°í‹S±²¼Ä¿þñ¬¯­Q(ä'»jÕ*÷îÞÁv²ŸU©X|¡Kd.—cmõ&ž—-ÁÔªÕKüR…‹ÙüÁÆ¥R{´ûbÜ`*†Ã/ïq||B¯ßÏαmjµišðtËå¬Ñ@Ó³î‘ãz’™zûwïâz.¥b‘j¥‚®ýôŸÆ¬¡”çy£¶Þ&–eb&Ý~~·‡›Ëáº.«7WØX_£^«áº®Ì>ˆkA~‹ÅT*ò|xïëk¨ªŠ®ëxžwém³~ wïÜff¦Žaèç–"²AQQ¼\Ž••effê ïÞ!â$!MÒI£ë:¸Ž‹íØ/Ì>¬®¬P*Ð5ÛÉŽÎ>¿Æ=îU1S¯óßþ¯ÿß÷©TÊä¼Ü ·¢(òylË"Ÿ÷¸sû6Åbá…µXÈŽ_œŸç“>šœ.™…)M×!·‚6F= ^˜××V©TÊFv€”mÛç–;êµÿõ_ÿHE8¶ƒíØØÖÅÁÝ0M~÷É',--Q*'!AQV–—(äó¨š6yŒó¯I¥\âÿò¾ïOŽÒ¾l묢(|tÿ>óssä½<¥bqÒ²ÚZ-;üìÖ­u? Š#@™,UŸðýx¾·‡i˜ÙÁc£ë¼ukZ­Š> 97‡e½ùÒ¦i”J%\Ç¡V«ñá½ûDqDÅYo]#çºYÛoÓ”™qmH€SÉ4MjµêÝv½~sÔ^Ú4Mßçøø„=bóé®ë²0?Oµòêe,!Ä›“!„˜Z“Žœ§g£( år9 AÀñÉ û‡ôº=nÜXäƒ[·þ©z!Ä$@!¦V’$DaÄÙÙ?<~Ìéiƒ$MPMÓFç‚hll¬óÁÆë««¯Üî+„¸ Bˆé¥d[5£(¦×ës|rB»Ó!NbÛ¦Z­°~s•õµ5V–—™¿l[‹âg‘!„˜Z¶eQ.—ùàVÖ`jܲ:It]ÇqlJ…âhÛjñm_®׊!ÄÔ÷Ì( Ü\Y~Û—#Ä{Eö2 !„âÊ$@!„âÊ$@!„âÊ$@!„âÊ$@!„âÊ$@!„âÊ$@!„âÊ$@!„âÊ$@!„âÊ$@!„âʦº•uÇÄILÇDQDš$$iéÛ¾2!„âTEEQUt]GÕ²“bUM{ÛWö³Mo€HS¢(" ||ˆ?…!QA* B!Ä;DQÐuÝ0°l˲1L SUAQÞöÕý,S Ò4%Žcâ($ð}‚À'‰ã,Õš>uOI!Ä{@QU%Ž"†é€$IHÓM7Цp&bêFÛ4M ý!ÃÁ€0 Ã˶ñ\ݰ0 eJÓœBˆë)MSÂ0$ }†Ãl ‹£ˆ( ±Õqßö%^Ùˆ”$Iˆ£ˆ ðý!ŠªbZ¶ãâ¸.†icš¦!„ï”4M ‚€00@QIÓlLóý!ª¦¡&I’0ME|S Ò4% CHDqD>W"_(¢é:º¦£ª*„B¼kÀÐu4ÕE7LÜœG§Ý¢Ón>$ CÒ)ªá›ž‘¤DQ€ïH’MÓ±l›œ—Û—&„B¼ž¢ jÚh¶Á |ú=$‰ñýQ&Ó ¦¦D6ýãã‡hºŽ—/`šÖÛ¾,!„âg1M /_@Óuüá ð§jbªD†A€¦i¸9c”â„BˆicnÎCÓ4‚ %Œ_Ëdûf¢ª*–eOu!„ï7M7°•žª‡!qK€øuŒvaÄ1Š¢b˜æÛ¾ !„âgÓ4 MÓP•8ާnÆÔ,a!„âÝ!B!„W&B!„W&B!„W&B!„W&B!„W&B!„W&B!„W&B!„W&B!„W&B!„W&B!„W6E‡iýzâ8¦ÓéÐn·9::âôô”r¹L¥R¡\.S.—QÕ³V† ‡CšÍ&GGG´Z-ƒišbš&žçQ¯×©T*¸®‹ã8oéÙ !„¿< @EñäÉþú׿òå—_rÿþýÉG¡P¸ †Ã!§§§|ÿý÷üå/áñãÇE¥R‰¥¥%>ûì3>þøcæææ$@!„¸VÞËÇ1¾ïÓëõ899áè舭­-677ùÇ?þÁƒð<ÙÙYz½Þ ç³GQD†ìîîòõ×_³¹¹ÉÞÞ¾ïcY†a†!‡‡‡|õÕW´Ûm>ýôSlÛÆ²,L9†\!Ä5ð^ˆ0 i4ìììðùçŸóÍ7ßp||ÌÉÉ Fƒ(ŠFç²_äû>N‡ðÿñt:–——ùì³Ï˜››CUUž={Æîî.<àË/¿`ff†r¹,B!ĵð^ß÷988`ss“ÝÝ]NOOQU•jµJÇDQ„®_þÒt:¶¶¶xúô)Ïž=Ãq–––øä“OXZZBÓ4fgg±,‹gÏž±··ÇÓ§Oyôè”ËåßøÙ !„¿¼÷2@ ¶¶¶ØÚÚÂq>ùäVVV(—Ëüçþ'þóŸqEQ.|ïÉÉ _ý5‡‡‡Ôj5VVVøýïÏÝ»wÉår(Š‚çy¸®Ëññ1ÃáF£Á_|çy¬¯¯¿…g,„Bü²ÞË ( Žã0??O½^çöíÛÔj5vwwùꫯ^¹ÔpvvÆÃ‡9;;cff† VWWYXX˜Üf\tyëÖ-ŽŽŽèv»|óÍ7ܽ{÷·zzB!Ä¯ê½ …BO?ý”[·naš&¶mS*•HÓôÒY‡óšÍ&Ožú€‡òÝwß±ººJš¦T* àÕj±¹¹ÉÇÙÙÙáîݻܻwÙÙÙ·|õB!Ä/CÄÕj5>ùäNNNøÓŸþD«Õ¢^¯“¦)·o߯q¶¶¶øæ›oøöÛoÙÝÝåßþíßøì³Ï˜››{Û—/„Bü"$@\‘çy,,,pçÎþøÇ?rzzJ£ÑàóÏ?g{{Ã0h·Û4›Mfff˜››ãÎ;ÌÏÏãyÞÛ¾|!„â!âŠÆ½ >üðCt]çÁƒ|ýõ×üío£×ëÏ癟Ÿç£>âÃ?œÔ?ÈöM!„×…ˆs Ã`mmÿ÷gaaùùyªÕê g]Œ·sÖëuEÁ²,LÓdvvvr\w±Xdaaû÷ïsûömÊå2¦i¾Åg&„Bü²$@œcš&Ÿ~ú)«««X–…mÛ¯HËuÝ7º½BqH!„B\™!„B\™!„B\™!„B\™!„B\™!„B\™!„B\™!„B\™!„B\™!„B\™!„B\™!„B\™!„B\™!„B\Ùç­ iš®“$ ?DÓt4}Šž‚B1Gq‘$ š®£i ¼íËzcS3¡(Y€Ðu$‰ñ‡C¢8zÛ—%„Bü,Qá‡$IŒ> Š"â§( †abÚ6IÓëvÿm_–Bñ³„O¯Û!‰cLÛÆ0L ¿EU0L˲‰ã˜n·ïoû²„BˆŸÅ÷ºÝ6qcY6†i¢¨Ó ¦¦€@Qt= IœF!þp@«ÙÀ0 tÝÈj$4 ¦(Á !„x¤)qÇ1Q†Ù i:–e£ëÓ51EBE7tLÛ&Š"¢(Äôú¸¹¹œ‡a9¨ª:U?!„×_š¦„QDèèõºô{=@×t 3[ž× E™š…é …MÓ1M‹4M‚€0 ƒ€]´¡ÏP—!„ï˜4%Œbâ8$ Ò4A7LLÓÄ4-4mºÂLY€€l)ô,t]G7†C( éu²u¤4IHÓôm_¦B1¡( Šª¢i†a&Haà¬IDATâØ.¦ma™6ê”í¾›º jªª’’¢ ¢Ê$4Ä) H€BñîP·"0²% ÓÆ0 tØÚYó© ( šn ª†i`»9™}BñΚÌB¨*ªª¡¨êÔ†˜æ¨ª ªŠ†Žñ¶/F!„xLWņB!Þ  „Bqe „Bqe „Bqe „Bqe „Bqe „Bqe „BqeSÝHê<é@)„bLã¹—‘!„B\ÙTÏ@ÄQDÇÄqDE$IL’$Èd„Bˆw‰¢dÇ/¨ª†¦ëhšŽ¦eÿžVSyåãåŠ(ŠŸ0ý!QE‘,g!„x§(Š‚®ëÙiœ–=:‘ÓBÕ´É×§ÍÔˆ4M‰¢8Š‚€0P°,˶‰B!Þ%YŬB!Þ“7ºd= #+¤LGoŒ§i bjú@Œ× @SU×Ê¢!„@× ×ESÕ,@„áTÍ@LM€Hâ˜8 QUÓ²döA!ÄÔÒuÓ²PU•8 Iâøm_Ò•LÍœ¦)I’G1Š¢b˜&Š2UùG!„˜P5 CUP•87Bœžˆ© ÀdϬ¢(¨ªö¶/G!„øÙEAQ²ƒi:]á¦l C!„ï B!„¸2 B!„¸2 B!„¸2 B!„¸2 B!„¸2 B!„¸2 B!„¸2 B!„¸2 B!„¸2 B!„¸²©: Cˆ_ÓOõ¡Wå7º’é5~ åµâú“!Þ[Éè„×Á`@·Ûe8âû>ae§â‘¢ª*š¦a&–eR(ð<UUQGƒäxÐLÓtt8λ3xž¿6àg]ß›<¿4M99=åäô˲pl›œë’ó<4U&:…¸Ž$@ˆ÷V’$„QD·×ãàð³³3:.ýÁ€0ŠHÓ]×1M/—£Pȳ¸°€mÛ躎ªi“cæ!DÕÑ`ù®„ˆìÛtTU½Òµÿþq€¸ì>Ò4åä䄇?<¢ÏS)—™©×°G„×”ñ^JÓ”n·ËÉé)íN‡A¿ašÔjµìh]RÒÆÃ¤¢*˜†¡ëhš6™}èõût»=¢("Š#¼œG±Ç0Œ·÷äFâ8¦ÛëÑëõ‰ãlV¥X,R*ßø>Â0¤Ûë1 ‰âMS)‹x¹Ü…Û¦IÎuq˲Ðuý RBˆ_žñÞÏ´;vvv騖E¡X V©÷ C†¾?y~f“(ŠÐ4ç†Î`0À݇ëº8¶=¹>Ó4±L Ë21-k²Œ1 hw:ÄqŒa(dK$QôãÏAÓT ÃÀu]lÛ=·ß÷ñ}Ÿ$IH’MÓ0 Çvp]ÃÐ/ìIÉÂâp0`8„!a’¦€BVÓb¸Nv/¿? Ýi`Y¤„a0z½U/—Ãu]ôÑÒŽïùï4}qwAgÓüQ½Qí¸óô쌃Ã#& ÓírptD!ïQ*•¨ÕjÌÍÌÇ''œ5èt³q”6†i™Ôª5j• ÅbáÒÑj·yºµªiTË%â8¡ÕnÓëvé‡X–É…EJ¥"Cß§ÛírpxÈáÑÑä¹v»]žïíQ*)•KÌÎÌ`[Ö…gGGGÒlµ&»0š­&¶íP.©”ËÌÍÎb['gg<ÝÚ¦ÏS.•(•J” cROÒévÙÚÙÁ÷ò^h÷zôûß'Ib,Ë"çºÌÍÎR«Õè÷ûôû}Íf“0 ‰¢Û²ÈårÔëuæggQÕšvnæhôs ‚€Ó³§§§´»º½>i’ (àyyÏcvvÓ4/}¶;žnmP.—!MiµÛt;Ã!ºa°´¸Àìì,¹Qˆâ}ò¦¿ñ//ê^m!Uˆwˆ¦©˜¦‰aš†AEœœžàº9ÇÆ4Œl«æ%[EA×4,Óœ¼ WU•8Ipl×uñFµ–i¢ª*QjtMö,ؼóŽÂˆf³IèûŒg0ÆË)cãq…av¿Q„¢d;D,ÓÄ0tôÑ»óó×—$ i’à¸97‡çåpã;%T5› ¿eš$I‚¢ªY‡\Žœ›Ë¶´Ž‚ïû´;4MÃu¢ÑVØÉõG½^â8ÂÐuÒ4Å2M4U¼>Ý^ã“S†£‡qÑ«mYèš–…µQ¬®ëX¦Iš¦x^n„¢(¢?Ðn·i¶Zôú}r®3¹Ï8ŽiµÛX–…¡ë£çôãlÌøõÏ\èšFÇ (£×ÆD7Œ+oâôò˜þF…\? Ò—þ^ò@BL]×ql w‡^¿Ï³½}Zí•J™r©D!ŸŸ¼«ÔF䘢(xž‡eYÄ£)õ¡ïµj•ùù¹É÷š†iš †C Ã$ïy˜•òd ?Žc:½n—v«Íéé)¦eR)—³éø08õúƒ9Ç¡\.ãU*†íØä=Ƕñ€|.Gœd³aÅ1óós,ÌÍaŒÒxWÉËLÓ¤R*e{œ`™&A¢ë: ósÔk5t]ÇÝÇUDqL¿?ÀËå¨TÊx£fSaqrrÊY£Áñé)û  …<ÅB¼—›4ÿ:9=åàð([ÒQ³m·¦eNf‚ àäô”³³3ý>i õzR©H:Z¾:>>æøät2³1;3ƒcÛfc†Ã!ƒ~Çu©”J”K%LÓÀ¶³×ÛuÝIˆbŠ%ü8ν6H¼.@\Î1•Æï®ó^Ž™zF«Åp8`0pv¾ÐëvÉå²wضecšÙzù¸N­Ÿßk'òù<µjwT÷0¦ë:9×Å4MÇÆ2MU%IœnÓ4éw{ôúýI@PTó’%•q 0ͬ3f¹TÂ2ÍÉ:žUÐ5-»>×Å×4Â(¢X(0S¯ÿä;fMÓÐFß“s]|ßG  à\*Q¯Õ^¸ý«vf\F՛ضM±P \.£›YÂÞÑÍVkRcP(¨”K@¶4E­v› iw:8ŽC½V›Ìxø£úF£‘5ó<ÊÅ"ÕjF߆!ýþ`4u–-‰¼âyŒû€Œ_oÛ2³Y¬ÑïÌ@ˆ)÷º1þ•ãý›,aŒSIrî#þÙ—)Ä[6þc_(XYÑ(µÛ4›M:.½^V«…ª(˜–I!_Èr‰R¡€eYW~Ç `è:Åb$IÑô—&R˜,‡´š-NÎΈã„~¿i˜¤Nzap²m›üèÝ{½ZÍÞÁkê$ļkí´_fè:…|>kHåyض±ª*¥b‘8ŠétÚ´šYÂl½Žã¸/¼îžçQ.—'5 Ãá8Îþ,%IB´Ûmº½7ŠEfêuq\–ZƳ œûº†Ì@!„ïš—Çò˜Äø#äÅYˆó!âÒ ñS»0. çÃÁùÏŸ  „BˆwÁe« !/.c¼.@\êU5ʹPáÅ`0þÚùY í’Û !„âí9?“0㥌ð¥—k!ÎßÇ ^71®¾Tx1DŒïhü¹Ë–.$<!„ïŽËVÎ×D\Æ·½Ôëj Î/S(/}í|1Æùe‹q]„P !„ïŽWµe8$ÎQžW®?zÉÄùY‡—gdB!„xû.kËpYƒÈ+5“zÝ ü¸|qþóã;yÉB–.„BˆwÛË-«_ //]¼²ò§üó¡àüòÄe¡áå!aB!„xû.;Ûêü¿_>,ó'ü٠ÿr0P/ù¼!„âÝvÙ®Šó!á²r…WzÓÁþUu Rï „BLŸô¥ÿÿÔç/ø¹¿Ì8!„ÓíŽíB!„B!„B!„B!„¸Îþ]*Ò¢øÎéIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/images/progressbar.png0000664000000000000000000002175515074673150025624 0ustar00rootroot‰PNG  IHDR©5¸ysBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timedom 11 dic 2022 21:27:35ÁòT IDATxœíÝwxU߯ñïn›H€„4 E)B“.¢-(F‘GA¤‰ð(åPPŠ"h¤I±7•^BOh B$´º;ûþ±Ùe³l’Ͳü>^s%™ræLâÜœsff„B!„B!„B ºƒå9ºl!„}ôE|[nçWY|µ\&á!„sÐc=4ô_KÅžÜ2Ì6ÿ^mO…„§|5Ë@)*`ŠTšð°li¨Í¾Z —ÒTDqÇè ¾Z†ˆbe¾ù×b¹Ú¸sk­ µÅ÷j‹ùÒòÂ9¸p3,Œ_ çiQQb€ØÒò°lUX„ 7ÃùCˆ!œßÕûBëŽ0‡q²ìÎÙ}).<̯¦»(ÆÐp|€ÆgOŸ\‰^/ãB”'*Uþ}¡u£€#À ›bìÊX^)\DQESø*ŠèkÁW ñ™S'V« ’CFqWéáZí°z0H.†UmÁWóU«­[.§šw[Œ­¿?Öýú¼‡å— *ý±î×ç1\èpçæX¦ñŠi±Š Ë{9,Ç;üëÖ {äv+/„([ç±?7ÏmcCÁò^®[wµÅ²ëb,Ü ðQ©UÑ;ì!DP©U1Œ_ºqs¬C‡áœ×SøF²Bl¹ÏÃòÞWÀS¯èUr=VˆòM¯×«O wYŒS±—k­…‡å3,–cÆÉqÏö !Ê’ùym9æaþµÐ)_Ü€©e«Ã¼û"Ï­ñïa~^[{ÔĪ¢º-Ö¹·¸-]ÚBüK˜?jbmÔê¸GQÝË»JÝ &wÓ$Ù!Ä¿…»Ùd~·© ÖŸÀäᵚ0‰3gÏ V«©V¥ M6 ªß3Tñõ)ãÚÝ–Ç\¹R%Ô«ÃÀ¾OS#8èŽíK¥RQµJ‚éÚ±=íZ·r辄cÙ÷ZÃã¡fM8qê¶nçøÉSÌþß4ÜÝþ½wæ÷zôòµ:>ÂνûIøû4 çÍF­vüW›V¨Õ*ÒÒÓ9rô(‡þü“»÷2aÌkß—pŒÛhyÜ+ña8ί ¡’·7YYY¼1i)iiìÝGÛȈ2®ß`8æþO÷ÁÓÓ“œÜ\^6ŠK\¼ôÕýü¾¯á/=§§''OâÝ>b÷¾ýlܶÎíÛ9påWŸƒiP¿ÿ=‚J• 7w_ËÌdæœyüyô8?¬^vWë#Ý–Ròôô¤C»Ö|ñå7¤¤ ôPZG<„_Õª¬ß¼êÕýxoÊ[(ŠÂ·?®e[ì..^ºDHp0žz‚æM›˜ÊËÎÉañò•ì‹?ˆZ¥¦KÇöü¼îwz=Ú}Ÿ,¶üœÜ\¾Xó {÷Çs#;‹ûÃÃò|”éäÞ½/ž¯ø‘ÔÔsxzzÈë#‡SÉÛ»Øe–*xxPÅÇE§Ã¯jU®]»Æêo~àà‘#\ʸBåÊiÑ’¨¾O™ZcEÕ»$uÃÂ<°sİ~ÃSx”t¼ý£‡Ù²<*°{_jµšÝ:Ó²E3/û‚§ÎP­jþóÂs4¬`ÓßÈYÔ æØñLzgÓÞJ¥bÊ;39s6‰ Çv'maûSLVŽW«5|$d_Ó:[¶ïäë~ÆËË“ûjÔ=|¶ô V~õ-...4mÒ˜Óg™6sG0•5{Þ§lؼ*>>„× ãûŸ%''·ð>‹(ÿý¹óë¯W‡–Íšè0ï¾?E§~þ3çÎãòå«<Úµ3‘-[PÑÛ›J^ÞÅ.3?æŸ~ýoü…>YHJZƒú=Z¥=¸»y°7.žêþþD¶|E§ðãÚu|óýÏ%Ö»¤ß/zˆhnè&&§¥™æw¼Æ²6o‹åÀá? âò•+¬Xó5£ÆO$/?Ÿª¾>$%§ðÁ‡óÉËË·ùoä,ÓÿMxÀÎ&¥0iú &MŸÁ™³IøW«Æä coÿÿñR’–G)(ŠÂ™³É¬ß¼WWW7h`Z¦V«ywò[Ô« À?—2øcãfj„3ë·qqqaýæ­Ì_ø9߯ý•ûë×#-=}ñð«V•¦ÿ...üº~#Ÿ-Y~˾-Ë?“”DÜÁÃ4oúc_}€Ü¼ód‘õ¶•F£A£ÑƒN§#)5µØã5þËëååÉ‚YÿC­V³ê›ïøê»éܾÃ^Š`ĸÿ’œšFjÚ9*z{—ø7r&U«TaúÄÿ2qú{œMNÀ¯ZU¦Nµjw½>·1`z‘U=7t¸é{µZÍ Ï $ Àßô{Ðh4Ô­SÛôsbr2Š¢Ð´IcÔ.jôèiÁü…Ÿ“œšŠ=É)i4it¿iŸÊ†¾¬¾à?#ËòSR ÛÆ8DŸƒ Õõzf&õê…Q#$˜ƒGþâ?#_'$8ˆgúô¤}›Èb—™[¹hžžždçä°bõ׬[¿‘5ßýÈ[¯àø‰“üòûNþ}š«×¯¡×ë¹~-³ØzÅòxóòòÈÉÉ! ºju‰ÇkÜV­vA¥6|lV½0C`©\T¦åuÃÂHNMãZæu.]¾\âßÈÙ¸¸¸âîænúÙÍÕ 77·2©«´Æ% zuÖoÞ Àß§Ï ÕZ~†®íb–®ÀÅÅ… ÿáä©ÓhµZìGíš5l:^{Øò7r&gÏRû¾šL?ßʆVÆÔ‰ã™6c–!øï2¹ÏÃf¶Ätáåã^{…¥«¿"þàaâ"¼nx† €ê¦uß5ŒO/ãÈÑãèt:ZµhΖ;­–gùóÁ©VÕ—Í;vòÝÏ¿PÝ:¡¡èõ Š^¡Fp»öÆ‘_Õª¼ý „sêLb‘ËÌ÷ñÃ/¿†AÈ @^ˆêG›V€žáuxæ‰^ü¶a3›¶n§ùƒMˆhÑŒ3‰I%ÖÛšm±»P«ÕT硦òTŸÇ ‚ãæ¶Å¯ªÐDXÛŸõ¦ˆ-#gñýÊ%f?êæ[¹³ß}»Ð¼»ÅÚsæOÏŸiÑLž€7ñwÂ_³ïV%ï%¿oØLÌ’å¼üÂ`ºuîPÖÕ÷€:á Ç{€L Ã;^²1|–©ñsMϸ˜È£õeL§ÓúyoÜjÖ )‹êa3û»-ÎÕ¢+·6lÞÆ†-Û¨W'”¤ä4þ:~œ5¤~:ò;NMÆ<ÊX¥ŠÞäçkÙ¸u;>•*Ó£[¢ú>‰ü~…³“«-e,²e "[¶(ëjQjòH¾Â.2æ!„°‹Œy!ì"—j…v‘ðBØEL…v¹S‰!îeÒmBØÅî–GjÒGÖCQÎØé[1o[>ùº’×-Kß Ì.y%!îA*• ïJöú˜ÝÝ–òBˆ¢éõz2¯]µ{{óBØÅîðÑÞ 7GVEq7Ýn·Åî1ÞzÑûA»÷{ý;_F-DY“n‹Â.B»Hx!ì"á!„°‹„‡Â.B»Hx!ì"á!„°‹„‡Â.B»8ô¥O‰§8Ÿ–Rªmª…P+,Ü‘ÕBÜ ÄS èõ í»>ŽZm[ƒFQŽÿOâ© !ʇu[Χ¥P¿Q3›ƒ@­VS¿Q³R·V„eϡݖÒ‡-Û\ºt‰…K–±gß~222ð­â˃›0fä«TªX‘衯ðDïžôz¬ÇíT»ÔróòÐ+ *TpÊò„¸œöE×yyyŒû Âë1{Æ»T®\™‹ÿáÀ¡Ãx{y•iÝ–­XIrj Ó&OrÊò„¸œ6<Ž'œ 55•‹?ÃÅÅð©CU|} ¯W·Œk&„'¾T«ÕéÈÍËã\úùb׋?È /§c÷Çxö…—8tøOÓ2EQX¶r}=G—Çz1f›œKO`Ê´w˜4ušiݼ¼<º÷~’|jš—MÛÎÝHMK3Í[±z KV|Á†M[hÓ©+ïÏù€üü|æ-ø”>}н÷“¼÷þl²²rX´tƒ^‚NgøÐ׬¬z=ݵ¿ýVdyB8;§ †÷7 ,´6/¿6Šå«VsáâE«ë¥ž;ǸѯñÝê•4lx?oNù?òóóX´t9›¶l彩o³l᧸»¹1|ÔXòóóiצ5qñMå§NX(wï^dyB8;§ ww>[ð1ýž~’/¿þ–>}0iê4Nž:Uh½ž=Jƒðp|}}5€K¤¤¦’——Ǫ/¿bÂØÑ„…Ö&8(ˆ)oNàÆlÝEdDK®]¿Î™³gؽgƒ£ðÏ¥Ë$§¤°/î­#[•X×YYü´ö†<ÿ¾¾>øûù1tH4[wÄàææÆø±cY´d);wíæ×ß×óæ¸×üâîrÚððÒhxv@~üz ï¾=… /òâËÃo £À€4 YYÙ¤žKG«Õ^¯ži¹F£¡aÃûIL:‹——ÍxÀÔúصg/:t 2â!vîÞÀ¾¸xZ·Š(±žIÉÉ(ŠÂ„ÉSx¢ß@žè77§¼MVV¦ihL×Îxý͉Œ1ŒjÕªÞίFˆ2ç´¦æ\]]éоíÚ´fÀàh6mÞJݰ0«ëªT†wèæçå¢( :®Ðå`w77<<< ]—ñ´k z…à Ú·k˺ßþ {×Τ;ǃM—X?o¯Š|þéªøú¹^ppŠ¢àá.—dEùçÔ-K...T«Z7w·×   cFŠ¢p<áuj× áð0»öì¥Md¤a^d$Gþú“í;wñPóf¸ºZÏW­Vkú>0À/†±;‹¬ObR+V®æµa/óÁÜÉÌÌ,´Ü¼Ô€€€êøU«Ê𝾡mëÖ†í¼¼hܰ‹–.£Mãþþ~8t„ôôódggãêêJÔÀþÌÿl{ãâP…ó.p,!0„ÖôÿÍdÐÀþ ì×—õ뺪cYžåCÃCQ‡mS©R%æ~4¨è!¼4|þuŒùsfs_6•=fä«D¶Šà‰“‰Š~‘ë×2™ûÁ T*•iömÚpérM74ÍëЮ-ééç‰lÙÒj¹vëJ“F Íĩӈ~vƒ£0çÃytîÑ“a#Çp€•_~EVV6û>Àë£F°aó&öÇ(²^êÏ0M<• "D9ã°nËù´”R}ø1€Z­¦~£f¥n­!ÊžCÇ<òóóÙ¼m;Ãþ3•Ê…={÷ÝVy/¿ô"oŒsäºBÜkœþE×»÷îÃÛÛ‹ðzu‰x¨9›·n£}Û6…ÖYóõ·üøóÏ\ʸL£F 7ê56lÞÂ’_°iË6úô|œq£G=ôžèÝ“^õ`âÛÓÐxxðÖ„7Le-_¹Š¿Ž%0cúÛ…Ö]±zÍ-å]¹zO†·Æ»¹ýªÕüù×Qf¾S¸‹=ôÚµmÍö;9›|–ÚµjóÆèQ8t˜^Ë… hÞ¼oŽ‹`P^±z ¿¬ûŒËWhÒ¸ãF½F`@:ŽÏ/á÷ɺ‘EëV…_™ŸŸÏ§ ³qËVrrsy¸m[F†§§¼h[Ü>§oyü±q#íÚÞ#ÛºU+¶Åî$??ß´ÜxrMyëMV.]L÷.]ð©\™gô'úÙAtéÔØMë7zä-ewë܉í»vzåå¶ØtëÜñ–u­•×¥cGvìÚUhû±;éÔña«Ç²?.ž7ßË7«VÈóC_æü…óÌšñ.KÆ’šÆ‚…‹Më/ZºœM[¶òÞÔ·Y¶ðSÜÝÜ>j¬éøÄ,d×Þ}¼ÿît–-Š¡‚¦p(ÌúècÎ&§°$æ–/Š!--ù11%ÿÒ…°S‡Gvv6;vî6…GdDK²²²Øþå]ºb%ãÇŽ¦~x=üªU£[—Nh4›ÊŒh‰V«åÏ£G¸”‘Á™ÓgŠ|Áµ¥Ö­Z’““ËÑcǸ|ù 'ÿ¦]ÁK³-uïÖ•ºuêPÅ×—¨~ýÐëõDõëGP` 5k„ÐóÑî>|0 ~®úò+&ŒMXhm‚ƒ‚˜òænܸÁöXÃØÏ7ßÿÀÇ¡nXŒ1Ü´¯YYü´ö†<ÿ¾¾>øûù1tH4[wÄÚtlB”Ä©»-Ûcw¡RéiP/œììl<5ÂBk³yëv"#"H;—Nvv6 êÛwˆ››Û·cGì.š4jÄŽ;iÓ&’ lkÖ{xxжu+vìÜE£†÷³c×.Z¶hŽ—§g‰ÛÖªu9¹¹¦yµkßGVv6©çÒÑjµ…l5 ÞObÒYj×¾¢^·®i¹ù‹‡“’“Q… “§ *X¢ÕiÉÊÊ´éØ„(‰S‡ÇúM›ÈÊÊ¡ëã½ Í¿xñÆMfæuÀ06àââb×>ºvéÄœç1ì?/±u{,OôêYªí»tì@Ì⥼üÒ‹lÛKç"º,–¬½a\e67?/EQÐét….g_Ï™Ÿ—‡¢((Šbõr··WE>ÿtU|}KuLBØÂi»-™™™ìÞ»f¿Ïî­›LÓwkVrõÚ5â"((EQ8–Pd9Z­¶Øý´hÚ”k×39qò$ÇN”xuŲ¼VœOOçÌÙ³8t¸È.Ki‡„pðÈÓÿ¿ÿô½ÃZBÜ-ž^Þc€=@&dLù“P &‡ ˜× %5é4ÛÖ¯-Õv~A× uT5ÊÄÖ;hѬ™‡¸§8,<<<<®Š_`Rmg¼zPžmØ´™'{—î*åC/Õzxx”û (­ä”4Nþ}ŠvmÚ”¼²ÿ"N}ŸGyP#$ˆ›7”u5„¸ëœöR­¹Ix!ì"á!„°‹„‡Â.B»Hx!ì"á!„°‹„‡Â.B»Hx!ì"á!„°‹„‡Â.B»Hx!ìâÐGòO%p>-¥TÛT ¡V˜}ï]B”‡…Gâ©ôz…ö]/õg˜&žJ¢œqX·å|ZJ©>ü ¯=¨ß¨Y©[+Bˆ²çÐ1Ò‡-ÛLš:Vw¢ÕÈìЙ^O÷ãÝ÷gqåÊÓ:¿Àò•«lÞ_ôÐWøé—_‹\ž›—GNNŽÝËK2iê4æ~<ß®mEaÖGóx¤gú Ì™ÄÄÛ®örúÓ'ûôbã¯?óÛOß3mò$ŽO`òÔwLËnÛ¦Ðû\oײ+ygæûv/¿“~þõWââ²jéb>™7—!!eZqosúÏ0uws3½Òà&óÚ« 9šYYxyzòòK/–q ¤î§jÕªe]!œ?<,U¨àJ¥ÂÕÕPõ衯ðDïžôz¬:Ž˜ÅKøcÃF²³³éо=ñ0gæ B‚ oS‹?È?ÿ™ÄDB‚‚x}ÔHhÒˆ«×°d…á•›¶l£OÏÇ7z¤ißE-W…«×ð˺ßȸ|…&1nÔk”êØòóóùtáb6nÙJNn.·mËÈáÃðô¬Àÿ>˜Ík`Ýúõ„ÖªE·®‹­¯wR¹ ½^OÚ¹s|³ˆ'zõÄ£ˆwÊÎYÈþø¼ÿÞt¼½¼X¶r5É)©…ÖI=wŽq£_#À¿:1Ÿ/áÍ)ÿÇ_­æÙýÉÎÊ&95…i“'ÝRvQË-]Nì®]¼7õm*Tð`Þ'1 5–/W,ÅÍÍÍæcœõÑÇüóÏ%–Ä|B¾6ŸiïÎ`~L ãFdÂëcðòôäêÕkLüï¦mŠ«¯w’Óy¬ùú[Ó€éSþU/â_×ÜÜ\¾ýþþ;n uà`ôˆá·¬×ó±Giޝ¯ƒ£p)#ƒ”ÔT+%–,//U_~Å„±£ ­MpPSÞœÀ7Ø»ËærndeñÓÚ_òüsøúúàïçÇÐ!ÑlÝkW½„¸Óœ¾åñÌ“}ñÊË(ŠBTôTjk¯×5H;w¢^·®i^Ñk ÑhÈÊʶ«~©çÒÑjµ…m5 ÞObÒY›ËIJNFQ&Lž‚ª ÖZ–¬¬L»ê%Äæôááââ‚{AåÙý™óýŸy/OÏ[ÖÕjµ(Š‚¢(¥ºl¬Réí®_~^.Š¢ Óé í³´¯ÑôöªÀçŸ. Š¯¯Ýõânqún‹¹tÃã_}ûÕåAÁÁ<|ä¶ö£Õjm^bØç‘›ûT…ã '¨S»¶Íû ðÇK£aGìÎRÖ¶äú q'”«ðpww'ªï3¬þòk²²n½1ÊK£á±î0cÖlŽ;ÆåËWX²ü‹RíÃßß‡Žž~žìì[»2–˽4zöèÁÌYs8vü8—/3gÞÇøúøÐò¡V÷‘“›ÇÕk× Mjµš¨ý™ÿÙ"öÆÅ¡( ç/\àXBÂmÕWˆ;Å¡á¡(ÊߦwOÃÛè¿ùÞzëcìÈ4oÚ”1ÞbЋ/‘›—€º˜±svëJ“F lÁ ãAIDATÍÄ©ÓmZ>fä«D¶Šà‰“‰Š~‘ë×2™ûÁ T*ëûüá§Ÿy¤gŸBÓ… ‰~vƒ£0çÃytîÑ“a#Çpâ¶ê+ÄbíÿnuÁä ¸Lš‚Éð"²ndÎ6ßèôÉc¨T”êùãƒqz=„Ömp‡Q´K<þä3lùc]‘—w…¸—yzyö™@]0åLZ@)˜L6`\3”Ô¤Ól[¿¶TÛù\3ÔQոʼn“' ”àÂÁ× Å/°F©¶+íU‰’$&%‘””Ló¦òOF bÕ¿¿ÃÊBØ–×2­Txxx84ì‘y=“%+V2yÚ;øûUãÉÞ½éÓóñ2­“NÎò|¶éÞ…’ÂCoñ½ÞÊŽœJ£†÷³$fAYWCˆòFáæ9nTlˆ7²i-8Ì'!Ä¿Cqçw‘çº-—EŒ‰¤˜M:»«)„p6: Ÿß6õ0J Å쫱@NÞuB”ŠùymÅžçÖÆ<,›.æc: ×|µž^Þ#÷‚É­ ,nÞ'bÛ]YBˆ;ͼç`<‡ó¼‚I[0™ˆåùK÷Å–Sóà0î8¨P0Ä•›¢¢œÝú.Ä¿˜1Lÿøs38r &cxX «Š ó´±–XÆÖfË]–‡ÎÈò<Öq3<Œ“ñNRóñb/×ò(*<̃Á|¾yx¨ðÂYXëAo=·%<¬*jÌCeö½q‡* ‡‚q™ykÄÅÊzBˆ²eÞ‚0†ƒ±û’o1YŽ}˜—QHq-ãH«ŠÂb,È8ÏZwE‚Cçb­'a>b-8nyÎ\qcæ]•Å2óÁó®ŠqDK…p.EÝva"æ¦æ¡Qê1ãŽÔV 2†‡ykòÕ!­!œƒµÛ.¬ÝøYªÅŠkyÀÍ.‹ù|cá–Ýé®áü,oC· ËîJ‘ƒ¦%ìæ`Þ%±–á!A"„s°öœšù÷–½–`Û n j+ó%4„p~Ö®ž˜„µá‰"Ùz¢5Ž!ãB”Oz‹¯%Í¿…½'½´4„(ÿlþì!„B!„Bˆ{Åÿ Mã¸`ìÖIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/images/spinner.png0000664000000000000000000001513315074673150024742 0ustar00rootroot‰PNG  IHDRï†5‹Ý+sBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timedom 11 dic 2022 22:40:18® Ñï»IDATxœíw|å™Ç¿Svµ«Þ«å"Y6ÍvŒml ´8T‡’pI(!äB.´˜b ±ƒ $98åhL'˜:Æ]¸€%˶ä&«[Ûgî-^­WÒîJHZô|õy?³;3û¼ïÌê·ÏóÖAAAAAB(ߢ½þ¶-ÉŠÙÍë>Ñ)ÛÈc"^Aðc]´fÄ6.X¤0Ã߇¿V) |1ÛpG º;wK<âô´jØ6šhµx "ßa|m¤ˆ(û÷=¢Ç˜y4ïªF¼V#ö‹ç?ûÅÜøuÒ`{p,ž7Ò«F Tc¿xÃEl‰Á¶ Ô8Z#UÔzowasä¨*K YCI´3{÷Ÿ—7È%†(Ö°>ÚJ#ú $@&ôŠÃédñkoòÉçKÙµ§‘T»Qååœ}æ,&vXLŸ¿âê9¨ŠÂãÞOJŠuJ;¿»þfjëêP…¼Ü\ÊJJ8ñ„c9樃\:¡'ïpp¼†apç¢û¨^»ŽŒŒ _ÅžÆ&¾\¿3fÓ=°Z­Œ,ª(è}ÈÞ·£gLGUvîäËõëY³v-þ×_ýÛÁ.šÐ }ð¼Cõß°ÿ¨©­¥zí:9hwÜr#J sÌéraµXˆå¨ªÂÝóo Û3Ô<ÿqÙE¤¦¦°iófî¼û/|¾l9ï~ø!3=f0 8d8ëÜÙ|Ð8n¸êJ23ýƒ Û::Xøç¿²výW,~úïZ ›{ ±©—ÛÇë l))¡sιø—œüÃÐÞÞÎò«IKOã¬ÊÉ3OèrŽÅb則þ+ôþ¨éÓ°Ûl|ºt9†ipÊÌ8÷§?éò™ÞÎqº\<ùÌ?øbùJö9:9düx.½è|Š ºØ(ÈËcÉûRTTÀ]·ÞÔëuWUV2û¼Ÿsï²ä…ÄK~G1[ŠÏ—­@UUN;i&GL=œÿýû“lÜ\K~^.—_r!‡4ðG7/¼ü~ò{öîeDYçžýc¦Lžÿö-S>¢Œ _mäæ;pûMsP…[ïXHmÝVF”–xyïò1¿û©ª²«ÕÊæš-üúªßóؓϰuëö&j½üÚ›lÚ\Ë„ÃaïÞ&þöðc,]¶²Ç%ÆÞûàc–¯\CyY)íí<ûâˬXU×9º÷¿xãíw?n,G>™•kª¹óO÷bøŒ}ô)Ï/~•´´TF•—xÝ|ŸÓ§L`[CC\ù½ÿá'¬ª^ˈ²Rš[Zxâ™çùÝœ¹¸=òr²Ùºm;wßw?n·Lxè±'yê¹Ð4É'PS»…Û.bý†ƒþýG¦?\-%Å…ÔmÝÎÍópóüÔÖm¥0?Ÿ[®¿&qÛ "ž·òrr˜{ÝU<úÄÓÔnÝÊâ×ßäå7Þâû3Žà²Ù¿…N9ÙYÜ{×íhšÆÇŸ/åî¿<À›KÞaúÔûµ––Êý‹þˆ®ë¼øòk<þìó¬]¿)ß›Ó9µ[·²bu5S&Oâšß\ø#„O—.£açÎ'PU•;o¹‰qc+âºv»ÝŽÝnÇápâóùØZ_S~ii©<°è¨ªÊÿýãEž{ñef{ ¿¾ìb®¼î¶Õ7Pß°ƒŒôtÞ~÷}ÊG”±èŽÛÐ4%ïÀýÿó/½ö‡4.®2Ûäåæ2î ÌuÛ¶PŸÇ¼¹s(ÌÏðòô¡Áª?IÄ„CfÑ]·±ºz-|ü)Ÿ}±œ>[Š¢ª\õ—`Ñ-¨šŠ‰ÉS&£( õ;vpÂß«ª†¦k˜˜T« µ­=æs¶×7°bÕÎ:ov—|Ú;:Bvìv;UcÇôú}™¿ n·§ÓIqQª¦ÆœŸªj(ªÙˆq•þ ESBÇ«*+ÙVß@[G;{››1 ƒÉ'„îß÷œÎýÿóÛêë‡äÿ˜¦éX-û{ ,º‹Å2(eÏŠ¢0yÒ&OšÀÌãå–;°vÃWQÏuº\]¾àÞеÞk/‘礧§0eò$.þÅ9]Žõ‡¨^·Ó4U>2áüTõÀëÒ®Ãéôß+Ÿá ís¹Ü(ŠÒ¥]a¨ÐÜÒÊ-w,`{}C(ÒØÞÐÀ­w,dÞÜ9ädìb2Rçí!yÜ6×lé²Ïëõ/5”•ª¯8:÷u‚ kª×þé˺¯WF»‡qž3²¬UUÙ¸ñ2Ó3(+. %‹néÞFwõ­°};vìæ‘ÇŸFUU~ö“3Ïö™P^VÀò•kBuà•«×`š&£GF©Ÿrº}á=!áΛ;‡ysç0¢´”í ܾ`Qâ¶DAHR›‡VD3øÈý©óör?„EZ›ûÈÿ=ü·Á.‚0L‘)‚¤HW’©ó B’"]E‚¤ˆx!I‘+AHRúÐ`%ò„ÁDÂfAHRö¼õ[kû³‚ ÄIÂâ~ÌLÚZšiÚ»Ǿ}ýV(Aø.cOK#7¯Ììœ>ÙéÓðÈÝ;êiijÄšb##+»O„á‚×ãagýVœŽN Kʶ“°xÛZšiij$5=#áÌa8¢[,è -MØì© ÛI¸Áªiïn¬)¶„3„áŽ5ÅFÓÞÝ >añ:öíCµIW‘ $)"^AHRD¼‚¤ˆx!Iñ B’"â„$E ‹“––ž}éV¹ŽÖÖ6²²29xÜ8.¹àÒÓÒp{<˜¦IŠ5öõgþ½qÕ ·pìQ3øñéýó8–þ¶'ÄŽˆ7<óþ™Š1£¸ñšÿ$##¦¦Ö½‘T»€_y»vqÕ¯/”ü{cÚáߣbô¨~+SÛbGÄ5µ[عk7wÏ¿5ôøÊìÌL*FLšüÏûéOúµLýmOˆox ·ÇÃîÆFŠ 8¾øõ·xá•×øì‹œtÂq\:û| Ãàå×ßâ½>¡­­ñãÆrÙ…çSŸÀœ[çsÜÑ3øtérê¶m§¬´„ËfŸGå˜1qå‹­9·Îç¤ÇÌ㎠½Ÿ1õp–®XŶúJ ¹töù4nlÌÇã±gO¿°˜?]ŠÓåbúÔÃY·á+nºîwÝ^“i°ŠƒªÊ F–—qó yéµ7ÙÛÔÜåøY³Náì3fqÔô©<÷ØC\:û|ž[ü*Ÿ-[ÎuWþš…ónÆ¢[¸õ®?…žõ ðÞ‡Ÿò‹sþûÌgüØ n[pû:;ãÊ?[á¬þr¿¼èXôGªÆV°è¯ëR¶ÞŽÇcï‰ç^`uõZæ\ýλEQر+ññ½ÃoX-î¸ùfôCÞøç;\qõïùó²eÛ¶n?ãñxxõrùÅ0²¼Œ¢Â~{ù%8N–­Z:ïÔOà ª±äæd3û¼Ÿ“•‘Á'Ÿ‘Pþ±Ø çØ£gP1z$Y™üäôÓhnmí"¨ÞŽÇjÏíöðÏ%ïñ«K.dty9ùy\ü‹sºµ#ôŒˆ7Nì6gÍ:…ÿ¾w!×üæWìmjæ†?ÜÙ­€wíiÄëó1fÔþF””ªÆVPß°#êgTUe\U%;vîêsþ=ÙŠFA~)))8®„Ž÷tþ®={ðcFí¯£G{Ƭ"ÞÑ4éS§0ïÆß“Ÿ—ËgK—G=Ïè:2Œ.VÅ¢[°Z»Ÿ•¥)*Öº›bÍ?[‘(½(ª·ãÝïóy1MS/ìD¼}DUUrs²±„Môù|¡×ÅE…€É†›Bû ä¦v #ËF„öu:œ]ì~S»…ò²ÞWYˆ–¢¶¾mŠ ÷âëM½ž+ôŽˆ76~SÃ#O>ÚµëÙ½§‘»vóüâWÙ\»…£Ž˜ @^n.ë¿ÞĞƽ¸\.ì6?8özô 6×ÖÒÒÖÆ£O=Mff“&²ýüâWX¶j mmí<÷Ò+8œNfL;<îücµ5Øm6ŽÿþÑ<øèã|SSKk[;ÿxùµÁ.VÒ"]Eq‘îÁôè“O³go))V*Gæ¶®¥´¤€ãŽ>’Ukª¹êÆ[8ôàƒ¸áª+¹ä‚syòÙXpßýø¼>&z(s¯ûJXü9ñЃyâ™çinie|Uónü=º®Ç¬¶‹¿ð<{êî¼ç/¨ªÆ1GM@UÄÄK´Ú‹H:` ${ ¥éÀôŸ}x,:×?Dö•[Ask+¿üíµ<õðX‡áÊ,í­-L9òØ«¥@Ð 8ÉH^À¤òs' *[ê¶R\X0,…ÛW†F,% êvP¿s‡4ž–ÖVžzöEÎ8í”Á.VR"â”}^xùuî{à!rss8yæ œx±ƒ]¬¤D꼂0ˆHW†!"^AHRD¼‚¤$,^{Z^§?Ë"à ¯Çƒ=†¥‹º#añææâv9{?Q„¨¸]Nró_€ ᮢÌ윎ÎÐ#>å¹E‚^·ËIvn~ŸžÑÛ§~ÞÂ’2löTšöµ¥/¦aØ`OK£¸läà>\ü¸¯…!~¤µù;ŒÏç;`ể ü`š&--­|S[CmͶnßFk[cFâÈÓ©=š”””Á.¦Ðψx“·ÛMݶm,]¶œ5Õ_²}{=-m­8NÜn7†aðÅŠ\|ÁLŸ6µwƒBR!âMB Ã`oSŸ/[ÎÇŸ|Ɔ¯¾boSS—åw‚lØð5ÿúècŽ˜:¥Ëä!ùñ&^¯—ú;x{É»,yï=¶m¯ïqA7·ÇCcc#>ŸoȬ¦!ôòm&>Ÿmõ ¼¸x1o¼õv ©IµÛ)+-á~‘o4I0M“=¼òÚk,~õu<1 MµZ­ŒWÅÏ^Ÿ/ ^0M¯×+ÏJÄóq:::Ø´y3Nçs§gLÊ´)‡“šjKÈvP¼†ÏÀÄÄðùðºfÁÔMñ¾CïçëMßàv¹CIAh³Ù˜6m ¹9‰Ïè2MÛaš˜\QU<ºß“…GÄ;ÄinnÆ0 4M‰·¤¨üÜÜ„'(Š‚Ï4ñz}~ûªŠašø\nUá&"Þ!ŽÃéÄçõ…Z€MÓÓ¤° ›ÍÞ7㦉ÛãÆ0LtMCQ Ó2•0 ñq¬V+ª¦¡kú`MÓDïÏð¼^¯ª¡ª ª¢¡ë*†! VCï'Õn'ÅjE·X(üû]N'ím Ûõw™ø|^¼^/þEùýØíiXS$lêHWÑ';;‹ììlt]G×5,º‹n¡­½ƒíõ;îÒ1 —Ëž}x½^ ÃÄ4Ágx}žP–0tñqrsr1¢‹®£©š¦¡ë:.§“Í55457'd×ívÓÒÚŠËí„Î^'^¯]Ó¥Á* ñq²³²[1EQÂÕH±ZQU•ú†–­\wã’Ï磵µ–ÖV¼>ÿÀ ·ÇƒÏð¡ `±è¨ªük uäâØív&MœHNNº®¡**Šª¢ë:§‹Ï?_ÆÆMßÄlÏ0 š›[ØÞЀÓéÀðyñzŸ—˃Óå`çÎÔ7ìÄåq¡kº¦ãöx0MÐTUÕ(È/ä«bEÄ›(ŠÂ¨òrf<|ôÞÀ$]ÓQUQÙ¹sŽN55µäççc³YÉÊÌÂíöÐéèÓ¤ÓáÀ–bCÓU‚NÚgX-V<^/#GŽÂn·É˜æ$AÄ›DüèÔ“innfÃW_…¬éz` ŸŠËí¢µ­¶öl6+º¦“š–Šiú§ùÙ¬)¦ ^ðâU@×ü‹Ú•–“—›†) }D¼IDZZ§Ï:UUù¦¦—Û¢€¦ihš˜¼ bšŠâŸìóèššRèñxÐTEÑQUEW)).bdy96›U¼n! VIFYi)³N=™É“&‘›ÅbAUýVÃð¡ª*¦iâv»»|Ökøðú¼˜€i‚Ýf£¼¬”Q#G’––*ÝCIF¬ž7²S†ß "e¥¥œ4óJKŠX·ákvïÚ‰é_ÞÕ4QTEQüb4MPTEÁãñ`µZIMµ“—“CIi ………ØSRD¸ƒK¤žb6×›x͈×f”Œ„A //Ó§S>bu[·Ó°sìÛ×éŸUÃ0ðz½hºFªÍNJJ 999RXP@Vf¦¬çŠ¢ Z¢…!®úŠ)ÂíM¼FØ6hЇ„ÎCUUQU‹Å2ØEâ#\WáÂíQgÑÄéºÃëº>ü?½©iéWÖ@²liø[°U@úÁOxäÔpRpBu¸€#õw@øKƒU¸pƒ¯l°Î~+H7”  2äüØ/\g ÅMÀQéN¼ájö‹ô®„×Ï+шԑýâ &]½o¸€£Š¸·Öæhâ føþpñ*ˆx!H´ÖC×й'ñF¥»:¯ö:˜¡BWQ…{c-Êy‚0Ü ÷ AqÃgODЬû†ÛèBOž7ØÒ¥ÐUÀACÁ}ÑÂe® t%Z$^Ž&Üà¹Qé©Î+ÇÂ+ßá¡r°,U‚Еîº]ÃEÞ`.Ú¸ë¼ÁŒÔ(†‚â ÷¶‘^W¼¯ ø‰ÖímàS\5zò¼°?dß4&K¸,½9 2R°‘ár·V½‰-\á!q4ÁFŠW„,~¢Í9é§WáBl‹¥e¿ˆVz'Zëq¸@£UO»%V¡uW•ú­ $†±ímÿ$*:ñ´‚Ðwbž»+‚ ‚ ‚ ÉÿiôÖpŽ%GIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/images/spinner_ext.png0000664000000000000000000002266015074673150025625 0ustar00rootroot‰PNG  IHDRïãm²CÂsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timedom 11 dic 2022 22:52:38 URV IDATxœíÝw|SUÇñOVÛ$]é‚¶”UZödº@† ¢(CÁ­8*¸PAQAœ¸@E!"{‰L¡ÐM÷NgòüÑ&¤!]é"ô÷öu^ionÎ=¹õË9÷äÞB!„B!„⢨Çúêºn!\•¹‚Ÿk¥6SØ=Ú?'ᢔǡ5Û=Öˆ3³¦íï¶?+i!SÙ£mˆí]QÀ+T“ðÚ÷´J›GG¡UÕ¤!B\ÄJÊíClr°Üö±RêjnÜQ華ûYi·\z^!J©8VË£‰ÒœTØ*\ž×¾Wµ¨Šsáµ ±¦u ÑQ>´–RBù@ÛöÆU£«êyíƒk[Tœ ®ð/@[º…h*Š# $ieËT”¸„Ҝ٣-¹«0ÀÕ ˜}pÕeV>@ëõë~½;"<| ¼1ËL³å(0c&ëÄÉ“¿^3d؇Ài “sd±Ý+LT¡²)(LkÛËZJÐáÌ©Rb!DÕ2[µ¸8 $Q\K±NW8|®,¼¶³É–!²%´n€/ÐõÌ©_`6Ëñ­5¡Pµj1 øÈ 9`ËPÚ~6º|UMùYd%¥Pê²Gw kÔÉã+à]'oFˆ&Æ YmÂ#'PàJ'¶ŠËm'¶ö¾Õù8ÇvØléu_ûËí\!œ§ïß×þr;¥½nœ›K²|bS©ŠÂkÿY®ýñnPDDøµµm¼M]YŽ‚8—-KGi.Åy*›m¶:[*×¾ ¥Â sc-D“¤P*¼(?ÒpîX·„ÒÌ™)"G9Õùœ×þ³]5 3›Ì ùpss£eX ” jú‚ÝoýûöA©TŸ˜È?‡sàÐ!¶nßÉ“3i즉 Ô¢ç½Pÿ7¬;§¢¢8xè_:uˆäåçžFQöáX~An ÕÙJ¥‚7_zÞfÉ…¶ßJÛóà=·£Óé8qò$¯¼ùÛwífÖ-\=h`c6ð‚1fÂ:vˆä©éãí]zraVN¯¿õ.‡å‡Ÿ4h{dØ\‰”´t )*.. ,x¸»[×ǽ\{ÍUdgg³{Ï~ôžzÆ\7œk¯¾²Ü:Ÿ-yÏú{¿>—¡õð`ێݘÌ&†]}%Æ-÷šªÖÉ/(àó¯¾cçî½äóèÔ¾=wß>‰fåêô÷gÝÆ-4kÈ«Ï?SåûŽgÊÄ[x{ÑbÖ­ßd ou¶wyïKñp÷`û®=(•JF ½šÞ—^ÂGŸ|Îñ“Qøûqß“éÜ¡=P:ºYùã¶üõ7É©©´ eÂ7Ыg·šÿÁêYX‹PŽ=γ/ÏeÎ3³P(<ÿòëD‰¦EHHƒ·Çù|̉o‹››'OæéO°ü󯈎Ž=ïB­׬åÄÉ(ºvéDjj︜»öVz‹±?6oe÷Þ„…†Ã׫~dϾƒ5Zç·ßã—ß×Ó>²½/éÉÞyå·1•˜¬ulúsßþðz½ŽVaaç¿Ï þž}zõ &>¾FÛÛ¸å/ö[ATt4?ü¼–ù•}{sÏ”[­C'ƒ¯o¿:•JÅÖí;xóE¬]·ž>—^RaÝz½Ž…ó^C­V³êÇ5|úõ·:|„^=ºUk¨èhöì?H¯žÝ™ùÐT t„°mÇ.â­=R©ä•çž!²]Û½w­V‹V«Åḩ¤¤„踸jmO¯×±hÞk(•J¾ün߬ú‘« ä{îàáÇŸ"&.ž¸ø¼<=ù}ÃFÂZ„2ïåÿ¡R©X·q3 —~Ì÷k~¡S‡Èµ¹¾ùûùñÒ짘ýÒ«œ‰‰ 0ÀŸgÏ"(  ÁÛS‹ «Zü“áBºvîȼWÿÇþƒ‡Ø¼uïÜÍŸï@¡T2ýÁûШ5(UJ̘éÝ«' …‚¸„Äóö‘íïJ¥ •Z…3‘ádfeW{ظxöì;À˜‰SÊm';'ÇZV«%¢]›*ÿ^æ²ÿ, ÉÏϧy³@”*eµ·§TªP(Ko^ú†B¥°>NL\ÞÌåå–5GW,Ø^=d9§Y[Vt€'Ðç¿cÿÎo¨F^È&Þu?Þž^|°àÆnŠpQíÚwžìr€*ÂEIx…pQ2a%„‹ªÅ„•ÄWˆÆ$Ãf!\”Ó=o\tT]¶CQCN‡·ÏÀ«ë²Bˆ’Ó#/"EEE;~‚-[ÿâÐáÃ$§$£V»Ñ±}$×¹†Ý»áîva}cƒpž„÷"‘”œÌ/¿ýΖ­ÛÈÎÎĘ_@~~D>ÍÆ-2lèn3¡paQ÷dÂê"œ’ÂÚß×±s×nÌf3j••R”ÞÔJï³µzÍÏ|òù—$$&6fsE‘ž×ŲoÿAŽ;†F­ÆÃ׃®ú1x@šϪÕkøcã&²²³Ù°qaa-ÓhʾB¸& ¯‹‹OL$ál"jµ èOÿËûZƒÁ#S§À—_KNNûö WîtêØ±‘[/jC†Í..+3‹Üœ\<ÜÜéÔ±#]:u:¯GÕé<Ô¿?—^Rú&g¢c¬wü®KÂëâJÊŽiµzAxyy:\/4$Øz£ðŒôt2Ò3¬¢~ȰÙÅ©Õ*ÜÜÝ@¡@£QƒÂÑ AK¿ö¤yóæøúú¢Q«Ñéµ ÜRQ×$¼.N§Õàï1ÏHII ùFc…Ÿåz ­[µD©TÒ¾ý…õ%^¢æ$¼.Î×Ç›?Ζ$“‘•EJj^^^¿'H¯×[{…ë“ðº8ƒÁ@P` ™YÙ( âhÞ¼ZëzŽÂ,\›„×Å)•JB[´ °°ˆä”T” ™YY˜L%hµ:<ÜÝñðpG«Õ¢R©»¹¢Ix/z­–ð¶mÐé´¤•Í"—” P€R¥D©TÛ}—¸Hx/Z­–Ö­ZÑ,(ˆììŠKJP©T¨”JT* îÅHÂ{Q*•èõzôz}c7E4™ÅÂEIx…pQ^!\”„W%áÂEIx…pQ^!\”„W%áÂEIx…pQrz¤ž}që6l@¡P@ß>½yàž»ðõõm´vM˜r'Ç^ÃäIëeýÚÊÉÉá½–°ÿÀAÎ&'Ó2¬wN¾Á4Èö/6^'3šgâ’NŸŽæÍïðÜ‹/óÎü7­Mƒô§}dõïQÓõk#3+‹;ï{€Ëz]ÂsOÏBïéÉ?ÿþ‹ŸŸ¡A¶1’ð:ÉM£±^н[f<ò<:ܼ<ô:]£´éþ{îª×õkã˯¾¡SÇö<ùØ ë²Vaa ¶ý‹‘„·Žxx¸£P(P«KwiQQ,ýˆ ›6“_PÀàxôÁÐéJïnqǽS8 nÝÆ™˜3´i݆'¦Oc߃üøÓ’’’èÕëž~|&¾¾¾±hÉR¶nÛFRr*Í‚¹còm :ÄÚ†;îÊ ×bôÈÖ߯<ÍþEÔéÓ´ á±iÒ½[§Ö/))añGËø}ýŒF#W ÄÞýûxëõ¹„†sÇ}SéÑ­+Ózð¼ý³fí¯ÌyþÙúû4A2aUKf³™¸øxÞ_ü!7Œe½ùÛ¼wÞãLL,˿ϧ.&>>ž…‹—{íî={yú‰™|÷儆sû½÷s6é,óæ¾Â²¥‹‰‹gÑÒÐh4´ eîKsørùGŒ>Œ9¯ÎåLLL¥íÛ±s³fLcÕŠ/èܹO?ÿEEEN­¿pñR¶ïÜů¾Äò¥ P*ˆ‰Îû;:æÏÏÏ'5- ƒ¯ÿ{ùUFÞp7Ü2‘_[ý-Î#áuÒWß®¤ï૸üŠ«¹q­tëڅǧ? @n^«×üÌÝ·OÆ`ð%(0{テÍ[ÿ*Wǰ¡Cˆh×?ƒI·Ü‚ÙlfÒ-·L˰Œ>Œƒÿ±®ã˜ëiÛ¦ ¡!!L™4‘àæ>r´Òv:„ö‘ ¾L™4Ô´4bãâj¼~AA+¿ÿ§ŸADx8ÁÍ›3ýáò=쯼Äí·N:¯Îä”4,ü€~}ûòåò˜öÐT–,[ÎÆÍV¾£E…dØì¤qcÇððÔû1™LLºãnÊsw«ˆŽ‰Ád2ñäsÏ£ tyqI1yy9Ö׺u+ò ¬ËÚ´iEžÑhý=##ƒß×ÿÁC‡ÈÌÌ$-=‚üüj·9¸ys´Z-yyƪW¶[?>!“‰öÖç«{/F\;”!W_ Àà3úë7näÊÁ«ýÄ9^'©T*ÜʆȷMÏÂÅK?î&ô:žúÒÿY?þ`~†êͦ: ‚Âfi^^>wM}ˆ«âîÛ'Ô¬ÓŸUãv+f§Ö/..Æd2a2™j|'Jo//ÜÝÜð÷÷+·¼uË0Ž;^£ºÄ92l®#®Š»»߬\@pó ôZ-[ÿÚVgÛ8zü™™Ã­wÝCAa!J¥“ÉD|B"É))_Û­k^›ók~ý›'Mæ“/VðêœoÛ¦!ßÂEÅÑÀKYVÔ€¦¬hËŠðúäåæÌo¨FŠ SjZ×Ǧß×VøýH¢j:½ç `äƲRTVŠSY±’žW8íø‰´ –à6™mÕv::šèèzõìAJZ‹Ȥñã»YM–„WT[NvË>û‚çæ¼LP`c¯¿ž1£®kìf5Y^Qm]:wbÙâEÝ QFŽy…pQ^!\”„W%áÂEIx…pQµžmÎÊH'-5 cnn]´Gˆ‹žV¯ÇÏ?oßÚÝ¿«VáMJˆÃhÌ#¤Ek| ~U¿@Afz qÑäó uº§Ã›•‘ŽÑ˜G‡.=œÞ¸M‘ÁƒGí'+#Ýézœ>æMKM"8´¥Ó¢© mIZj’Ó¯w:¼ÆÜ\* Q >¿ZÍÉl³.JÂ+„‹’ð á¢$¼B¸( ¯.JÂ+„‹jðþðÃDFF²páÂrË÷íÛÇ!C0 0€Í›7WPƒÂ^½†wÏž=\qÅ<úè£å¿bãøñã\uÕUŒ1‚}ûö1räH†Îþýûë³IB\4ê5¼ü17Ýt'Nœ C‡åž{ûí·5jÓ§O§uëÖ<õÔSŒ9’·Þz«>›$ÄE£^ïae?L¶õí·ß²|ùòrËÆÏ]w5Ü> áÊeÂÊh4’’’Bxxx¹å‘‘‘dff’ÝÍÂ¥4Jxðññ)·Üß߀ÔÔÔo“®¦QÂ[QH333 jð6 áj%¼ÞÞÞxyyqâĉrË£¢¢ð÷÷G§Ó5F³„p)v’ÆèÑ£Y±bE¹e+W®äÆol¤ áZífΜIÿþýyýõ×™4ikÖ¬á»ï¾cûöíÕ$!\J£õ¼={ödíÚµ¬^½šÎ;³bÅ Ö­[GÇŽ«IB¸”ëy×­[wÞ²Áƒ³uëÖ†j‚¹0A%áÂEIx…pQ^!\”„W%áÂEIx…pQN‡W«×“™žV—m¢IÉLOC«×;ýz§ÃëçDB\´Ó¢©Kˆ‹ÆÏßù+蜯·¯­VÇÑCû¥¢2ÓÓ8zh?Z­®VßÑ[«Ó#ƒ‚CÉÊH'>ö4'ý[›ª„h2.ˆ/׆Ò¸¶BÔœÌ6 á¢$¼B¸( ¯.JÂ+„‹ª“‹ñÍfs]T#D“¡P(j]G­Âk6›ÉÉÎ"'3ƒü|cÕ/Bàá¡ÅÓÇO/ïZ…ØéðšÍf2ÒR0æå„ÎÓËéFÑ”äåd“’œDqQ!¾~N×ãtx³³31æåѲMxÕ+ !¬tž^´ôô":ê$*M¦Óõ8=a•“™I@ |³Î  "'³Â[o”¡²µ óô¢ sEòQ‘.JÂ+„‹’ð á¢$¼B¸( ¯.JÂ+„‹j´¯ø¼˜åìÙ³‡˜Ø8òŒF´Z-ÁÍ›ÑÿòËñpw§¤¤³ÙŒZ]ûÝ_U]Žžÿzå*"Û…Ó³{÷Zo_4 o+))áç_ÖÀˆk‡âîáA^n.ñ‰‰¸»¹°wÿ2³²¸æÊ+j½½ªêrô|›V­pþ´ÒZwë–aœŽŽ!##?ƒ/ûõ#>1‘#G‘››KHHƒ @«õ Ädb×®ÝüEII1­[µ¢_Ÿ>h4š ÛÛ"4´öxÓ%á­cÍ‚ñóóã‡5?ÓµKg"ÃÃÑÛÜX»G·nŸ7”õñöfØkP«Õüwê·l!((_ë:mßN¿>}¸¼o|¼½iê°®ª¶åH\|ƒôG§Ó±mû¾ûáGºuéˆk‡b2™ømývîÙÍàJÛò÷ßäææqã˜ë1•”°qó¶ïÚUîûöŠº%³ÍuL¥R1fÔutëÒ™þ9Äç_}Íú›HMM­ôu;uÄÏ`ÀÛË‹KºwÇËË‹¤¤ärë\ÖëÚGFàïçW'“]¶"Ûµ#ÀßVK®]èÑ­+^^^øøøÐ¾}$ ‰g(,,äÈÑc\zIO´èõz.ëÕ‹¨Óg¬½BzÞzá¦ÑУ[7ºué™èh:ĪÕ?1vô(üýý¾ÆhÌç¿S'I<›D¾ÑˆÑh¤¸¸¸Ü:jUÃü¹ †Ò[ùÚnßàëKQQ™™™˜Íf~[¿Ë¥ä&“Éú|C··©’½[”J%mZ·¦UË–|½r§¢N; oQQ߯^MÛ6m¸´gôžžüòÛoÐâŠÙÞïÁÝÝ€±×F§Õ6Nƒ„ ›‚R©D¯Ó¡TÛÝ&“ÉúsrJ ùôí}ƒ7†šÜŶ.gž¯)OOOÜ4Μ‘ïªjLÞ:v6)™¿þÞNl\ÙÙÙdfe±{ß>’SRoÛ½^OBb999¡Óé(,,äßÃGJ‡Ï'O’šZ½ï²¯«¦Ï;C©TÒ½[WvîÞEl|·Y¥R¡Õ{¡PªHI>KAÌ™ª_$„ÀÝÃ­Þ ­•Jåt=µ /€R鉻‡“ÉŒ³Ó ¢)P @©T R©¬ÅYN‡W¡(m€åÑl–à Q ……BR©D¡¨É•ÛåÕê’@ ®ΩMh-êäzÞºhˆ¢fä$ !\Tô¼2l¢f}Øl6›ÉJO'=-c^n­#DS Õé1øâm04΄•Ùl&%)Üìlš…„áíãët#„hJ²238CaQ>AÁN×ãtx3ÓÓÈÍÎ&¢cW§7.DSäíã‹·/'ŽüƒFãît=NOX¥§¥Ð,$Ìé ÑÔ5 #=-Åé×;Ýóæçåâåí#“UB8ÉËÛ‡ÓÿuúõòQ‘.JÂ+„‹’ð á¢jy’†ï ÑX¤çÂEÕò «ºj†¢¦ä[ëIjj*K>ú˜¿wî"-- ƒŸžÝº3sÚ#øx{SPXˆÙdÂÃã^¶ï¨þ[n›Âˆ¡C˜rÛ­õ²MѰ$¼õ °°§Ï¤cûHÞ~c.¾¾¾$%%³ïÀ¼Ên8¶ìÓψ‰å垯—68ªðÀthß¾^¶'ž„·9vŒØØX¾Xö‘õ6'~ÚG6j»¸÷žFݾ¨[2Û\ŠKŠ)(,$!1¡¡ç=ÿé+øø“OذqcG扙Ó0™L|úÅ ~úe-éétëÚ•Y3¦ܼ9Sî¾—×e݆üwê­[·â‰éÓèÔ±CµêŸr÷½Œs=×_7ÒZß زu+§££iÛº5³fÎdß|¿ú'’’’¸´×%<3ëq ¾¥ž±hÉRÖÿ±‰‚‚®8i?ˆN§µÖy˸›Xó˯>r„¹/Ï¡Ïe—ÖÏŽnâd¶¹téÔ‰vám¹çÁGøäó/IJN.÷üäI¸sÊm ¹úJ¶oþƒ'fN`ɲålØ´‘¹/½Èg-ÅM£áþ‡§QTTd}íê_ÖòðCSùöËÏèÚ¹3NŸIvvvµêwdçž=<3ë ¾ÿz¡¡!L¾ûÏ&òö¯ñéGKˆ‹gÑâ¥Öõß|ûÎDÇòé‡Kø|Ù‡ÄÆÇóÞû‹ËÕ9oÁ†ÂÒEïѽ«|{}©UxÍf)ŽŠ›Æ¥‹2~ÜM¬øæ[FÝx3Ï<ÿ?ŽøÏºeÅò{AA!_¬øš'{Œð¶m á…gž&77—Í[·Y_sóرtëÜ…ÿ¦=ô _~_ÿÇym°¯ßÑ2Ì0bèP"ÚµÃàk`Òø ˜Ífn?àæÁ„µcÔˆáì?øf3äääòÃOk¸ûŽÛñõõ%0 û﹋þY®Î{+ëÔz–„IDAT† §]x8îîþ÷¸KmÈ1o=ÑëtLž8‰7ãÏmÛøòëo¸ó¾©|¼ø}"Ûµ;oý¸øŠ‹‹éyî¸X«ÕÒ¥KgNŸq|Ol¥RI×.]ˆŽ‰©“6·iÝ €ü‚ürËòòò8‹ÉdbÖìÙ((½ˆ¼¸¤˜<»1x¸;™›¨>9æ­gjµŠ+ dPÿ~ÜrÛíü±q‘íÂmÖ(݇…E˜L&JJŠQ*5ÖgÝÔÜÝÝ8·¯ÍØîw•RYöqPE ûåf»eç~W8؆%¤`ÆK¯`ù’ð3*ÙŽý6D}cÞ¢R©ðGãv.˜ÅÅÅÖŸ-[û´.3™L9vŒvmÚZ—å”õ‚‡¥M›Ö·i[]nÞ ½NÇŸ[·Õi½Â9ÞzpèßÃÌ{ç]vìÚM|B1±±|¸üŽ;Æ5W^@PP{$1ñ,F£½NÇè‘#xíÍ·8|ô(iééÌç]ü|}éÓûÜlí‡Ë–³eë6222Xºl9¹yy\5xÐym°¯¿.¨Õjn8ž÷/açîݘL&Î&%qøØ±:©_ÔŒóÖoo/æ¿ó.‰g“pww§S‡ö,Zð­Z¶`ĵCضýoÆO¹Kzö`þk¯2sÚ#¼÷Ábz6ÅÅÅô½ô2Ì£ÜMÊz÷êÅ»ï@Jj*]»tbñ» Ðh4çµÁQýuáÎÉ·ááîμ¥ïÍÏ``òÄ t’“?œ£[×)ËŠДmYÑž@Ÿ=o™ß©»|~×n¿ç>Æ^?šÑeŸÓ ×wøÀnz]>h°ÈòcY)*+Å€©¬XɰY%³Í.Iö»žW—%V.dùÒ» â"=¯.ªÖßU$„hÕíyíSjr¸–ÂöyªV¯XUx°jðÐéÉÉʬvë„åådeâ¡Ó[~5áøÄó U^GÁµÉgjÜ`!D©ä³ øøÀA¾lV«0ÀÕ6[þE0Ù”½·:OO¢N•XˆÈÉÊ$êÄQtžžè½}J(Ÿ/ë·2UMX™l-–&•J…·¯?j•ÉI Äœ>éä[¢iñÐéðöñCçåe¹Ç™5W”n¥v^û®ÛöX·„Òó,‹½}|ÜÊŠ¦¬.çÎvþ+¿…¸¸ØŽ\-* ËJqY± °}þÎ>WÕóÚײá=€GY±X͹+Ï…°°ÒÚùq.¸ùeÅ^Gv¨¢ðÚ¦ÝÑ¿–Þ›çUHÏ+„#ö9*á\x-Årõíño…½.TÞóV^Û`Ú.· ¯ ¯ŽF°–Ëýª^‡*:æUØülÙ ‚ò¡´Ùûc_Û:Ê©¬çµÌt)(`KE–eކË\!Ês4’µ=vÜó.À·UÙ1¯íÐXa÷œíÁ·íPÙr,“UB”WÑÇ®¶!¶°² my-R:¨È^ÛÞ־וÞWˆRŽ>v=ïÄ'»ß«”JË%´BTÍÑì±m@žV¨ºA«è8VŽo…pŽÙåçq6tÒÓ Q{Õ¾vW!„B!„hJþžK{íHˆ9ªIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/label.rst0000664000000000000000000000603015074673150023116 0ustar00rootroot.. currentmodule:: gi.repository Label ===== Labels are the main method of placing non-editable text in windows, for instance to place a title next to a :class:`Gtk.Entry` widget. You can specify the text in the constructor, or later with the :attr:`Gtk.Label.props.label` property. The width of the label will be adjusted automatically. You can produce multi-line labels by putting line breaks (``\n``) in the label string. Labels can be made selectable with :attr:`Gtk.Label.props.selectable`. Selectable labels allow the user to copy the label contents to the clipboard. Only labels that contain useful-to-copy information — such as error messages — should be made selectable. The label text can be justified using the :attr:`Gtk.Label.props.justify` prop. The widget is also capable of word-wrapping, which can be activated with :attr:`Gtk.Label.props.wrap`. You can configure this wrapping by changing :attr:`Gtk.Label.props.wrap_mode`, in can be :attr:`Pango.WrapMode.WORD`, :attr:`Pango.WrapMode.CHAR` or :attr:`Pango.WrapMode.WORD_CHAR`. :class:`Gtk.Label` support some simple formatting, for instance allowing you to make some text bold, colored, or larger. You can do this by enabling markup setting :attr:`Gtk.Label.props.use_markup` to ``True``, then you can use markup with :attr:`Gtk.Label.props.label` using the Pango Markup syntax [#pango]_. For instance, ``bold text and strikethrough text``. In addition, :class:`Gtk.Label` supports clickable hyperlinks. The markup for links is borrowed from HTML, using the a with href and title attributes. GTK renders links similar to the way they appear in web browsers, with colored, underlined text. The title attribute is displayed as a tooltip on the link. :meth:`Gtk.Label.set_markup` method can be used to set the text and enable markup at the same time. .. code-block:: python label.set_markup("Go to GTK+ website for more") Labels may contain *mnemonics*. Mnemonics are underlined characters in the label, used for keyboard navigation. Mnemonics are created by providing a string with an underscore before the mnemonic character, such as "_File", to the functions :meth:`Gtk.Label.new_with_mnemonic` or :meth:`Gtk.Label.set_text_with_mnemonic`. Mnemonics automatically activate any activatable widget the label is inside, such as a :class:`Gtk.Button`; if the label is not inside the mnemonic's target widget, you have to tell the label about the target using :attr:`Gtk.Label.props.mnemonic_widget`. You can also change the alignment of the label text inside its size allocation. For example if you use :attr:`Gtk.Widget.props.hexpand` in a label, the label may take more space than its inner text. You can change this alignment using :attr:`Gtk.Label.props.xalign` for horizontal alignment and :attr:`Gtk.Label.props.yalign` for vertical. Example ------- .. image:: images/label.png .. literalinclude:: examples/label.py :linenos: .. [#pango] Pango Markup Syntax, https://docs.gtk.org/Pango/pango_markup.html ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/picture.rst0000664000000000000000000000210315074673150023507 0ustar00rootroot.. currentmodule:: gi.repository Picture ======= :class:`Gtk.Picture` displays an image at its natural size. Many convenience functions are provided to make pictures simple to use. For example, if you want to load an image from a file you can use :meth:`Gtk.Picture.new_for_filename`. You can influence how the image is displayed inside the :class:`Gtk.Picture` by changing :attr:`Gtk.Picture.props.content_fit`. See :class:`Gtk.ContentFit` for details. Also :attr:`Gtk.Widget.props.halign` and :attr:`Gtk.Widget.props.valign` can be used to set whether the picture will fill all available space or is displayed at its original size. Sometimes an application will want to avoid depending on external data files, such as image files. See the documentation of :class:`Gio.Resource` inside GIO, for details. In this case, :meth:`Gtk.Picture.new_for_resource` and :meth:`Gtk.Picture.set_resource`, should be used. .. note:: This example requires a GTK version higher o equal to ``4.8``. Example ------- .. image:: images/picture.png .. literalinclude:: examples/picture.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/progressbar.rst0000664000000000000000000000341715074673150024376 0ustar00rootroot.. currentmodule:: gi.repository ProgressBar =========== The :class:`Gtk.ProgressBar` is typically used to display the progress of a long running operation. It provides a visual clue that processing is underway. The :class:`Gtk.ProgressBar` can be used in two different modes: *percentage mode* and *activity mode*. When an application can determine how much work needs to take place (e.g. read a fixed number of bytes from a file) and can monitor its progress, it can use the :class:`Gtk.ProgressBar` in *percentage mode* and the user sees a growing bar indicating the percentage of the work that has been completed. In this mode, the application is required to set :attr:`Gtk.ProgressBar.props.fraction` periodically to update the progress bar, setting a float between 0 and 1 to provide the new percentage value. When an application has no accurate way of knowing the amount of work to do, it can use *activity mode*, which shows activity by a block moving back and forth within the progress area. In this mode, the application is required to call :meth:`Gtk.ProgressBar.pulse` periodically to update the progress bar. You can also choose the step size, with the :attr:`Gtk.ProgressBar.props.pulse_step` property. By default, :class:`Gtk.ProgressBar` is horizontal and left-to-right, but you can change it to a vertical progress bar by changing the value of :attr:`Gtk.ProgressBar.props.orientation `. Changing the direction the progress bar grows can be done using :attr:`Gtk.ProgressBar.props.inverted`. :class:`Gtk.ProgressBar` can also contain text which can be set with :attr:`Gtk.ProgressBar.props.text` and :attr:`Gtk.ProgressBar.props.show_text`. Example ------- .. image:: images/progressbar.png .. literalinclude:: examples/progressbar.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets/spinner.rst0000664000000000000000000000155015074673150023517 0ustar00rootroot.. currentmodule:: gi.repository Spinner ======= The :class:`Gtk.Spinner` displays an icon-size spinning animation. It is often used as an alternative to a :class:`Gtk.ProgressBar` for displaying indefinite activity, instead of actual progress. To start the animation, use :meth:`Gtk.Spinner.start`, to stop it use :meth:`Gtk.Spinner.stop`. Example ------- .. image:: images/spinner.png .. literalinclude:: examples/spinner.py :linenos: Extended example ---------------- An extended example that uses a timeout function to start and stop the spinning animation. The :func:`on_timeout` function is called at regular intervals until it returns ``False``, at which point the timeout is automatically destroyed and the function will not be called again. Example ^^^^^^^ .. image:: images/spinner_ext.png .. literalinclude:: examples/spinner_ext.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/display-widgets.rst0000664000000000000000000000050715074673150022042 0ustar00rootrootDisplay Widgets =============== Learn how to use the most basic elements to display things, like text, images, icons or ongoing progress. .. toctree:: :maxdepth: 1 :caption: Contents display-widgets/label display-widgets/image display-widgets/picture display-widgets/progressbar display-widgets/spinner ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/drag-and-drop.rst0000664000000000000000000000610715074673150021352 0ustar00rootroot.. currentmodule:: gi.repository Drag and Drop ============= .. seealso:: `Drag-and-Drop`_ in the GTK documentation. GTK drag-and-drop works with drag sources and drop targets. These are event controllers that can be set to any widget using :meth:`Gtk.Widget.add_controller`. The data begin moved in the operation is provided through a :class:`Gdk.ContentProvider`. Drag sources ------------ :class:`Gtk.DragSource` is the event controller that allows a widget to be used as a drag source. You can set up everything needed for the drag-and-drop operation ahead of time or do it on the fly using the signals provided by :class:`Gtk.DragSource`. You can use :meth:`Gtk.DragSource.set_content` to set the :class:`Gdk.ContentProvider` that will be sent to drop targets. A content provider is usually created using :meth:`Gdk.ContentProvider.new_for_value` where you only pass the value to send. To pass different values for multiple possible targets you can use :meth:`Gdk.ContentProvider.new_union` were you can pass a list of :class:`Gdk.ContentProviders `. :class:`Gtk.DragSource` provides signals for the different stages of the drag event. The :func:`prepare ` signal is emitted when a drag is about to be initiated, here you should return the :class:`Gdk.ContentProvider` that will be sent, otherwise the one set with :meth:`Gtk.DragSource.set_content` will be used. The :func:`drag-begin ` signal is emitted when the drag is started, here you can do things like changing the icon attached to the cursor when dragging using :meth:`Gtk.DragSource.set_icon`. Also the :func:`drag-end ` signal is provided, you can use it to undo things done in the previous signals. Finally :func:`drag-cancel ` allows you to do things when the operation has been cancelled. Drop targets ------------ :class:`Gtk.DropTarget` is the event controller to receive drag-and-drop operations in a widget. When creating a new drop target with :meth:`Gtk.DropTarget.new` you should provide the data type and :class:`Gdk.DragAction` that your target accepts. If you want to support multiple data types you can pass :attr:`GObject.TYPE_NONE` and then use :meth:`Gtk.DropTarget.set_gtypes` where you can pass a list of types, be aware that the order of the list establish the priorities. :class:`Gtk.DropTarget` provides multiple signals for the process. These are :func:`accept `, :func:`drop `, :func:`enter `, :func:`leave `, and :func:`motion `. Generally connecting to :func:`drop ` is only needed, this signal will receive the value sended by the :class:`Gtk.DragSource`. For more complex use cases checkout :class:`Gtk.DropTargetAsync`. Example ------- .. image:: images/drag_and_drop.png .. literalinclude:: examples/drag_and_drop.py :linenos: .. _Drag-and-Drop: https://docs.gtk.org/gtk4/drag-and-drop.html ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/application.py0000664000000000000000000001237215074673150022675 0ustar00rootrootimport sys import gi gi.require_version("Gtk", "4.0") from gi.repository import GLib, Gio, Gtk # This would typically be its own file MENU_XML = """

Change label
win.change_label String 1 String 1 win.change_label String 2 String 2 win.change_label String 3 String 3
Window
win.maximize Maximize
app.about _About app.quit _Quit <Primary>q
""" class AppWindow(Gtk.ApplicationWindow): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.set_default_size(200, 200) # By default the title bar will be hide, let's show it self.props.show_menubar = True # This will be in the windows group and have the 'win' prefix max_action = Gio.SimpleAction.new_stateful( "maximize", None, GLib.Variant.new_boolean(False) ) max_action.connect("change-state", self.on_maximize_toggle) self.add_action(max_action) # Keep it in sync with the actual state self.connect( "notify::maximized", lambda obj, _pspec: max_action.set_state( GLib.Variant.new_boolean(obj.props.maximized) ), ) lbl_variant = GLib.Variant.new_string("String 1") lbl_action = Gio.SimpleAction.new_stateful( "change_label", lbl_variant.get_type(), lbl_variant ) lbl_action.connect("change-state", self.on_change_label_state) self.add_action(lbl_action) self.label = Gtk.Label(label=lbl_variant.get_string()) self.set_child(self.label) def on_change_label_state(self, action, value): action.set_state(value) self.label.set_text(value.get_string()) def on_maximize_toggle(self, action, value): action.set_state(value) if value.get_boolean(): self.maximize() else: self.unmaximize() class Application(Gtk.Application): def __init__(self, *args, **kwargs): super().__init__( *args, application_id="org.example.App", flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE, **kwargs, ) self.window = None self.add_main_option( "test", ord("t"), GLib.OptionFlags.NONE, GLib.OptionArg.NONE, "Command line test", None, ) def do_startup(self): Gtk.Application.do_startup(self) action = Gio.SimpleAction.new("about", None) action.connect("activate", self.on_about) self.add_action(action) action = Gio.SimpleAction.new("quit", None) action.connect("activate", self.on_quit) self.add_action(action) builder = Gtk.Builder.new_from_string(MENU_XML, -1) self.set_menubar(builder.get_object("menubar")) def do_activate(self): # We only allow a single window and raise any existing ones if not self.window: # Windows are associated with the application # when the last one is closed the application shuts down self.window = AppWindow(application=self, title="Main Window") self.window.present() def do_command_line(self, command_line): options = command_line.get_options_dict() # convert GVariantDict -> GVariant -> dict options = options.end().unpack() if "test" in options: # This is printed on the main instance pass self.activate() return 0 def on_about(self, _action, _param): about_dialog = Gtk.AboutDialog(transient_for=self.window, modal=True) about_dialog.present() def on_quit(self, _action, _param): self.quit() if __name__ == "__main__": app = Application() app.run(sys.argv) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/clipboard.py0000664000000000000000000000514515074673150022331 0ustar00rootrootimport gi gi.require_version("Gdk", "4.0") gi.require_version("Gtk", "4.0") from gi.repository import Gdk, Gtk class ClipboardWindow(Gtk.ApplicationWindow): def __init__(self, *args, **kargs): super().__init__(*args, **kargs, title="Clipboard Example") box = Gtk.Box(spacing=12, orientation=Gtk.Orientation.VERTICAL) self.set_child(box) self.clipboard = Gdk.Display.get_default().get_clipboard() text_box = Gtk.Box(spacing=6, homogeneous=True) box.append(text_box) self.entry = Gtk.Entry(text="Some text you can copy") button_copy_text = Gtk.Button(label="Copy Text") button_copy_text.connect("clicked", self.copy_text) button_paste_text = Gtk.Button(label="Paste Text") button_paste_text.connect("clicked", self.paste_text) text_box.append(self.entry) text_box.append(button_copy_text) text_box.append(button_paste_text) image_box = Gtk.Box(spacing=6) box.append(image_box) self.picture = Gtk.Picture.new_for_filename("../images/application.png") self.picture.props.hexpand = True button_copy_image = Gtk.Button(label="Copy Image", valign=Gtk.Align.CENTER) button_copy_image.connect("clicked", self.copy_image) button_paste_image = Gtk.Button(label="Paste Image", valign=Gtk.Align.CENTER) button_paste_image.connect("clicked", self.paste_image) image_box.append(self.picture) image_box.append(button_copy_image) image_box.append(button_paste_image) def copy_text(self, _button): self.clipboard.set(self.entry.get_text()) def paste_text(self, _button): self.clipboard.read_text_async(None, self.on_paste_text) def on_paste_text(self, _clipboard, result): text = self.clipboard.read_text_finish(result) if text is not None: self.entry.set_text(text) def copy_image(self, _button): texture = self.picture.get_paintable() gbytes = texture.save_to_png_bytes() content = Gdk.ContentProvider.new_for_bytes("image/png", gbytes) self.clipboard.set_content(content) def paste_image(self, _button): self.clipboard.read_texture_async(None, self.on_paste_image) def on_paste_image(self, _clipboard, result): texture = self.clipboard.read_texture_finish(result) if texture is not None: self.picture.set_paintable(texture) def on_activate(app): win = ClipboardWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/drag_and_drop.py0000664000000000000000000000742315074673150023156 0ustar00rootrootimport gi gi.require_version("Gdk", "4.0") gi.require_version("Gtk", "4.0") from gi.repository import Gdk, GObject, Gtk class DragDropWindow(Gtk.ApplicationWindow): def __init__(self, *args, **kargs): super().__init__(*args, **kargs, title="Drag and Drop Example") self.set_default_size(500, 400) views_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) views_box.props.vexpand = True self.set_child(views_box) flow_box = Gtk.FlowBox() views_box.append(flow_box) flow_box.props.selection_mode = Gtk.SelectionMode.NONE flow_box.append(SourceFlowBoxChild("Item 1", "image-missing")) flow_box.append(SourceFlowBoxChild("Item 2", "help-about")) flow_box.append(SourceFlowBoxChild("Item 3", "edit-copy")) views_box.append(Gtk.Separator()) self.target_view = TargetView(vexpand=True) views_box.append(self.target_view) class SourceFlowBoxChild(Gtk.FlowBoxChild): def __init__(self, name, icon_name): super().__init__() self.name = name self.icon_name = icon_name box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) self.set_child(box) icon = Gtk.Image(icon_name=self.icon_name) label = Gtk.Label(label=self.name) box.append(icon) box.append(label) drag_controller = Gtk.DragSource() drag_controller.connect("prepare", self.on_drag_prepare) drag_controller.connect("drag-begin", self.on_drag_begin) self.add_controller(drag_controller) def on_drag_prepare(self, _ctrl, _x, _y): item = Gdk.ContentProvider.new_for_value(self) string = Gdk.ContentProvider.new_for_value(self.name) return Gdk.ContentProvider.new_union([item, string]) def on_drag_begin(self, ctrl, _drag): icon = Gtk.WidgetPaintable.new(self) ctrl.set_icon(icon, 0, 0) class TargetView(Gtk.Box): def __init__(self, **kargs): super().__init__(**kargs) self.stack = Gtk.Stack(hexpand=True) self.append(self.stack) empty_label = Gtk.Label(label="Drag some item, text, or files here.") self.stack.add_named(empty_label, "empty") self.stack.set_visible_child_name("empty") box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, vexpand=True, valign=Gtk.Align.CENTER, ) self.stack.add_named(box, "item") self.icon = Gtk.Image() box.append(self.icon) self.label = Gtk.Label() box.append(self.label) self.text = Gtk.Label() self.stack.add_named(self.text, "other") drop_controller = Gtk.DropTarget.new( type=GObject.TYPE_NONE, actions=Gdk.DragAction.COPY ) drop_controller.set_gtypes([SourceFlowBoxChild, Gdk.FileList, str]) drop_controller.connect("drop", self.on_drop) self.add_controller(drop_controller) def on_drop(self, _ctrl, value, _x, _y): if isinstance(value, SourceFlowBoxChild): self.label.props.label = value.name self.icon.props.icon_name = value.icon_name self.stack.set_visible_child_name("item") elif isinstance(value, Gdk.FileList): files = value.get_files() names = "" for file in files: names += f"Loaded file {file.get_basename()}\n" self.text.props.label = names self.stack.set_visible_child_name("other") elif isinstance(value, str): self.text.props.label = value self.stack.set_visible_child_name("other") def on_activate(app): win = DragDropWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/extended_example.py0000664000000000000000000000116415074673150023702 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class MyWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Hello World") self.button = Gtk.Button(label="Click Here") self.button.connect("clicked", self.on_button_clicked) self.set_child(self.button) def on_button_clicked(self, _widget): self.close() def on_activate(app): # Create window win = MyWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/layout_box.py0000664000000000000000000000157415074673150022561 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class MyWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Hello World") box = Gtk.Box(spacing=6) self.set_child(box) button1 = Gtk.Button(label="Hello") button1.connect("clicked", self.on_button1_clicked) box.append(button1) button2 = Gtk.Button(label="Goodbye") button2.props.hexpand = True button2.connect("clicked", self.on_button2_clicked) box.append(button2) def on_button1_clicked(self, _widget): pass def on_button2_clicked(self, _widget): pass def on_activate(app): # Create window win = MyWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/layout_center.py0000664000000000000000000000135715074673150023250 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class CenterBoxWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, default_width=400, title="CenterBox Example") box = Gtk.CenterBox() self.set_child(box) button1 = Gtk.Button(label="Start") box.set_start_widget(button1) label = Gtk.Label(label="Center") box.set_center_widget(label) button2 = Gtk.Button(label="End") box.set_end_widget(button2) def on_activate(app): # Create window win = CenterBoxWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/layout_flowbox.py0000664000000000000000000000633115074673150023445 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk, Gdk class FlowBoxWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="FlowBox Demo") self.set_default_size(300, 250) header = Gtk.HeaderBar() self.set_titlebar(header) scrolled = Gtk.ScrolledWindow() scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.set_child(scrolled) flowbox = Gtk.FlowBox() flowbox.props.valign = Gtk.Align.START flowbox.props.max_children_per_line = 30 flowbox.props.selection_mode = Gtk.SelectionMode.NONE scrolled.set_child(flowbox) self.create_flowbox(flowbox) def draw_button_color(self, area, cr, width, height, rgba): context = area.get_style_context() Gtk.render_background(context, cr, 0, 0, width, height) cr.set_source_rgba(rgba.red, rgba.green, rgba.blue, rgba.alpha) cr.rectangle(0, 0, width, height) cr.fill() def color_swatch_new(self, str_color): rgba = Gdk.RGBA() rgba.parse(str_color) button = Gtk.Button() area = Gtk.DrawingArea() area.set_size_request(24, 24) area.set_draw_func(self.draw_button_color, rgba) button.set_child(area) return button def create_flowbox(self, flowbox): colors = [ "AliceBlue", "AntiqueWhite", "AntiqueWhite1", "AntiqueWhite2", "AntiqueWhite3", "AntiqueWhite4", "aqua", "aquamarine", "aquamarine1", "aquamarine2", "aquamarine3", "aquamarine4", "azure", "azure1", "azure2", "azure3", "azure4", "beige", "bisque", "bisque1", "bisque2", "bisque3", "bisque4", "black", "BlanchedAlmond", "blue", "blue1", "blue2", "blue3", "blue4", "BlueViolet", "brown", "brown1", "brown2", "brown3", "brown4", "burlywood", "burlywood1", "burlywood2", "burlywood3", "burlywood4", "CadetBlue", "CadetBlue1", "CadetBlue2", "CadetBlue3", "CadetBlue4", "chartreuse", "chartreuse1", "chartreuse2", "chartreuse3", "chartreuse4", "chocolate", "chocolate1", "chocolate2", "chocolate3", "chocolate4", "coral", "coral1", "coral2", "coral3", "coral4", ] for color in colors: button = self.color_swatch_new(color) button.props.tooltip_text = color flowbox.append(button) def on_activate(app): # Create window win = FlowBoxWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/layout_grid.py0000664000000000000000000000212415074673150022706 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class GridWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Grid Example") button1 = Gtk.Button(label="Button 1") button2 = Gtk.Button(label="Button 2") button3 = Gtk.Button(label="Button 3") button4 = Gtk.Button(label="Button 4") button5 = Gtk.Button(label="Button 5") button6 = Gtk.Button(label="Button 6") grid = Gtk.Grid() grid.attach(button1, 0, 0, 1, 1) grid.attach(button2, 1, 0, 2, 1) grid.attach_next_to(button3, button1, Gtk.PositionType.BOTTOM, 1, 2) grid.attach_next_to(button4, button3, Gtk.PositionType.RIGHT, 2, 1) grid.attach(button5, 1, 2, 1, 1) grid.attach_next_to(button6, button5, Gtk.PositionType.RIGHT, 1, 1) self.set_child(grid) def on_activate(app): # Create window win = GridWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/layout_headerbar.py0000664000000000000000000000131415074673150023676 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class HeaderBarWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, default_width=400, title="HeaderBar Example") header_bar = Gtk.HeaderBar() self.set_titlebar(header_bar) button = Gtk.Button(label="Button") header_bar.pack_start(button) icon_button = Gtk.Button(icon_name="open-menu-symbolic") header_bar.pack_end(icon_button) def on_activate(app): # Create window win = HeaderBarWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/layout_listbox.py0000664000000000000000000000623115074673150023450 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class ListBoxRowWithData(Gtk.ListBoxRow): def __init__(self, data): super().__init__() self.data = data self.set_child(Gtk.Label(label=data)) class ListBoxWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, default_width=400, title="ListBox Demo") # Main box of out window box_outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=24) box_outer.props.margin_start = 24 box_outer.props.margin_end = 24 box_outer.props.margin_top = 24 box_outer.props.margin_bottom = 24 self.set_child(box_outer) # Let's create our first ListBox listbox = Gtk.ListBox() listbox.props.selection_mode = Gtk.SelectionMode.NONE listbox.props.show_separators = True box_outer.append(listbox) # Let's create our first ListBoxRow row = Gtk.ListBoxRow() hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=24) row.set_child(hbox) # We set the Box as the ListBoxRow child vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) hbox.append(vbox) label1 = Gtk.Label(label="Automatic Date & Time", xalign=0) label2 = Gtk.Label(label="Requires internet access", xalign=0) vbox.append(label1) vbox.append(label2) switch = Gtk.Switch() switch.props.hexpand = True # Lets make the Switch expand to the window width switch.props.halign = Gtk.Align.END # Horizontally aligned to the end switch.props.valign = Gtk.Align.CENTER # Vertically aligned to the center hbox.append(switch) listbox.append(row) # Add the row to the list # Our second row. We will omit the ListBoxRow and directly append a Box hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=24) label = Gtk.Label(label="Enable Automatic Update", xalign=0) check = Gtk.CheckButton() check.props.hexpand = True check.props.halign = Gtk.Align.END hbox.append(label) hbox.append(check) listbox.append(hbox) # Add the second row to the list # Let's create a second ListBox listbox_2 = Gtk.ListBox() box_outer.append(listbox_2) items = ["This", "is", "a", "sorted", "ListBox", "Fail"] # Populate the list for item in items: listbox_2.append(ListBoxRowWithData(item)) # Set sorting and filter functions listbox_2.set_sort_func(self.sort_func) listbox_2.set_filter_func(self.filter_func) # Connect to "row-activated" signal listbox_2.connect("row-activated", self.on_row_activated) def sort_func(self, row_1, row_2): return row_1.data.lower() > row_2.data.lower() def filter_func(self, row): return row.data != "Fail" def on_row_activated(self, _listbox, row): pass def on_activate(app): # Create window win = ListBoxWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/layout_notebook.py0000664000000000000000000000145715074673150023611 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class NotebookWindow(Gtk.Window): def __init__(self, **kargs): super().__init__(**kargs, title="Simple Notebook Example") notebook = Gtk.Notebook() self.set_child(notebook) page1 = Gtk.Box() page1.append(Gtk.Label(label="Default Page!")) notebook.append_page(page1, Gtk.Label(label="Plain Title")) page2 = Gtk.Box() page2.append(Gtk.Label(label="A page with an image for a Title.")) notebook.append_page(page2, Gtk.Image(icon_name="help-about")) def on_activate(app): # Create window win = NotebookWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/layout_stack.py0000664000000000000000000000261315074673150023071 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk, GObject class StackWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Stack Demo") self.set_default_size(300, 250) header = Gtk.HeaderBar() self.set_titlebar(header) stack = Gtk.Stack() stack.props.transition_type = Gtk.StackTransitionType.SLIDE_LEFT_RIGHT stack.props.transition_duration = 1000 self.set_child(stack) checkbutton = Gtk.CheckButton(label="Click me!") checkbutton.props.hexpand = True checkbutton.props.halign = Gtk.Align.CENTER page1 = stack.add_titled(checkbutton, "check", "Check Button") checkbutton.bind_property( "active", page1, "needs-attention", GObject.BindingFlags.DEFAULT ) label = Gtk.Label() label.set_markup("A fancy label") stack.add_titled(label, "label", "A label") stack_switcher = Gtk.StackSwitcher() stack_switcher.set_stack(stack) header.set_title_widget(stack_switcher) # Let's start in the second page stack.set_visible_child_name("label") def on_activate(app): # Create window win = StackWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/popover.py0000664000000000000000000000237415074673150022065 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk class PopoverWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="Popover Demo") self.set_default_size(300, 200) box = Gtk.Box(spacing=6, orientation=Gtk.Orientation.VERTICAL) box.props.halign = box.props.valign = Gtk.Align.CENTER self.set_child(box) popover = Gtk.Popover() popover_box = Gtk.Box() popover_box.append(Gtk.Label(label="Item")) popover.set_child(popover_box) button = Gtk.MenuButton(label="Click Me", popover=popover) box.append(button) button2 = Gtk.Button(label="Click Me 2") button2.connect("clicked", self.on_button_clicked) box.append(button2) self.popover2 = Gtk.Popover() self.popover2.set_child(Gtk.Label(label="Another Popup!")) self.popover2.set_parent(button2) self.popover2.props.position = Gtk.PositionType.LEFT def on_button_clicked(self, _button): self.popover2.popup() def on_activate(app): win = PopoverWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/popover_menu.py0000664000000000000000000000403515074673150023105 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gio, Gtk # This would typically be its own file MENU_XML = """
About app.about Quit app.quit
""" class AppWindow(Gtk.ApplicationWindow): def __init__(self, **kwargs): super().__init__(**kwargs) self.set_default_size(300, 200) headerbar = Gtk.HeaderBar() self.set_titlebar(headerbar) builder = Gtk.Builder.new_from_string(MENU_XML, -1) menu_model = builder.get_object("app-menu") button = Gtk.MenuButton(menu_model=menu_model) headerbar.pack_end(button) class Application(Gtk.Application): def __init__(self, **kwargs): super().__init__(application_id="com.example.App", **kwargs) self.window = None def do_startup(self): Gtk.Application.do_startup(self) action = Gio.SimpleAction(name="about") action.connect("activate", self.on_about) self.add_action(action) action = Gio.SimpleAction(name="quit") action.connect("activate", self.on_quit) self.add_action(action) def do_activate(self): # We only allow a single window and raise any existing ones if not self.window: # Windows are associated with the application # when the last one is closed the application shuts down self.window = AppWindow(application=self, title="Main Window") self.window.present() def on_about(self, action, param): about_dialog = Gtk.AboutDialog(transient_for=self.window, modal=True) about_dialog.present() def on_quit(self, action, param): self.quit() app = Application() app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/simple_example.py0000664000000000000000000000053015074673150023367 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk def on_activate(app): # Create window win = Gtk.ApplicationWindow(application=app) win.present() # Create a new application app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) # Run the application app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/examples/textview.py0000664000000000000000000001656415074673150022260 0ustar00rootrootimport gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk, Pango class SearchDialog(Gtk.Window): def __init__(self, parent): super().__init__(title="Search", transient_for=parent) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) self.set_child(box) label = Gtk.Label(label="Insert text you want to search for:") box.append(label) self.entry = Gtk.Entry() box.append(self.entry) self.button = Gtk.Button(label="Find") box.append(self.button) class TextViewWindow(Gtk.ApplicationWindow): def __init__(self, **kargs): super().__init__(**kargs, title="TextView Demo") self.set_default_size(500, 400) self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) self.set_child(self.box) self.create_textview() self.create_toolbar() self.create_buttons() def create_toolbar(self): toolbar = Gtk.Box(spacing=6) toolbar.props.margin_top = 6 toolbar.props.margin_start = 6 toolbar.props.margin_end = 6 self.box.prepend(toolbar) button_bold = Gtk.Button(icon_name="format-text-bold-symbolic") toolbar.append(button_bold) button_italic = Gtk.Button(icon_name="format-text-italic-symbolic") toolbar.append(button_italic) button_underline = Gtk.Button(icon_name="format-text-underline-symbolic") toolbar.append(button_underline) button_bold.connect("clicked", self.on_button_clicked, self.tag_bold) button_italic.connect("clicked", self.on_button_clicked, self.tag_italic) button_underline.connect("clicked", self.on_button_clicked, self.tag_underline) toolbar.append(Gtk.Separator()) justifyleft = Gtk.ToggleButton(icon_name="format-justify-left-symbolic") toolbar.append(justifyleft) justifycenter = Gtk.ToggleButton(icon_name="format-justify-center-symbolic") justifycenter.set_group(justifyleft) toolbar.append(justifycenter) justifyright = Gtk.ToggleButton(icon_name="format-justify-right-symbolic") justifyright.set_group(justifyleft) toolbar.append(justifyright) justifyfill = Gtk.ToggleButton(icon_name="format-justify-fill-symbolic") justifyfill.set_group(justifyleft) toolbar.append(justifyfill) justifyleft.connect("toggled", self.on_justify_toggled, Gtk.Justification.LEFT) justifycenter.connect( "toggled", self.on_justify_toggled, Gtk.Justification.CENTER ) justifyright.connect( "toggled", self.on_justify_toggled, Gtk.Justification.RIGHT ) justifyfill.connect("toggled", self.on_justify_toggled, Gtk.Justification.FILL) toolbar.append(Gtk.Separator()) button_clear = Gtk.Button(icon_name="edit-clear-symbolic") button_clear.connect("clicked", self.on_clear_clicked) toolbar.append(button_clear) toolbar.append(Gtk.Separator()) button_search = Gtk.Button(icon_name="system-search-symbolic") button_search.connect("clicked", self.on_search_clicked) toolbar.append(button_search) def create_textview(self): scrolledwindow = Gtk.ScrolledWindow() scrolledwindow.props.hexpand = True scrolledwindow.props.vexpand = True self.box.append(scrolledwindow) self.textview = Gtk.TextView() self.textbuffer = self.textview.get_buffer() self.textbuffer.set_text( "This is some text inside of a Gtk.TextView. " + 'Select text and click one of the buttons "bold", "italic", ' + 'or "underline" to modify the text accordingly.' ) scrolledwindow.set_child(self.textview) self.tag_bold = self.textbuffer.create_tag("bold", weight=Pango.Weight.BOLD) self.tag_italic = self.textbuffer.create_tag("italic", style=Pango.Style.ITALIC) self.tag_underline = self.textbuffer.create_tag( "underline", underline=Pango.Underline.SINGLE ) self.tag_found = self.textbuffer.create_tag("found", background="yellow") def create_buttons(self): grid = Gtk.Grid() self.box.append(grid) check_editable = Gtk.CheckButton(label="Editable") check_editable.props.active = True check_editable.connect("toggled", self.on_editable_toggled) grid.attach(check_editable, 0, 0, 1, 1) check_cursor = Gtk.CheckButton(label="Cursor Visible") check_cursor.props.active = True check_editable.connect("toggled", self.on_cursor_toggled) grid.attach_next_to(check_cursor, check_editable, Gtk.PositionType.RIGHT, 1, 1) radio_wrapnone = Gtk.CheckButton(label="No Wrapping") radio_wrapnone.props.active = True grid.attach(radio_wrapnone, 0, 1, 1, 1) radio_wrapchar = Gtk.CheckButton(label="Character Wrapping") radio_wrapchar.set_group(radio_wrapnone) grid.attach_next_to( radio_wrapchar, radio_wrapnone, Gtk.PositionType.RIGHT, 1, 1 ) radio_wrapword = Gtk.CheckButton(label="Word Wrapping") radio_wrapword.set_group(radio_wrapnone) grid.attach_next_to( radio_wrapword, radio_wrapchar, Gtk.PositionType.RIGHT, 1, 1 ) radio_wrapnone.connect("toggled", self.on_wrap_toggled, Gtk.WrapMode.NONE) radio_wrapchar.connect("toggled", self.on_wrap_toggled, Gtk.WrapMode.CHAR) radio_wrapword.connect("toggled", self.on_wrap_toggled, Gtk.WrapMode.WORD) def on_button_clicked(self, _widget, tag): bounds = self.textbuffer.get_selection_bounds() if len(bounds) != 0: start, end = bounds self.textbuffer.apply_tag(tag, start, end) def on_clear_clicked(self, _widget): start = self.textbuffer.get_start_iter() end = self.textbuffer.get_end_iter() self.textbuffer.remove_all_tags(start, end) def on_editable_toggled(self, widget): self.textview.props.editable = widget.props.active def on_cursor_toggled(self, widget): self.textview.props.cursor_visible = widget.props.active def on_wrap_toggled(self, _widget, mode): self.textview.props.wrap_mode = mode def on_justify_toggled(self, _widget, justification): self.textview.props.justification = justification def on_search_clicked(self, _widget): self.search_dialog = SearchDialog(self) self.search_dialog.button.connect("clicked", self.on_find_clicked) self.search_dialog.present() def on_find_clicked(self, _button): cursor_mark = self.textbuffer.get_insert() start = self.textbuffer.get_iter_at_mark(cursor_mark) if start.get_offset() == self.textbuffer.get_char_count(): start = self.textbuffer.get_start_iter() self.search_and_mark(self.search_dialog.entry.get_text(), start) def search_and_mark(self, text, start): end = self.textbuffer.get_end_iter() match = start.forward_search(text, 0, end) if match is not None: match_start, match_end = match self.textbuffer.apply_tag(self.tag_found, match_start, match_end) self.search_and_mark(text, match_end) def on_activate(app): win = TextViewWindow(application=app) win.present() app = Gtk.Application(application_id="com.example.App") app.connect("activate", on_activate) app.run(None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/application.png0000664000000000000000000002103015074673150022447 0ustar00rootroot‰PNG  IHDRäåC [(sBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timejue 08 dic 2022 22:08:02ëúi IDATxœíÝw|Õþÿñ×nØt’Ð’Pi@ EDëEc¹*ÈOëõz-¨\½(¢¨ØîW¯Š *‚HïÅFM„FB(Ò@ ¤³ûûc ›dÓàóä1dgÎÌ9;ä=çÌlB!„B!„WÕU²M!”J×–k‹ðÔ· ¦¸–ÕÄV´¥¡©½žª‰Ë„¸ÚÕœ®‰Ëš¤¹a±ik=®]¾QM ‹¥ƒhi’PŠk‘¥0jë™j‡Õ|ýzuhB#êë­Ì~Z®@gÀ °1l[)®%æÁª*€bà4p¸h˜´f?Í×UÑH( dí0{@c;Ž€Ï²¥K&… … t@qP¡Óiuçöî‹_<)*j9p¸€>¬*.…ÒÌFCÙXpjQ̓¨\CBBB]òóÿ©T8·ø‰ q•ÓAá]&NOLLŒÎUèƒiì5- aëh(æ½£±gì`˜¬§aÆE®Xúów:]“†¾B\ÓT¨ªoŸpÏ£IIIÑ@ P‰>”ÕÔ<·„zBÙX -õŒÖèÏŽM_Ò3 q‰ê\oo߀$ôç˜ÆPZê)ëP×·ÕZ¿CiªvùyщH…¨EçòÓÂïïFSƒ>3VÔ|Õêé {Û›ùPUƒ¾g´úgMÿE.­n¿×V{¶ï€ûC@úžÒxNYû"O ûYº²j ¦‹J¥ëÔ¶o«âÚ R«]ÐwVj^ÜQÓȕ֦¾Y;öhå¥ !,Ó©{jYo˜iPSzÈÚìXKç(Dƒ¬¹”ó@§f]Ô1ªoØjÕ&MâÚež•Úo)­—¥ÒÒǧj‡RÝÆŸËâZcþöÒúÂX§§lÊ[ç,½‘ÜJò(DƒÌÃhé5ô:¤¥×"Í7~ÍØüûŸ,Y¾’ââb‹ËϰdùJþÚµ»IÛ+**æ½yŸñÛ_ۛݖ˜½ûX²|%I)©5æ9–ÁÚM[Ø»¯Æü²òr–,_É–?þàëïàë…?6»^s·þÎ’å+[µ Q'/–òTGK?í¡º–:È[ÿ ãÄ *+«xøûê,_¾f=¶üÆÀFGF4º½´#G‰Þ»3gÏ1ö†QÍjË™‚s,^¶’ða 4Ð4ÕúìØƒ££=aÆ Vë¥)i‡X¼l%ãoËù ØøÛü=jv¶¶ÍªÛhÃÖß9™™EÔÄ»[´¾ZøÙàæ|Ú£Ö¼k)’úç²aËoL¸ë6::8˜–×êéÞCóÌSñéÛ§IåÍ -=Ý´®N§#1å çÏ—räXý|úú@ùÂÁÁž/>‡Z¥ÆÎÖ¦Ùu×u-ý[6áG8 3^x'''ŠÏŸgîÇŸ“|0U‹¶fóõ}ÃF½»ÊÚ”Š®eåå¬Ý°¹Æ¼µ›¶PYYY§ì¹ÂB¶íÚÍŠµø}ûΙ–•œ?Ï™³gÉÎÍ5•]²|§ÏpôØqÖlܶ]»©®®®³ÝîîtéìFaQ1y§Np23›¢¢b¼zyŸ˜d*0õjµ¿¦²'³³MË—¯^GJÚ!NŸ)`óï±iëïÕškµZbãâYµn#“Ñéê±äÂvÅìaõºÄÅ'¢ÕêßlrüD&K–¯bgôSÙ£'X½ncawrjK–¯"+'§Î¶¯¤žž=HMKgæì÷)..¦¤¤„7ßyŸäƒixzx´fÓ-ÊHs?¥q©’kðàéÕÓ“u›¶2á¶ñØÛÛSV^ÎÆ­¿èO|‚!:È?}šé/¼lú£°µµá?3^¡¿¯7g Y²l%a!D†…šïØc )ÀÖ?¶ñÎ3ê´#È0[ÿÜFZÚºwéJB²¾w|ô(Þž;ø„d¢îþ•••9–¯wìíA¿®ZƒFcÍÝ·ßèwtt¤¸¤„Š ýeñòU|öÞlœ¨¨¨äÍ9sIK?\w‡þÓÒÓyïãÏky€¯oÍx;;[–,[‰{÷nŒ`ý¦-ü±}'~úáï÷:ë6neϾ8ÆÝ8FQ;o½ú/Þxg'Nf1ó÷Q©T?™I×Îù÷«/¶E[›Ì–öפ‰wÝAii)ë6oôç–¥¥eL¸ýÖåºuéÂô©“yï?3ùßÇs™4á.ÊË+XºjuƒÛ¯ªªbæË/òÆ¿^ÀÕ¥ÉÓ8|ôhrAþƒHMO 1%'''‚üéÛ»éGŽPZZJú‘cTWW›Ê×ç\aÿï‘¿3çÍ×ñТ¢b~ß¾€u›·’–~˜¡A|þÁ^xzÖÖÖ¦u«««ùäËù\(-ã¥çžâ³÷g3Øoi‡°bízºué‚WOOróò)26!ù *•Š´ô#”•—pðP:Þ}úàÒIYŸGpsuå7fàÞ½+'2³8~2“.ݘõÆ+tíÜù²·§ÅÔ]CÿŒ†‡ ý{7ÖnÜBñùÖnÜDèÐ`<{¸×yÎ7…ƒƒ©é‡±µ±F¥R‘“›[k›5ëðñîÍ † dxÈ0ròòë´ÇßßµZMZúa.j/’r0ÀÁ~ ‚!AhµZ$%- €@ÿÁuž‹ùc;;;n3Šý}¹cü-äêOÒ÷üwßu;ž=Ü9œîݺš¶qôø òòó JDx(={ö`Ú”G8”„¡Ã†zø0Y¹9œ=Ë£"õíL>ÈÉ슋‹ xÅÿ¯-ý³²ê€µæÒAHÓAƒF£iÕ6[JzH3jµš»ï¼’óçykΜ+,b·Ö)WUUÅ»~ʳÿzßþÜΩ‚T*«µ¶j™³¡§¸xñbeðéÛ›Ìì$%SV^Nà`ýÅž¡AÄ'&“’z;[[Óž¦p餿pQm¨·  Ÿ>},–Ï7œÇvér©·pïÞ •Je:o @Ú¡t“booσ÷Ý‹Z­æ@R2©† OƒšÜÎËå\a‘~Èš™…§‡žääåñæì¹5® \.-¤¥/Á»Z'³ç4fD$®..Ë8߀~ ðõ­ó]c ‰)ìÝÏ­7å™3xrÊ£t°²ºT¦ö>ªoŸ5°ýýÑjµüºb-ƒü@¾}ûÒÑÑ‘ýI?r”Á~±R[Õ_—¥ºÍæurÖN:m±mΆ+99y¦eG@§Óé{Rx{õÆÕÅ…Ôô#$$$p°®:ÑÏLJøÄ$RÒáÒ©}¼z]ùÿëZÓÛsç‘•ƒ§‡³Þx…Yo¼‚§‡Y99¼ýþG­ÿ›j&é!kéСQÿF¯^Üû·;-–)-+ 3'‡²²2’¦šzœ¶l8/L;|÷nÝèÒÙ Ð÷âCü9}¦€òŠ ‚ =gK 6\ÿÃ"²rrˆ‹çÔéÓ¦åÞ½{ãè`OlÜ~þܾ“ܼS¬X»€pð[¥R:4˜£ÇINMeH ¾L^þ)öÆÅ„J¥¼‹óÇOÐÇ«³Þxgg\œ™õÆ+ôñêEƉ“—½=­ø.œVKx»eÌhn3ºÆ<ó2Áƒprr"ù`*=þjµšŽê-_÷1õÌ»¤¿o_ììì(++#ÐP2C‚ض;€?‹ë×g鱎»nGÌÞ8SòìK¯aee…‡{w2³²v<ùØ#|öÕw|öÕ|ÓÚ‘a¡Œ{ƒi»¡CƒÙôÛTWW0Ð24…‹¡¬¼œ¡Cëi畵rÑ÷fôísqvbÞ»ÿ©1ïriq •·k[nÜØ1œ+*•Êâó²µ³#jâºwïŠpìØ‘ß›ELl:Ž@?Μ>Kfn:ÀÅ¥Q'㇇ÅÇ~ú5q^½{Y¬S¥V3õ‘9}¦€à e‚ƒˆš8VVôðp¯±ì޿݉Z­6Í«ýØÍͨ‰è㥯×ÁÁž¹³fw€ââbû¡¶R³3:Ö´NDx>Þ}I:˜FyY9Þ}{3 Ÿ/péï`°ß¢&NÀÞÖWWt€‡»;·êêjæ/XHIÉùoÃÜڛضcGùI))¬\½¦Îüòòræ/XÈùóçIJI!zÏž:ešcÍú MÞw׫v䱌 &?1¿ý{öÅq )‰>þŒ·Þ™ @ff&‹—þÚÞÍh3«Ö¬·|c Zûܪªª˜ÿýBŠê¹‘lsËÈàëïÔ™?ÿ»¼?ùf„ä~]± ~Z¼”/¿ù®Uõ¯Y¿¡ÉûîzÕŠÏC6îÌ™ú9¦=6…Iï®ñE¹–¾B_´¯ðÐP–,]FQq±éÉËËËIHNÁ×Û›ÑÑx÷½tK¸ýñ„… E¥R1kækoŸ'ÚV»ò¿_~Å£Frß½÷ÔYfeüê}ƒS§O³;fU•UDF„ãáînZvüäI“(>_oo ߘ °g_n..TWW“”Œ½½7޹;»Û‹ãÈ‘£ôðð oŸ¾Ë8Êè‘#MËOŸ9CÌÞ}TVTB&Þ°°°˜}û8}ú ݺteô¨ؘÝ= ãÄIb÷îÃÉ©#áa¦0´¶îæ ðÇÚÚš„Ä$Fˆ`üúùx3fôhþܶGzÐT~ßþx&N¸ €IÉ”—•šöÙêuë{à $¥¤pìø <=<5"²ÆA·¢¢‚Ý1±äæå2ØÏÏb›2³rˆ‹ßJ¡Ã†áÞ½;›¶nÅɱ#ÃÃMe—­\M?_̾­}ÁO‹¸cüx:¾Ùýj×®CÖ»vq§á>… 9WXÈ3/¼HZúavFGóàä©ËП’SòÏ—gŸHbR2¯Î|“÷>¼ô•°±±{yöÅñÁ'Ÿ’™•Éâ¥Ëxìñ'©¨¨0•ù÷Ûï0gîGœÌÊæÇÅK˜üÄ4þܶӴ|ÿ›ö©iiJ?Ì£?Il\\£í®ªªbòÓÙ¶}ÇŽeðéÿ}ÁcӦ׸ÁkÁÙ³¼úúL2Nœà—eËyhÊÔ_QßÒº[ÂÆÚšàÀ@âLó¢ccÆÈÈ’¦RXXÀ…ÒR¥§6Lð‹Ý[cŸ­Z³ž¨‡'³|ÕZ²srxï£yÌz÷=Óò¢¢"¦NšŸ–,ádV6ÿy÷=ÓMwŒ6lÞÂãO?CÊÁTþÚ¾‹'Oewt Ù9¹|ûæ²¹yy|øÉ§,øñ'Ó¼™™,øqNNÛp/]YíÖCæŸ:Å…²2zõôl´¬½ßó•©W›:ýi–­ZÍË/üƒA~Y±d‘©ìîè^œñ:Ï?=;Cy¿ùhŽþœôBi)ãﺛ»£;æ¶íØI\|¿üð=ŽŽŽèt:^{ó-Óö´Z-s>ø€Ç§<Ê]wÜÀ ¿|ùõ·„~5´Ávk4V,Y„Z­?®—”pÇ=“Ø·?žÃÍKíííøîë/q°·G«ÕòÒë3ùïÿ¾â£9³[UwK…‡†°qËÓã˜ØXf¿õ&ž=<ðêÙ“Ý{b¹mÜ-8@o¯^ ö<ÞEÝÀ¨ÈþñÒ«<÷Ôt\\:±à§EtíÒ…çÌF­Vs¡¬Œ¿OžjZ÷ܹB>úä3>ýp.ƒé{ϯ ç²ËÿĨȾ]ðÊÊp°³#fO,aÆ€ŠŠ lllØ·ŸaC†Ô¸ŸåÕ®ÝzÈrCe¼1MClllj 1‡‡†’››`•••qøèQ¬¬¬Ðétœ:sÆT¾£ƒ£éw{{üù‘“—@ôžXn¾ñMÛëéÙÓT>'7̬ÊË+X¿i3ë7mæì¹BNœ<Þ¤ç©V«Ñjµdœ8ɱcÇñèÞS†[¸ØÙÚéïnl(ûPÔ}Äío“º["<,„ÃGŽráÂ2³r(-«À×Ç€Q#"Ù­¿gȾ ip[/í÷¡ÁÁh4róôwˆÞÄ;ï0¬ììpss5•‹ÇÃÃÃF€‡ˆâÔéÓdfgãëãC×.]HHH :v/÷ßw/îîÄÅ`oÜ~F kí.Q”v ¤§‡:t0 =›ÃÞÞÎtŸûÊÊJÞ™3—)OLç—¥ËÙ·¿ÑõíìíMëçåŸÂÕÕµÞ²%çKý°97/ܼ<.^¼Èä‡nR[ÿò+Q?Â7ß}Ƕ];Mw ®OwÊË˹PZÚêº[¢w¯^ú?ôÄ$bbc‰ 3ôFFF³g/ÕÕÕì‹‹'4´á@šÓh4h4V¦Ï­çŸ:[û=7?WW—óììèÔÉ™‚‚³Œˆ'n<ÕÕÕ$§dHp0cFdwL Z­–¸øxÂÃB›¹”­Ý†¬VVVø³hÉRFDD´x;6mæHÆ1~üî4 Z­–Ÿ–üÒäõ;»º’›—_ïrãÅ£Q##Ø¿³Úv"3“/çËŠÅ‹LC»ƒ©© ®söÜ9p°·oUÝ­Âþ ;~œ»ÌÎñýÀÆÆ†m;v’™•EP€‹ëpuq!7/A†ÛÝYZž—›Wc^uu5%%çñp×_ØÉ—ßÌ'19…Áƒü°±¶fôȼ:óMn¿u<]»t¡{·n-n£µëEž}†Ää>úìsªªªj,Ój›v·áÓg P©Ôh4@‘¤9† fËo¿sæLi޳᮳“Aþ,üégS¯Ú • ­á%ã6­môç0UUU×|ÿBi)çΚ¯\½–‘Ç7©ncÏuQÛ¶/  aÏÞ}$$%bvÅZ­V3"b8_~3ŸÀÿ:W‹›cXpKW¬4½TRYYIQÑ¥;ø“•“Ãî˜Ko6X·a#½½z™®´ $+;‡-¿ýÎÃÕÖþý|Ñét,[±ŠÈðp®5íú²‡wß>Ì›û³ß›Ë_Ûv0xÐ@4 ©i‡ð4ˆ¿öj£Û5"’?-â©ç_ WÏžÄÅÇ7ëeÜMcÙ´y “§=Éè#ÈÊÉ!99…‘‘‘¦2/ýãüó•<ùÜó„ J~þ)\:uâ©i×Ù^PÀ`V¬Y‡µ cFÄÕÅ…'žz–¡C‚IHJâl­FuUS¦M'bxY™Ùäæçòù¼šT·­­-ý|}ùß7ó™tÏ= lòónHÈÐ!¼þÖ,‚ê¼<422‚5ë70q„VÕ1uÊ£Lî¦<1  “’)9Á´¼‡‡Ó¦NaÆ¿ßâ¦17p±ú"{ãã™ûÎ,ÓH£Ñ2”õ›6óø”GMëŽɲ«øâ“[ÕF%²²0OEÍ[ÒYqé¶t6†Éóõ×_×” <=<˜pçø ˆµÆšî]»qûm㉚xþ„_¥ÂÙÉ ³“{TЭ[W|úö¥³›7Þ0+•š=FDDàÞ½»~«R1$8ˆÛÆßByY9C‚ƒxöé§píÔÉ´½ÆêAEeÝ»u¥k—.MÙå²¶¶¦“³3£G ‡Ùë½Ýºv¡ƒ¦ãnkº¦ß©5÷³Jû÷ÃÍÍ­F™ Àìíqttäöñãpî䌭µ ÝÃÃBéáánZ'0ÀŸˆ°0ª««éë݇ç¦?I¯^=Í›C÷®ÝèíåEȰKW»wïF'ggÆÝ<ÖtÑHif¿ûîf ¨4Læ·¡3ÞŠ®Žß²ôÂù«öþoüçmú÷óåáî¿ÒM×({ÇÝR™‡—6f~¾Z\Rž½{1ü ¶HËÚõR){ò)zõôÄÍÍ»v3éž{èc6ÄB)®Ë!«íM†¬B\$B(H‹Ï!óòò/$„h–²»áÝBˆ¶#CV!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA:\é\Oòòò‰;p€‚³gquu!È?ÏÍÞÎoü‰·w_úxyµC+õróòøkÛˆšÔnuˆº¤‡¼L–üºœ‡û슎&7/Ÿ¿¶íä±iÓ)**`wÌ6lÞÒ¤mÍ÷ kÖ­o—v^(-勯¾!êáÉ,Xôs»Ô!ê'=äe—ŸÏg_|ÉÂù_áëímš¯ÕjQ«õÇÄ䔃dfgqÛ¸[ÝÞ¯?ÿˆƒ½}›·óÈÑc<ûâ¿È‹Ï?Ã_Ûæuˆ†I /ƒcÇÑh4ôíÝ»Æ|c“’‰OH ¨¸„ù â׿?ÃÃÉÌÊ&5ía¡Ãؾk7¬¬¸õ–›ùkûvöïO?__2³²9~âý|}ˆ‰¥²¢ŠÈˆp<ÜÝkÔuôXûã`ç`ÇèȬߴ™û'M¬Q¦gOO>ûè|½½ILJn×}",“!ëeÐÛ«UUUÌÿ~!••u ¨T¨T*T*°²²B¥V™™Éß|ÃãO=Ão¿ýΉ'Xµf=ié‡MeÞš=‡çþù©‡³3:š'OåXF†ióËW­fڳϓ~ø0Ûwìbâñó/Kë4ÃÆÚºF..?é!/wwf¼ô"ÿýß×,]±’›oCÔ¤{éãÕ €€Áƒ  3;‹)ÿ½ÆºçΞã‹O?fßÀz·¯ÑhøáÛ¯±±±`êô§Y¶j5/¿ð øü˯øï¼<È€_—¯äÇÅKÚéÙŠÖò2¹ó¶[Y½t1ON}Œ¤”|t 3g½Muuuƒë9;;7FkÆF€á¡¡äææŸ@OOOSzõôlÅ3íIyÙÚÚ2iâÝ,úþ[>ž;‡í;v±~Ó¦6¯ÇÞÞN@Þ©|Ü\]Û¼Ñ>$WHxh(Aþ7œ¶7WWòòòÚµÑv$—Á…²2 kÌ+.)áHÆqú÷ó@c­!ÿÔé6¯;80€ÌìlvÇì1Í;UPÐæõˆ¶!u.ƒ½{÷ñï·g3 Ÿ/ž=zpñâEböîcØ`n;€ðaÌÿ~!³ßÿoo¢î½§Mêöpwgê£3cæ›Ütã´Z-ѱ{±ÖhÚdû¢mYY˜§2›Ô†2 `c˜<_ýµq—«‘W»Þ^^Ü}׸ººbmcM~ Ѝ{'¢Ré_âèÒ¹3‘áᔕ—ÓÃï^½@¥ÂÙÉ ³ 2* ìß777ËeTЭ[W|úö 8(aCƒ©®¾Hÿ~ýAbR2÷Þ3¡þF«ÀÑÑ‘€ÁƒÛ|\f¿ûîf ¨4LU@5 5L:Kë©ê™g £1ˆ¶€=ÐÑ0…—^8?¯mŸ‚¸\V®^Ãö]Ñ|úôs²rrðéÓ‡”´T¬;Xsû­ã¯t³„ÈëÀK/<¥› šH†¬B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ "BA$B(ˆR‘@ ¡ H!D)„‚H …P ¤ ÒÜ@êÌ&!DýZ”•Æ©«õ³ö|!„eõe¦Áì4¥‡4ßÖ0I …h˜¥¼4š›¦YÍ7~Ñ0 !êgÌI³:±õÌ×Y˜jÒÞÁñÀ°4†m©¹rUKž…W cÀŒ¹¨ª€J  ˬ=ÕG 5lIDATQ_ kW\»Òý€=ú@Ú¢eÀ ¤¸>˜ò"úlTåèYŠ>+Õ4£—´H—ÂdÞ;+­*¸<­až•aR!a×c>Œ½¡1冟Æ@{ÊÚ=c€6ÔCZªƒg œqž†K½£R\/jwXÆ!«±§¬4̳4tµ¨9CÖjô«4›oì1½£1B\/Ìi ¥y0«¹4lmѵveÆ.Ye¨jÌ/æ¨R\?,]ô4°Êì§1¬¾Q ±!+†JàÒKæcfc¯(a׫ú^‰0ž;ÖwµÕ¢¦Y!¬=f–0 a9”æál4ˆF Heá§yø,Q)®GæïÄ1fíßk—­£±©jý^;|µ{E ¤¸Õ~)ü7´ôF€z{ʦ¨v™úzC £¸ž5õÍä [›¢úÊJ…¸¤¾À5齬- “„PˆÆÉ§¢„B!„B´›ÿŒ×ÇS[{/IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/basic_example.png0000664000000000000000000000773415074673150022757 0ustar00rootroot‰PNG  IHDRä nùËsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timejue 08 dic 2022 20:57:52‘‘#û¬$Üp<7È:«‚]¹²®ˆ'Ú:=Y´;hG£‰ü9O/nt‘ÁÛxY›´7·ð<­|ÝÑí¹Ålåk·ŸkU{B‰ Ͷx#¾&p£‹Œ/| D|yý˜Ú‹[„Nˆn Q¢'r‹1e‰Œ5üç£òµáFDãÂNã$¥JJ“4PRŸÆu$z’ð°$]–T+é´¤*IW—@ØiøÏz#ÊXAFÆèŒ€N„>I‰’F®{uͽùyÓæÊ#¿‚ˆ^À£`0¬úý¶«ï;w½¤O%]P(Vš£tÂŒe¬p"§¨á!ÆKJÍÏÏ/X»æ•ç=%wøŽ7¸ TýåÙs¾¹k×®í’ÎJªW(LgÔt›Â^¥µ ÃGGgdô5. ’æååÍÚðê+/ƒmšú=šGž†;gßó`QQÑG’ÎIªS(ʵ|m)E‰2Vn#c‚B¯o)=¸ÄÈ4óT ¿yÔW$)ôÓ‰Òm¤¼Š7ÚZ#¾v¢t¦ªé¯¼¼jŽˆˆô¿´êÅ»ÚÁ¯P3qjù®ƒe0ŒuØ[øT5^¡‘±Ÿ¤Ñ‡îÿ¥Gòwúö=L08;bÔ˜û%í“ô™B#¥óš2r'O ­½ösÛ³ê„é÷x‚)]{X-Ð3x¼^¿BƒU¼ZîÜñ*ÆžÖ¶¾dxkpôHꯖSV瀙Vµe„Œ Ò')ÁhU‚š{ ÒYÚµSÇmÚ×%7è¹Â[‰<¤4*·ÒíãS‘Qz»øs™@O~xi´¯)ÛrèœÛäqô´*œÞµûiÒÄñš8~¬r³³u´â¸^Ýðšv—”hˇ[õÇ·ßÚ-Û½fåAó9=:ÿÛ8p $©öüy=õìs*ÞS¢×V¯êÌê£ý…¨:zP8ó–6Xÿ?ohòÄ êÛ¯>Ùµ[I‰”?mŠúõí«C¥eúÝöÊš©YÓ %…¦‰k_Û¤¤ÄDùS’UV^!IzëÍJõ§è¾{îj±þiOÉ~¥¤$kfa¾|¾æ§3hÇÎb­¨PZZª&Oœ¨úKr¦½ïëŽÛoSmí9íÞ·_É5«° ißš÷õ¦u–«ªš½ð‹—u᳋Ýú˜]k9ÙCµ·d¿?±BK[(ǣǟxJ‡ËŽ(;+«3«îP#í ²y# 1­}íu½ûþ®¬T}}½$)+#CO>þ˜ú÷í«5ë6*=}f†‚üôÀa­^»AöÅ;´·dŸŽ”•$½ùë÷äõzußÝw5=îÛvìÒ–?nÚÖ;›£¥="Iªª®Ñ²®ÔÁC¥M—òûµxá ÏÍÑÙÊj­Y·Q[>تŠãÇ›×ñÞo´lÑ£-îC}}½JöÐ;ッ„„åO™Ü£žûï?ò]-Zö¤ÊŽÕâe+äñxTz¤\ƒÓÒôï,èŠûÚ®0c½‰N:SY©þÆßë¹§ŸÔ´)“tìÄ ­}“2† ÑÍ7 ×éÓ•:qò¤¤ÐU’fäiÁ·Òm3B¡>»|©6¼ôb‹õ&è¯Åß[ G¿ó/JN¨¢Ý{uàÐ!IÒªÕktðP©î»û.=ÿÌr}ùÏ¿¤Êª*ýìÅ_´XG}}½o}w¾Rý)*ÞS¢Olº|ë¶íšûwó´ø‰åª8v\sž2î¶Çêz”šªe‹UfÆ`••Ué‘r¥§ Ò’E 58-íšßžä_Ì’”’œ¬[g*{h¦þáoÿZ’T´§DA5«°@’´³x‚ jû'»”””¤qcG‡­ÁyµØr½£GÔÔÉU7ES§H’ŽŸ<¥@0 ~·M©~¿îÿ«ÙÊÊÌЃ_½_þ”•ìÿT—._nZÇÈ›‡kê䉚6u’fä‡v;q²i;Y™™šs×_èö[g*!>^Oÿçózë½Í×ýqíêqq>%Ä'4ýߎ÷Å+>>¾Sëì(FÈk(}Ð y½^ÕÔÖJ’fNÏ—$í,.Ö¹sçt¨´L3ò§ÉëmßÓ’’Úás%PuM._®SzZjÓ[^¯WCÒ U][㺎dgW®4—34SÜ{~hžV,Y,Ç£—Ö¬kß6®ªº&4e-?ªì¬,ege騉zü‰§TUíþXu§ŽéöGðXÜ?~Úø}ii¹€§¥KAiHZºFŽ¡¢â½ÚþI‘€fä_ýó ûNU—ó’$ÊëõêÄ©S \ HAéJÕ–•+..N驃¢?‡nç5.¹ÙÙп¿.\¼xý×.\–>µRG+Ž);+KK-Ô’E ••¥£ÇŽiéŠg:ÿÜ·#d7;sö¬þ÷í_ëø‰SÚðƯ$IùS'5]>kzÎ]¸ õ¯¿¡¤ÄDÝ2~lÓeÉII’¤m;v6íŠÅçóiܘѪ©9§Ÿ¿¼F'OÒ†M¿Òg—.©pÚ”6¾ úás?Õ[?Vé‘rïÙ«Ÿ¾ðs;^#oÞŽ{oßáÒ2–«%‹ÊŸœ,r²–,Z¨Ãru¸ìÈ5¿=ø[8ø5ÐËü÷ª—š¾ó¹QºóO¿(çñ›9=O«VÿRG+ŽéO¾ðyy½Íp|~Ö ½ùîf½²v½Ö¬ß¨Ÿ¬\®–»û9ïÁ¯ê+žÑ¦7ßÖ¦7ß–$ ÏÍÖ×þæ]ý+<q*•WThëï·éƒ­+\fÆ`=üÐ<—íÞ¸6¾übØw¡ûåO¨•ÿñƒç]+²ç<%Ý+-5UëÚ·ÿ€2† VÞ”IŠ‹k>8=-M7¦C‡Ë4£0¯Åã:jäMzvùRíØU¤> }”ÐG~¼æÎ™­Üìì¦ëN7V^¯WÃrr””=T?^±L;véLe•†ffhò-äóù”ä÷§hîœÙÊšÕ´ŽqcFkîœÙ6Ÿ†ffjâ„Ðvxî»Û{$áÇ­:Hî«Ð.“—éöí^y­näê¯ÿ£&&é¿~ütÔë}íŸæ«¾®N«~ö\‹7÷qã9züw$mUè¯Ï“tQÒ%µüSW½âìø³Ï¯É¶kå±ÚY´[µµµšYX _œÇµ—ã5ä5ý±úí‡I’ ¦Mnõzè:>e-)fÊ D1rÌ„k;eåw9Ðõx ÂkHÀŽÔ !HÀvê†tb§I])+`H‡GÈŠ#‡»òvP'‚,¼íŽ®¼Ä”0… C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0„ C0¤½AÃÑu¨•XA#N#Ïà.Z3­¶Ó–2|EÆ… Ö¹õ³›¶NYÃW~¥qÓI»1_”óƒ.K‹ ûHœ/©Ÿ¤Iñëòª9rOGîpƒpsºhT/©NÒgr2r¹J´ #7¹Ñ?Hê¯P}ŠÒ')N‰Þ!<È+ µQ'é’BA^T¨•µc”t 2¨æ˜ÂGGg£õ’.«9¼@ãyq‹GĈÞÁéà 6.5ž:A:#eäÈxU ­nSU'<'8ç¼x5މÞ"rÀr¦¬ÎHY×xžÛÔÕU{¦¬ Wv¾3b:££$Ð[„éDfƒš§­š²FnÌ’=’ZþFß™ã#$z·žN€õa§N¬1ˆ5eUãF¤æ·:ÂçÌΨHŒè­¢½á¼vŒ¶·ÕU[§¬N„‘sfbÜ£ 3fˆŽÖò¸œ†Çç"A¢7 ?'<Ìȯ#¯{•Xy"¾ŽŒ/rT$HôF‘oe„†nD)ÛPäu¢†ÄˆÞ¬­“·:mmODÑ®Kˆ@³hÁµéXÖŽÆD„@l|* ÐmþÁrëO \ݯIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/clipboard.png0000664000000000000000000007046515074673150022123 0ustar00rootroot‰PNG  IHDR ‰³rˆ§sBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timedom 25 dic 2022 14:44:236 ¾ IDATxœìÝwtÕùðñïl×j‹êªwÙr·±166¦“„Jè!”@€B „Nx P„$@pè6ÍÆ˽۲zïÒ®VÛçýCÒZ’%K–lI¶ŸÏ9s$ÍÞ™¹s÷ÎêÙ[f@!„B!„B!„B!„B!„Bˆ½¤ìÇýíë} !„bä©ýü>,à ”^?{¿&ˆBqàSé;ðP{ýÜ+C zÝÿîþ»f(B!ĘêüÙ=é”ô¤ôkoÞ-šn?û <´{“!„BŒIÁΟ½‘Pë»ÿÜ#Ý ÞW+‡¦×ïš^ë¥D!„8ðiÙptý Ññ¿¾¿ cÀ d0- ½[7zZv Ýý ö-„Bˆ±ÍOÏÀ£k Ò3(éÞ*2`—Ì@- ½ƒî‹–]Á‡ˆâ+1ˆ} !„bì 퀨;×iéB‚tÄ Ý»dºb‡~ƒÁ ½ƒ]çu€ÈüâóO®—“ól¨2F!„8h(¨¨´îعó“OúÉK@1Ю†Š@¯-B `O‚BÏ1Ý[;º0¡¤pÇKt"B!„8¸µdd»Ø ÔÒ|t-½»fúíŠÙSÒ}–KWwKWàa¢€©%…;þ‰ªÊx!„âP¡(þŒìq€fÀÇ® ¤«[¦÷,™ž»èo×ôœÝ¢¡cP©®ó§˜Z´sû[ ØöÉÉ!„‡BkVÎø éB¼t V tþì>XµÏVÁL•íÞÓÕúÿÙÇ]&Á‡BqhRÀöÙÇ]FǻƇv͆ݣþÞ÷úè=þÃ1n\·›y!„B¸:c»âƒ®‹Þ÷ ÛÍžfÁôî†éÚ¹ˆR4ŠuŸ=“F!„E£Xéªgר qƒJÏ›•õ0˜û€ô¾÷‡0«!U‘¹¶B!Ä¡KUU0Ó³û¥kÙãTܾÞÏ|é=¤kÙwÏäB!Ī{lÐ{ H÷Ÿ=†= BíÝúѽ+Fžó"„Bèôõh–>õ×£ôú½{0ÒyOiÿB!DG³ô5ð´Ïq ýuÁô¾û©¾s1„‰?„²ú†âbcG9'B1l†nK÷»¢jéûɹ€<0Nˆ}æë¥ËøjérŠKËp·»Ir$°`ÞÎùééœùUD˜L¼úì_i÷x¸öw·¡Q^{þŒFàöþåWa³Xyñ¯ïç3œï~Ègá_žâŸÅ眵Ûë7ÝþGŠJJúÜöíW_Äd4îï,I÷÷J±ÿ 9‘!:„B!~ìIV®^ƒÉh$#=ˆ¡¸´Œâ²ò׊  ÒÓRÑ( :½n¯¯¥±ví ôÌíÙ3C¯ïùQ£h4cî¿z… Ÿ¼§Çº½3V®½Þ¡U߯ÿæÚ+ÃeÒÿöcÑXÏŸ{çÌ /eâ„ñÜñÛß`³uÜȼÕåâ‘¿ü•›·òþ[ÿÑüHŒÃ …xç?ÁM×^µÛ?ZFÓo7×_^oàõžÿýãÇét’¿j-‘–HÎ<íd~|Âq=¶k÷zyôÉgX³~#Qv?=õd~|±=òóïñͲåÔ54š’Â…çœÅ¬Ã¦ÐÚÚÊ[ï¾ÏÚ hhlÆn·2oÎ\|Þ9ôúp^æÍ™M|l,Ÿù ñ<|Ï´··óÒko²jÍZB*¤§&«ì}òo,û~—^|>gv ÕµµÜp˰Ûm<øÇÛyÑ'æóÈ#Çd4ñýÊUh4NùÑ qøLþþ7ؾ³ˆ¸Ø~uÅ/˜û‚¼ñ¹1ó0V¯[ÏŸ}‚P04êõOYöf¹÷ö[HJtPRZÎ\È\HQI)ޏ8î¾ýæ¡ï{ˆ¤Dˆa¨®©Àfí«‹aïDGÙyâáÐjµ,ý~~êo|üùÌ9|f·4Q<òÀÝh4¾üvO>û}¾˜Ù3£¾¡‘ÏIZj =tZ­–Ï¿üšg^|™÷}Ĥ ã1™Œüýé'Âû«ª®å×7ßʪuë¸èܳÃë5 ºûNÆçfPY]MþêµÄÇÅòçïE«Õòé’¯xö¥W<¯ïóWõø[£ÕqÊI'`·Û¸ü’‹xê¹¹÷áG()+çÔŸÄ´É“•ÏÈH3{ìÿ¡ÑhxóÝÿðÿù€Ž^À¯¯º€ßüþÊ**©¨¬"+#}ÐåÜ¥¨´”Uk×3ë°éÜ|ýµx}>¾[±’ÊêêQùÖ(ÄPÅÆÄðà]wp׃SRV@|\,÷ßuޏ¸ÏÏ0¡#ìâ  @UMÍ ®‰Þiºÿ­×éÑh5¨¨1ë0E¡¢ªºWŠFAEeÞÜÙ<õÜ‹”WV¢¢R\VF(â°iSÃû9êÈ9<óâË”UT„÷³uûþ÷éì((¤ÅÙŠªª8[]=ŽÁ¸Ü¬ðºÒò ¦M™Þ·ÕÙí,ú?÷×^xºG×T÷ó>îèù|óÝrÖ®ßHRb—\pî^åS£Ñ†Ëc|NG°¤h•pšq99”UTÒêr†× ¦œ»òX^Q Àª5ë8ó¢K{¼ît¹öxÞBŒEZ­ƒ~×Ì;½N^¯•º,- B CJr†â’2JÊÊÉHKÝ'ûõx½=>(zóú|è´—±ÇÓ±M0Ü•ÆëCQ”ðX”ÊêjîyèŽx®¿ú RSS¸ú†›ÌO0ØñH‡“ig³g±ÑQ¿©(eÈùÔhvïQÖj÷ÜËc rîý^ýøøãøø‹ÅÜ~σ{Ô<êikoç–ß\»Oò#ÄH)*.!+#?Þv3ÑöŽÖŽûïº>FQIéˆçg•áœ,²Œ%Âdä‘ûÿÈ%œKnvUÕ‘àˆcâøq€Ê¥O´ÝÎ'‹¿¢¸Ç…Þµ°FF’èˆgŪÕ$ÆÇqçÍ72.'«GšŸx–ÈHVä¯"ÁÇí¿½žIÆ…Óüþ†kùÑ ÇÒîñ²jÝ:òÆå²ðÞ;;[0T&æårîYg ÕjYòõ·ÄÇÆt|¹ë8=ÿîXn½ñzæ>“úÆFŠŠ‹¹þêˉ‰Žî3m÷ý¬È_ÅÒå+z,ÁP—ßx“†Æ&.½à\b¢íüò …øÛ‹/“7.{ùdë_ν߫+/½ˆKÎÿ­†ÿ|ø?¶ï, ÂdDUC#ZÏd‘e¸Ë{ÿ|…ÇÿtÑv[x]´ÝÆãº÷þùÊ0ö=4}=¥®ûSo»žѹ˜ 0§`Û¦±q?h!ýòl+Ï=ùèhgå &å,ľ—›7ùwÀ À¸öÎÅß¹ØõL˜°a´€!„B ÍÐÇ€ ½ÕEѹ®F†”³£Nž#Ę"×ÕÈrb´É,!Æ€7_zv´³pHrbìÆP…B!†FÆ€!„bÄÉ!„BŒ8™†+„Bˆ'ˆB!Fœ BB!ĈÆ T A„B14Ò#„Bˆ7äŠÒ¢}™!„BB†€ÌYp닚XW줺5(CÄèP Ѧez¦•iYÑ&WU•Ö¦&šëhw·@…è[„9’è˜xlÑÑ(J_'ßEê­+ö¦ÞîɰnÅþÅšj6V±ÚbHJ‰ή„¯§%[Z¨mörâa‰ý¦SU•úÚ*ÚœN’Ó°Ù£F0—BôÔÚÒLMe>¿‡8GR¿æRoÅXÒ»ÞÕõEMl¬ —Èü“ =bèT`K¥‰e;#ØXU#ª©Ï–UUiij¤ÍédÜÄ©#ŸQ!z±Ù£°Ù£Ø±ez½{tÌnAˆÔ[1Öô®·C5äA¨ëŠXmvæç˜˜$Á‡E 0)ÙÀüV›uÅÎ>Ó…B!šëIHNÙ 1€„ä4šë …B»½&õVŒU]õv¨†ÜRÝ$)%‚‰É†!\ˆ}ib²eT5w{MUUTUÅãnÃj³£Ê4r1†XmvŠ ¶†ëiW+ˆÔ[1–uÕÛ¡ú4ÜÎë@Z>ÄX®‹ý|Fˇ·ëúª£RoÅÁJî"„Bˆ·_’ÒÒý¹{!„B ¤D!„#nX÷âÀ$}êâ@$õV\$‡Ó'DRoÅÁf¿ UUUÜ{ï½|öÙgTWW“À‚ xòÉ'‰‰‰Ù߇Çã! a6›Çäþ„¬Å_~Ň}Äö‚ÜmnÒÒR9ëŒ38û§gŒÈñϾàBÊÊ+ú}ýÝ7ß #=}Èû÷ú|¨¡&“iÈû£ïÎ{ïã³/ ÓéHKMå쟞ÁyçœF3üQé'R‡GÖ~ @|>§z*³fÍbÑ¢EÄÅÅQQQÁ7ß|CTÔØ¸•ðC=DAAo½õ֘ܟƒqÿC“¿f ×\u%7^wþ€Ÿ­Û¶cµDŽX^ùï¨7ÒzóÿÞae~>ydaøõá导ö:eååŸßÿþ÷dddàp8¸úê«q¹\»û‘Gᡇâí·ßF¯×sÝu× ¸ý}÷ÝÇôéÓ ¸\.ÒÒÒxõÕWûÝ_—óÏ?Ÿ_þò—=Ö-\¸3Ïüø#^û盼ü×ø|ñæs<ö—Q/÷}¿ d´ó·ÿ–Ó§ÑÜÒ‚ÛíÆï÷ñ—¿þ•³/¸£N8‰s.¼˜>ý´Gúå+¾çÒ+¯bÁ‰?â¬ó/äéçŸÔ~ëÉžêÔáý]oû·_éÓ§3uêTŽ>úh.\Hyyùniî½÷^Þ}÷]Þ}÷]V­Z…ÑhäøãÇçó…Ó,^¼˜_|‘‚‚²³³9üðÃ)--eÑ¢Eäçç³sçNþð‡?„Óßpà lÛ¶•+W²zõj ¹í¶Ûv;ö­·ÞÊwÞÉùçŸßïç™gžpû;ßÏ_ÿúWî¾ûn¦M›Æe—]ÖïþºœwÞy,Z´¨Çóþûßÿrî¹çº,ë‘GáÕW_åõ×_gýúõ\|ñÅÄÇÇc0ÈÍÍå½÷ÞcãÆ\vÙe\~ùålÛ¶­ÇöŸ~ú)Ï>û,………Ì;—sÏ=·Ï|ôwœÁžÏ+¯¼Â£>Ê–-[8òÈ#9餓hnn°¬DÇCYy9S'OÚcº^y•Å_}ÉÂïçõ¿¿ˆA¯çšßÜ„ßï§ùïGó›ë¯å7_gêäÉ\÷Û›q:œtüñ|ûÝw=Þ‹o—.ã„ãŽÝëüþù‰§()-çµ—^àW^¢¼²’§Ÿ}€Ë.¹˜@ ÀÛïþ€çÿþwÆåæpúÉ'ó‹‹/äŠK/ᤎãû¯—pëÍ7íõ±ÅØÕÐPOll,fsz½žÔÔýÓƒ¼ýú«œ~ÊÉÜ÷ÐÃáûJµ¶ºøýwqú©§ð¿ÿü›??ü Ç}4@¿õdOõnoIÞwökb4Y¶l7Þx#O<ñ™™™\xá…¬[·¯×Ëc=ÆsÏ=ÇÔ©SÉÎÎæµ×^£µµ•ÿþ÷¿áýüüç?gÆŒ$$$pË-· ª*·Ür YYYŒ?žË/¿<ü ½µµ•_|‘{ÃAjj*<ðï¿ÿþ ò<ÐöƒçŸž{ï½—ÿýï¼þúë¼øâ‹ƒÚ÷)§œB[[?üðµµµ¬Y³†ÓO?}Ðe1@€?ýéO<÷ÜsÌš5‹””.¼ðÂpóü¯ýk¦L™Bvv6wÜq™™™áÓTTV˜0~|x]DDS¦L¦¸ŸîQFÃÔ)S(-+Ãh4²`Þ‘|»lS&Obéwß1göá=Æ› FIy9¡PˆÛîº ¥óÉ=`·»-œfÆôiüè„ã¹ùŽ?pïw×y~âàòÖ;ïòÖ;ï¢( ÉII\xÞ¹üì¬]Ý«ÍÍÍ|úù¬Û°‘æÖ›ñx<def2ë°Ã¸à—rÔ‘GòÓÓOcv·Ï™ÞSïKêð¾5b÷Ñëõœ}öÙœqÆLž<™wÞy‡sÎ9‡`0H À`ØõT]£ÑØï4¥®  ¿u]³kV¬XABBÂ^çs°Ûçää …ö8£/çwwß}7=ô|ðA¸KÁãñ ª,ó`ªææf€>íír¹˜;w.?ûÙϸûî»IOOçä“OpŸ}•ûžŽ3ØóéM«Õ†Gš÷WVb»ÝNLt4ËWüÀ¤~ŸßG(" ö˜æhÐé1ýî[«Ñ„ß«O8žç_z™k¯¾Š¯—.åÄ!t¿X#;ó½úÂóÄDG÷›.%%…P(„Á(SVçœu&×]}ƒ¡Çç€ÛÝÎ忺–Ž=†+/¿”„„n¼åÖðë†gžxœÕkÖòáÇsëäð™‡ñèŸêóXƒ­wƒ!uxßñ[±ët:’““1™Läææ¢( ß~ûmøõ`0H~~>S§NÒþ322°Z­|øá‡ƒÞ¦{?ø`¶ßºu+ .äÏþ3×_}øq_ûëíä“O¦¤¤„Í›7óÍ7ß„»S‘‘‘lÙ²eÀóÉÎÎ& ‘ŸŸ¿Ûkùùù444°páB&OžŒÕjí3¸Œ=g°ïmï–©•+W2yòd ÿ²>õ Z.ºà<Þxó-**+ú|=5¥£…níúuáu¡P-Û¶‘›•EWc³ËÝÖc»Í[·’•• ¨9窫«)*.bÍÚu5oÞ òÖ³¬“DšÍ|»tY¿Û—óúÿäÆë®åÑÇÿ‚Óé챿ŽÁߣ_æûgÈhçoß§A§Ãb‰Ä`ÐïöúÖm[iimáúkEvV&‘攺îXf6{þp;/ýíi¾þv)uõuáýw¯'ƒ©w{~OÔ½ÚסW‡‡n¿ k×®åÆoäóÏ?§¨¨ˆ;vpÿý÷“ŸŸÏ¹çž‹ÕjåŠ+®àÚk¯eåÊ•ÔÔÔpÓM7áp8øÑ~4¤cêõzn½õVî¸ã¾øâ ‚Á eee}þ“HKKã›o¾¡¤¤„¶¶¶·ƒ\~ùåÜzë­Ü|óÍÌž=›[n¹¥ßýõf2™8ýôÓ¹ñÆY°`v»`Pe1þ|þþ÷¿SRRBii)/¼ðBŸçËYgÅõ×_϶mÛp:|øá‡¸\.’’’hiiáÙgŸ¥®®Ž7ß|3<&goíé8ƒ}oï»ï>þûßÿRWWÇ}÷݇ÓéäœsÎÙcY‰ž.:ï\òòÆó‹_^Í;ÿyŸ…E”–•ñÉç_ðí²ïˆ4›9ãÔSøþ ›·n¥±©‰ÇŸú+1QQÌ9bW÷ÙK¯¼Ê7K¿£¹¹™_y•6·›ãéÜg4X0=ù43¦OÃ2„û‹èt:~~Ñ<ýü üŸO(¢¦¶–Í C¡÷?¼Ÿ_|!_p>“&NàÉ¿=ÞÞáp°zÝzª«kztÁŠƒKll .Wÿ~ïš››ùäó/((Ø~½ÅédÑGSW_ÇãaõÚuDDD„»g{דêÝÞ:¼oíפ«;ãÆodêÔ©ÌŸ?Ÿï¿ÿž%K–——ÀSO=ÅÉ'ŸÌYgÅ´iÓhjjâ“O>ò·r€;3Ûo¿n¸»ÝαÇ˪U«úL{É%—0oÞ<¦L™Â\0àö=ö.—‹ßýîw<ýôÓ¼ýöÛ,Y²¤ßýõvÞyçñÅ_ìÖ¥0PY<òÈ#¤¤¤0yòdN<ñD²²²úmBÿûßÿΔ)SX°`iii<öØc444——ÇÂ… ¹çž{ÈËËãý÷ßr°·§ã æ|N<ñDn½õVrssY¾|9_}õU&ÙþÊJì¢ÓéøÛsÕ—óù’%\uÝõüòW¿æßï@[[Ǹ›oºyGÎá÷¸‹ /½g«‹'´Ç{qĬYüõÙç8ë‚‹Ù°iÏÿõIôz}øõŽ;Žòó‡ÔýÒåŠ_\Âe?¿ˆÇžü+ÇýäT®ùÍMlÛº€7þõ6ííí\|þyüþ·7òÅ’%ä¯Z À)?>‰éS'sÁ¥—qç}÷9blËHOçúkÅó/¿ÂÏ.ú9ß|»”9³wÊ.§“Å_Íϯ¸’“N=ƒ>üÿ÷À};?7úª'{ªw{Kêð¾Ó×yMç¢ôKDçb,Àœûþ¹áñ¤Ôt®:ºÿA%¥¥ÃºmíÁjûöíL™2…ºººCú[ýìÙ³¹æškv»ßGw{[V/~ÓJUy)¿?3«ÇzUU lÙÀ¤é}Î=”]vÕ¯8û§gpÆi§ö›¦´¬Œ /½œO?üË^@Û¼.ŸÜ‰SÑétáÀPê­ë6¯ËgÖ‘GÿX¸7ÐÞ¹ø;—ê\ÂF|ÔBe IDAT ˆ€÷ߟN8á>KÊjìøúۥ̞9S‚!Ä>!OÃo¿ý6×\sÍhg〰Êjx§ný—ÍçK–pö™gì1ØŸ¤ÜÅÁEZ@FXAAk×®åŒ3Fæ ¥2)«±£¬¼‚;9zþüÑΊâ ±_[@düÇîrss ƒ£1¡ë¹/ý‘²9¯¾øÜ_OKMaùW‹÷˜F!ö†´€!„bÄÉqÈîó Øûþܹ8„I½›¡ xUúžË+ÄH „X!åÃVˆ¤ÞŠƒË»`mZ¼žv¶Tîý£â…ضTúðzÚI´iûMc2GâjmÁ\ 10Wk &sÿÓ›¥Þбh z;! Ó3­8[[X¶ÓÃæJŸÄæbÔ¨ÀæJËvzp¶¶0=ÓÚg:EQ°Û£©«©Ù 1€ºš*ìöè~¶)õVŒE]õv¨†Ü3-+šÚf/«ªYÒngYÁÞ=Vˆ}ÉëiÇÙÚ”$-Ó²v¿ EAQ"mvüE;¶Ÿ„Å&78£ÇÕÚB]Mf‹…H›=\O»H½cQïz;TÄzâa‰8¢šXWÜHUCPº(ÅèP:ºŸhí3øè¢ÑhÐjµØ¢bÑi ÔÕVQV¼³ßôBìo&³›=³ÕŠV«E£Ù½QZê­kz×Û¡ö,˜iYÑ{üÐb¬P%|±Xìv",B!U"g1 4šŽ:Ùµô×#õVŒ}ÕÛ¡’i¸âÒõaÞõSÝ¿s…Ø£®.F³Ç'€K½cÉ`ëí@$‡ùcÉ`?À¥Þбd8G @Ä!k_\@BŒ4©·â`!·bB!Ĉ“D!„#N!„BŒ8 @„B1â$B!Ĉ“D!„#N!„BŒ8 @„B1â$B!Ĉ“D!„#N!„BŒ8 @„B1â$B!Ĉ“D!„#N7Ú說£!DäqðBˆ}aÌ { 8$btu:z_!†bÌ ½õtH "ÄÈê .º_{p!ö…Q @zªªöX'ˆ£¯¯`£ûº^BˆþŒhÒWÐÑý÷®¿ F$bÿêDô:ú 2E‘Ö!Ä ŒXÒW@Ñ=Ð…Bá¿û @$îbduÅ} ]‹F£é3 t\»„!ú2"H÷€£÷OUU …Bá$RQé @H„ûG]¿£ Ñ(á® ¤¯ýH"„èË~@újíèxtý †B¨¡ííí´··ãõùðû|ƒÁpºÞûBì½FƒV«Eo0`40›Í˜L&mçõÜ•®¯î B„½ø ÔÞ­Á`ˆP(ˆÇã¡­ÍM  àñzðûüBjh·}!öŸÞÁ‚FÑ Óé¨Á@€¶67‘‘ˆF£E«íhé«KF!zÛ¯HïpkGg«FHU øý´··ÓÚÚJKK 6«•¨(1Z;(€ÄBŒ ףߠ¥ÅIC[Q¾(¬V+¨èÑ„BáÖ’îÝ2Ò "„èmDº`z·ztu¹\.õõ x=íädgumÕã‡b è¼õzqqÑÄÅÇPPX„Ûí&..‹Å‚V×ñ‘ÒhôB„¢Ë~ @ú»ÇG÷࣫壮®‘–– ¨2ÕEˆHzr 5õõÔÕÕ£Ñhˆˆˆ½>lôþÙõÙ Áˆb¿wÁô|ü~?µµµèuZlV½^Ævq QU =±ÑQ´:Û¨««#))©Ç}Bº¦Jà!„èmDž†Û}¦KWðÑÖæÆç÷a21›ÍÒð!ÄHEÅlŽ "ˆ×륭Íßï'ì6½^!zÛç- }ÝÝ4<Û%$ âõzinn‰Ñh(!`ªªbÐë1›#hnnB¯×¡ÕjQ… }߬L¤ !ö[ Hﻚªt"@¯×GSs3V‹…“ieA1BL‹…¦æf¼^_ÇôùP(|SÁ¾n((„8´í·A¨»Ýå´súm Àï÷álu úPUýþÈ‚b„…BAœ­NüþŽD«Õ¢Õj ) ¡Îé¹2DÑe„¦á¾ÿG s H»§P™j+ÄA"Ri÷´ã÷wÜ@P§ÓuZiùBìf¿ ½»_‚ã?‚wQôù|M´BˆƒA(ÂçëhýCák^«Óõø<Ö!ŒÀ,UUQ»ß€¬+ ä[‘UU;f¿t^ãÝ»_åZBô¶_ÞƒÏ:n¿¾ëVìBˆƒKøQ ê®)¸2UÑ—}ÚÓ׌ªöºj0H(¤ ©¨j"ÄÁAUCák;Ôí)Ö]ãÀvO/Ý1BÊöÿºÏ†éù<T$þâ`Ñ9Ø|×¢î BV!DOûåFdý= &ÜÒÙ<{¨ªoh¤²ªŠ`(ĸì,Ìfs‡vuñx½ÔÔÖÒØÔ„Íj##= V;àþUUÅëõ²nã&TÒRRHINR^먭«Çàˆ‹Å΃×륡©™ú†L&‰ŽxlVkx[ @Qq îövbc¢‰‹cõÚµC!r³³HNZžºsº\•”âõz™0.k·ã‹‘×Õͺ§®™Š+„€˜†Û›|‚òÊ*¾ýn9í~ŸŸ‰ÆcµXúL—¿f-ådefœ”4¨$¤ªÔ54²ü‡|<^sŸ5䤡±‰µë7RSWÇÄñã8æ¨yè""hnieÕÚulÙ¶H³™ãÅÄ ÖŽ§¶«* M,_™ÛÝÎÔÉ“0Œ|ñÕ7øü~ôz Ú>¯½ÑØÔÄ·ß}OSs3ñq±€Œr !2"£ëþ{Ï–õì©ohdãæ­467£ àpÄÙãa0dóÖm|·b%MMÍ€B0Ty©ªŠ»½×K[[;míîa•s]C=«Ö¬£½ÝÃÜ#ïxâ)PߨÈòV²eÛôz™éädgb0©!JËËÙ°i3z½ñãrñü¸ÚÚðùüx½¾ðÍ©†ÃéjcÓÖmTU×pÆ©'’õiO|~?; ‹1ôÄÅDcµZÃe ©oh¤µÕ‰Ñh$=5eXÇ õq÷¾þ…¢Ë~Ò×ï=ÿ>Ttœ·ßï'ÍZæÏ›CBB<&£1œÂét²m{å•DšÍ=¶ë>¨WUAQ@£Ñ (´Z Yiœxì1(ŠBjJRx»`0Ø™N w‡)(hµš>›ÄâqÄÇáõy)-/Çï÷Cçmõ.%e(Š‚×룶®žÆ¦&„B!JÊËqµ¹ÉÍN =5™¸˜hÎ=ë§ ªÝI:-ª"¢Ñ(y¢sp2áç‰ô †:Ó(½ºòzÖ§]eÔ±N£Ñ„ÿùv”EÇ­Â5Š‚¶³e©û6»¥ï\¯í¶~¬kjjâGþL|\,§þø$Žœ= ‹Å‚ 4·¶òѧŸ³ü‡|²2Ò¹ãæ‡y´]ÁFµ{ø,BºF¼ ¦‹|uŽÕðùX»~ñ±1äfg…_Ë_»ŽÊš‚ÁànÛy½^j(¯¨¤Õé"Òl&=5…„øxL&#ªªÒîñÐâl%b³Zˆ‰ÆÕÖÆêuHLpm·ÓÜÒBEU f³‰ñ¹9DÛí»ýcµZ,ÄÅÄbŽˆÀétÑÐÔ„ÝfÅãõQW߀×ë%!!žúújjk©©­  eeå´··CbBÁ`ÚÚ:Bjˆøø8ZZ[Y‘¿ŠÔ”Tb£ì´´:©©«C¯×3aü8lVK88€Ž–¡; ©­«G¯×ÓÜÜÒg] †B´{<ÓØØ„^o$91ô´4 õ Mãt¹HJL`ò„<›š)+¯Àét‘””HVFZ­–úÆFJJËiiiaòÄ<âbcÑéFíò4­NK‚#žšš:}òm®6N:þÿü×;¬ß¸¿?@”ݾOŽ'×µb°Fô´ÏfØCøóJ£ÑÅ–m;Ÿ“MfZZŸÏϪµëPU•ؘhüþ@Ç*¸ÚÜ|õí2¾_™ÛíÆï¢Õi±Y-Ìœ>£ŽœCLT®Ö6Ö¬Û€ÇãA¯Ó‘‘–Fk‹‹¥ß­@¯×ÑÜÜ‚ÛãA§Õ’Á±óç1eâÄžyT4DGE‘œ”DQq U$ÅÇÓØÒJUu-&'½€OIumÕµuLSU|>?•Õ˜LFâbc0›L4µ´°tù ¡q±±d¦¥ÑÒÒÊg‹¿":* EQp··ÓÖæF«íøÇyöé§’™ž†F£¥¶®ŽO/¡ °—« FC  ±©©£^u6€¸Ýnvóé—_Q_߀ÇãE£ÑegBn.'ÿè¶í(`ý¦-L—Ã伎¤  e+VR[_O^nɉ ˜#"(.)ãë¥Ëq»ÝL›29ü~Œus$œ}&ïýïcÊ+*ùvù ªkkQU•u6á÷ù™yØtŽ9jÞ>=érB dì…;ˆôzfL™ÌÆ-[)ØYDnvŽøx¶RZVAVF:Q6+;‹JÂÛè´Z z=Qö(R’’0 ”WVQRVF("6&šyGÌÆï÷SWß@{{;®¶6Tµ£Ë§¦¶§ÓIJr‰ 6o¥¹¥…$‡ƒÌ´4,½ÄFGÙIOI¡ °ˆ²ò &ŽGCc#µuuØlVf6ƒõ›6S^QEmmííêëhmuâpÄF£!RUSC ÂínèTªª©©­##=øØX,æHvSQUÅ„qã°ÛlhµZ6lÚÂÒå+Ðëõdeda2RY]ƒ¿ªºÇXƒ²Ê*–|³”5ë60qü8ÒSS¨oh¢¬¢’úúFR““ÉÍÍèhIÑéðx¼ JÊËÙVP@Ss3~¿ŸŸzª ¡àÞýP…ÈÈHt:]ø¡½éu:ì6+ÉI TTVSX\LM]=&“‘¬Œ †ÌŒt¢ívªkëØV°“ºº:4 Žxì6Û^åI§Õb‰4£( ÁP°s°®—Ë…¢($'$`6Gô¹­ÛíÆånC«Õe`5›#°Ùl¨*8]n‚Á I‰RS’Ù´yÅ%Å´:[io÷0.7—q9Ù¬Z·EÅøü~ZZZ±ÛlädX]³•Úø¿÷>`݆MâãQU•º†>üè|~?'w –HóÀ;Bˆ}dtCyn·ß'ŒËeÃæ­ì,*¡¾¡‘Ì´4²32±DFîJÛYV•ÕlÞº¶67GÍ=‚“t"z½Ž¾ýoZZ7í¾ÿnÛîöw碠ìvœÞÌfr²³©ª®eͺM¸Ú\ÄÆDw E!1>ž˜èhv•°mGmmn’°Y­hMÿyè+Ÿ*ßлåI¯Óc2™Pi¥ÕéÄïõ£5{îGíWcÔ444 A¥cOCE!ÊnG¯Óe³‘^¯§°¸ŒúÆf̤%'KbB;‹‹ñz½´{<¤&'‘àpPuÖétñÚ¿ÞaÓ–­qøLŽ[0 ÀÛï¾GEu ß,[Ž‚Â™§þdx;€ÊE1úŒ›ä"##É—Äñ¹ÄÇÅ2îDGEõ˜~Ú¥­­ g« ׋F«%Ñ…PgKÁþÁ¸œlôz¥åå8.¢£¢ˆ‹‰AQŒF#‰ŽxÌ&uõõ¸Ýn2ÓÓ°FFî“ã["#ILH  ñCþjŠJJ¨®©¥¢ª*<ÈÀfµE(bÇÎlÛQ@Mm;‹Jغ}Z–ÜìLÌèuzb££ILpPZ^Á΢b¬ÖHlV+9™444±cg!ɉ‰ †}r>#Åçó³aÓTæ>“ã>Šñ¹9L—Ëé§ü˜qÙY´´´PTR2ð΄b’.˜1@Qr³³Ðh447·0eÒÌ&¼>ßni-‘‘˜Íx}>vì,ä“/–ÐÜÒBumí°ûð÷$Âd$;#£ÑH«³G|ŽøxŒFCøˆ‹‹¡¬²ƒ^OfF:˾iÖ‰fRÞx¶lÛÎÚ ñú|جªkêèþÕÛAZZ29™élÝQÈ×Ë–³cg!MÍ—–’’”ÄÌéÓ°Z;ÚFEÙÉÊHcóÖm¸Ú\9{ޏ8ÌæòÆåðýÊ|êIIN"%9iŸœËH2 Ì= s„‰Ó¦™Ao@UUfÍ˜Ž‚BaI ޏ¸ÑΪâ3C¯ÝÖd4…ßè TâãHˆïùOÀç÷a6GÕjAQ ÁǸœlªjjiniá£Ïc6G 7èINJÄjT´: v»£Ñ@„ÉŠŠN§!:ÊŽÑ`è TPT"LF¢£ìX­ôz=}½'½žÄ„xR““Ñh4d¤¥’–šÜ#mR‚ƒÌŒtÊ*ª0 dd¤a6›Ãi4Z…˜˜h‚ÁPç]_Ut:-±11èt: †Žc+Š‚Á` 6&›Í‚^¯#6&šÃ¦MagQ1å•lÞ¶½N‡Õja\neåèõzt:-™éœpÌ| UU”–•¡Õj‰‹aÆÔ)L™”>~”ÝÆ¸œlb¢£Ðh4¤$%uü®Õ›‰ÃËå"-%…䤄>Ëf,³Z-\ñó z­UQ”Ž rþÜÙÌŸ;;¼^!FÊ(Ï‚94?òR’9zÞ‘ƒAôz(JŸå ÓëÉÍÉF«Óàˆ‹C«×aÐë9öèùŒŸËÎÂbTUe\n†ÆFt:-ŠFƒÕjeÎá³ðû¤§§¡é\7ÿÈ9ètZR’“P雞žÊü#ç`·[‰ŠŽê÷=ÑëõœtÂ1ÔÖÕKNVF´G<‡ÏœAdd$Fƒž´ä$ C8M„ÉÄñ Ž"¤†HINDì6'w B|\,jçy'8â9ñøcˆ‹‰!&&­VKZj ¿¾ò26mí˜me·‘˜àÀð³nã¢;óż¹s˜7žÂâRœNV«…Ô”dR»µb¨€ÅbabÞx~|âñ˜Œrs²0š:¦¤&%&ð㎣Íí&o\ ŽøC²¾–”boôÕf¯é\t€¾s‰è\Ì€˜ãns=Þ{Ãî  ƒƒAü~ŸǃÛÝŽÛÝFSs37lä¸cµon} øü~P!"ÂÔïcÉ;nÀð£Õj1 ág¸Aü?ÐÐùlE£ÑH(Âëó¡ª*z½^O(Âãõ¢  ×ë·÷ûýø4 z®Ï±']ùñú|ƒA´-z}Ï´ªªv¾ßþŽoØ=ÎMUUÚÛ=¨¨ t:¡Î[¦CGËV« ?§Åëóîvµó.«²SÐju¨¨ø|¾ðö]éB¡þ@ üÐ;V‡N·û¹ƒyÐ(`0Ãiºni¯†Tô=zN!¿MÍ-|ùÕ·L™:…è¨(ÌæŽîB“É„Þ`×­®güt-Bˆ›9Òò;`àÜ@{çâï\@¨s “Y0£@§Õ¡Óv+ú~Ê@AÁ ×cÐë{¤UP:‚Š^Ï"Ñëv¥Ñ("Œ¦Ûi fSDuÛéÑëô»­ï+?&C¯V©=_7èôúÙ—‚‚9¢çñ5ІÈsu :­]¯õ]ûèk ¨>B·[:­F‹ÖÐ+àèãÜ´ sßÇêQ^ýl/:IÙ!ö‚Ì‚B!ĈåA¨‡hˆ%¹–…ƒ'- B!„q2 F±Oȵ,„Ø2U±oȵ,„Ø 2D±Èµ,„<"„Bˆ'ˆB!Fœ B!„q£þ0:é5B!=£< FíX„>¹–…{Aº`„B1âFµÄëõàiלP1æy½žÑ΂â2ªH{[Z%4pB!Ę×ÞÖ>ÚYB@F5É™0G|ühfA±ÔÖÕ±vÓ¶ÑΆâ1ªˆV«E«õ‰8Bˆ}@«ÕŽv„„*„Bˆ'ˆB!Fœ B!„q€!„bÄI"„Bˆ'ˆB!FÜ9ÖçóÑÚÚJKk+>ŸƒAÝf#:&­FC›ÛM}}ƒ¤Ä„ÑÎî> ))-%ÒlÆn·c2™µ×륩¹…¶¶6r²³†UU)*)Ád0âpÄ£ÛÇÓ¨›šhjn&Âd"1!fWŒhlj¢µµ•‡«ÕÚcÛ`0HeU5¡PG|<®¶6ü~?QQQ˜#"†7§ÓI]CQ6v»]¦ !Ä0PˆÏ磮¾žÒÒ2jjkpµµÑÞîE£ÑËÄ yŒËÉ¡¡¡‘•ù«ˆŽŽ:hŸÏÇÒåß“ž’Âĉ€8].¶lÝFIi)Y™=þ¡E0ä»ïWÃQóæa±ìÛ*TU]Ãú1 œzÊɺå×ÕÖÆù«(**âèG1iÂôú]·òw:]¬Z³U…ùGÎeõÚ5´:]Ì™}8iiÃÎ[Mm-߯ÌgÒ„<&æå±‚!„8T0]0¡PˆŠª*¾Xò%¯¼ñ&Ÿ-^BiYõlݶ%_}ÍW_C0¤¥¹™õ7²£`çhg{Ÿñûý¬Z½–‚Â"œ.× ·kkkcga!ù«W£ói¥ªªX½f-[·ïÀëó k}ñx<ì,,dñWßàëµÿ¦¦f}ô1,úˆuë7ÒÔÜÒãõ²Š ÖnØHiy9Á`ÕkÖ³â‡|÷IÞêY½f-啸üþ}²O!„8T0- N§‹¿÷_ªª«8ûôÓ˜?ÿÈp¸RQÕŠ¢ìó.1²Žx ¬^³§Ë…ÉdB§Õ qºœCm]•UU8âãÂÛ–”–b4HKIÂǯ¯þ%@‹Åº‡# !„ Ì믾þO»›Y‡Í`ΜÙX-–ÝÒôþ†ïõy©¬ª¢°¸˜` HZZ*‰ =Æ445QUYECS# àp™Á`:º0*ªª°˜#QÕuõ ¸\mØí6òÆÃh0 (Jx@€¢’jjjÑétÄÆÄ`6›ih¨güøñ˜ŒÆpºæ– ‹‹ñy}ÄÇÇ‘œ”Ôçyõ' áv»),)¡©©  Žøxrs²Ðjµ»å«º¶–Ò²2ÔŠÃOjJJ8?]ü~?MÍÍã÷ûILL )1Kdä ó5q11¤¦¤ …(,*ÆiÁb‰¤¥µ•êê’“™:y2.—‹ªêjfL›Þ¶¸¤“ÑHJJ ~¿ŸŠªj|>/™éé˜LFšš›Ù±s'ǧ®¾žšº:‚Á ޏ8Æåæö(/UUñx<ÑÔÔ„Õb¡¶¶®Ï<ûü~š()-! àˆï(³Î÷rÓ–-ü~I‰‰áí6nÚL $91‡c×3‘6mÞ‚?`\N‘‘æ}]ÄB1&0Èšuk‰Š²3eÒ$¢£¢úLÓýˆÏïgÓ–­ýFCk«“å?üÀÌ38òˆÙ˜ÍfêêëùbÉ—47· …p·»ñ´{9|æ æÌžÃÓédõêµTTVb2Ñëô´{<´¢8˜ IDAT{<¬Z½†Ÿžv*11Ñ(ŠBm]ËW¬`ëö˜Œ&TUÅï÷£h4ÄDE‘––†ÉhÄér±mû¾[±‚“‰`0H»ÇCJr2 æÏ#)aàq+ªªÒÐÐÈ;ÿy•`0ˆ«ÍM("';“Ó~r2KGÐ ¨®©åÝÿ¼N¯£½½U…Œô4N<þ8¢l64šÿßÞ}Ç·uöþÿœƒƒIÜ{S{yÊV,¯xÄ{ÄNìÆIc§iFórÒ&M“ÜŒÞ&½MÓþ2Ú4¹MgÚiÓ$ÍM³<â)kY¶¬aMJ¢¨ERÜ$H‚Øøý")Š¢DŠß·_ç%88xpç‹gÁ¤?`×îF^cn·‹X4ÆÆM›¨«­eå[Vdå‹].EE…ÑÔÔļ9 x½9ôööÒÒÚÊâE Y~Ùe<óÜs´µ%‰`·Û‰Æbii¡¾¶–ªŠ †C!vìÜÅàÐPj€r~>===<ÿ‹lxíõLKÙÐð0±H”K.ZÆ5+¯Âëõ‹Å8ÜÒÂK«^¡§·‡ÃN<§¥µõ¸îœîžvìÚÍkßÀãv‰„‰FcTUVpÝÕ+©¨¨ ¥µýû›Y0>åee$“I†††xiÕ+ôXù–+¹±äzlx}#§ƒóæžóó-"r¾Lû1 ‰‘O¢­mmäææRYQ>µÇ%Äcq,Ë¢ª²Šêª*:ÌÆ76qààA’É$‰x›ÍFA~>5ÕU”––2â™çžçð‘#$ Âá0­­­lݾh4õ鶪²’I~÷‡§ØßÜÌðð0CCCìÞ³—_~ËfQYQAyYáH˜m;vp¤¥•X4ÀƒY¿aG¶SZRLuU‰x‚]»Ù¸ió”ÏMˆ'PSUEeyÃÃÃüá™g9ÒÒ’£‘H¤ŠaT”•QQ^ÎÐЯ¾ö:olڜٯ©©‰ ¯¿NggåeeTWWFÙ±k[Þ|óÔ*î4†AžßO]m ûöï'L}Å{Oo/­mm\¼l æÏÅårÑÓÛKgW‰D‚ÎÎN†‡‡ÉËË¥¨°h4J{{;--­™cƒÃìkj¦qï>l6‹ŠòrŠ èéíåW¿ù-]]Ý$ ºº»Ùúæ›l|c>oÕ•U`˜&¡p8SÖX,ÆÞ½M¬]·ž`0Hyi)••„Ãa6o}“µë_%‘Hàq»8xèMÍÍÄãqâñ‡´pððaÞܾ$ ZÛÚhik#4ʴ‰ˆ\ˆ¦} H"‘ /`8ÆårMyæÝ²¸hÙRyÏ»3oäCCƒ45 qß>–-]Jyy=øÉdêÝ?0Àœº:¾öÍ£½£ƒèÈ@C›ÍFeE÷Ýs7õuµÄãqvìÜÅšµëØÛÔDUU%Á`Ý»‰Åâ<üž‡(,(À0 6oÝÊo~ÿT¦\±XŒ»w³»±‘»n¿+–_ŽÝn§¤¤˜Õk׳þÕ Ü}ûm'}}†aPR\Ä£þ ¦i‹Å…ØøÆf¾ñ­o³¿ù¥¥%™ò—••ðþGÞ‹ÇíÆ0 ^c¿úž}îy–_v)–ÍâÍ;8pà·ßzW,¿ Ó4),È畵ëxíõ7¸å¦›NµúN‹ÏçcnC=xæY‚Á`fúmWw7K-¤¸¨ˆÊòrºº»i>p‚Böì݇Ï륨¨ç¸n¥ÑW,¿œÛn¾‰Ò’zûú(.*âËÿüU:»º(++åÀÁCìØ¹‹¹ ¼ûOÄ›“C,§rÍZþë—ÿ9ÖÀÀ »9ÚÞÎ'>ö(ÕUUØl6¶ïØÉS|ŽV­æöÛneN}=–eÑÝÓÃàÐ.§‹]»)-.¦»»‡ŽŽNÉõûin>€Çí¡²¢\Ó|Eä‚6í[@’‰‘Hd¤;#F4›Òãl6N‡çÈÚš|^/@j‰a$’I"‘=½½´··§ºq’©)ŸÃ¡¦iâq¹3SXm6~¿Ÿ††z‡†G"ttvÑ×ßÏe—\„ÏëÅ4M ÃÀíöPXP)C 0@GG==} ¦Z!Ö¬[ÏþýÍôöõÒÝÝuJçÇ0 b±Ý==ii¥¿¿Ÿ‚¼<@&@™¦‰ÓáÄíreÊUW[ËÒŋٳwÑh”þ@ U®Þ~ë^ÝÀšuë9pð=½½ôôž™$Sá÷û˜3§¶¶£zzzéííÇ0lTWUa·Ûi¨¯Ã²l457EiÜ»—’’ŠF뉆ÇíÆf¦.î¹~ÿȱ,úúû ‡ÃttvÒÛÛÇÊ·¬ÀétbvË"Çã3F§µ­ÊËʨ«­Í†ùóç±xázzzhï褠°ÒÒR"á‡!žˆ³«±‘¹sX¶l Mû›I$457ãóæ¤ZÙDD.`Ó¾IJ,JŠ‹q:ôõ÷Ñ××G®ßZDz;ì©‹D2™™Rúû§ŸaÛö$â Š‹‹°,kJÓKMÓÌ\œHBpx˜áPŸÏ‡1ÉZáH˜H4B,£?`h8¤Zz*+*X¼`Á”_ÏÀà «×¬åÕ×_Çf³‘ŸŸO08L8&ÉäSn=n¹¹>Âá0¡PŒÔÔh,J_ ŸÁàP¦\uµµN¹\gÊåtRQVFAA­G¦ÆÜ 3îœÌ8ŸºÚZÞܶ‡Ù½gW]y…§XNÓ4±, Ë:Vg¡Pˆàp¿ß9j\ÑxƒƒƒDã1rÆ Ðµ[—ËI?•åeÔTW‡8xð UU•8xk®¾ ¿?—í;v°»±‘‹–.¡ùàA.¿ä**@DäÂ6íˆa8*ËËiimeϾ}ÔÖÔœö±Ò°p$Âö;ضcÕU•,Y´¯×K<ç©?þq cLаÛ,LÃdp(8ézn·—Ó…Çãaá‚ù”––dZV \®wŒ‡9pè¿úŸßróM7P_[ƒÏçãHK+Mû÷Ozá„Ô‚b±X »ÃÝnÇétàt:ñy½,Z¸€²’9†a¸]Ù[tË4MêëëÉÍÍ#/7¿ÏOkkÛvìäê«®"™HRŸß§©Ã"ra›ö]0º@¬¸â ¢Ñ¯oÜÄ®ÝÇív* mÅb1š›ÒÓÛGuu5Ë/¿Œ… æSYQý4ÖñçúñxÜìÙ»¡Á¡Lùâ±áQs<Š ð¸ÝôöõQSUÅœúzæÔ×ÓP_GEùäƒl“É$$!ŽÐÑÑɾýû™?w.—]r ‹.¤ª¢"hF]PÉ‘h”P(œ9GÝ=½´m§¶º§Ã×륰°§ÓÉ@`€ºÚºc媫;nEÙäÈçŠÝngÉ¢…tvv±s×nBá0sæ4dî÷¸Ý™1.¯¬]‡Ãa§  Ê+ÄNÆïóáv¹Ø¶cGf1´t‹ÙèÅÑ òq:´wtÒv´x<@Ww7]]Ýx½^Š‹ŠFBWâõzijnfÇ®ÝÔ×Õâ÷û)).¦¨°€Ö¶£lÜ´‰ü¼< Ƭð*"r!šö- i+®\Ρ#‡Ùµ»‘§ÿøƒƒø|^l6Ñh”D<õisª­#©‰‘H„––Vöîk"‘LpäH ápdÌ'â©(-)¦¢¼ŒÍ[¶²aãFêkk°Y{›š8ÚÞN®?H]Xëjk(/+cÍÚõ”•–RTTˆAê"çr¹'\>Þ0L|>/Àí©ñ†ÝnçÀÁC¸]. Ó qï^G €DEÚl6™.'-[Êó/½Ì˯¬fϾ}¸]NšÂ0 # Œ™¦‰ÃaÇép`šÇ.²¦aàt:±Û혦IYi)—^|onÛÎOÿëçÌYتµ­Þž^ò–ëX´`!CüÇýœ'ö3æ44``@2I]M ÷Ü}çq¯ß²l,Z0Ÿ-ongÓæ-¸Ýnj««¨®ªä÷O=Í–­obÐzô(¦‘;“)¿ÝN(âO<Éüùs‰E¢ôõõQVVÊ­·Üœi5¸hÉRƒüê7¿á‡O>É܆‰$¦i2·¡žÛo½»ÝNMm MûšXÿê,›ÅÂùóÎz±ÛíÌ›3€¼¼<*ËËqŒ«Ï²’bêjkØ´y K-Ä›sl€¨1ÎG&”˜¦‰ËåÌœ›´T—ËJ-ÞV_WÇË—óæöüä§ÿImM5Ãá0GÅnÙ3÷æäpɲe´·wðëßü–}Mû±[픕•òÎÛïÍt…™¦Iii e¥ìmÚÏÞ÷0>_ª¼ùÌŸ7—ç_z‰ÛÞö6 òÏê¹™ŽfL¨ª(çûîå†k¯áÀ¡Cmo'OàÏË¥º²’9 ©éŽ……\±|9~ÿØ~ôòòr.¹8†ÇãÁ²,jª«ø«G?ž½{é(,,àOzoîØÁ‚yóp8ø|>–.]F8<¯—PxMû`ŒŸÏËÕW­`Þ¼946î¡»·˲¨®¨`þ Ÿr:ÜuÇíTVV2<<ŒË餪ªŠÿó·_`Ó–- )**¤¨¨`p¿Ï‡ÇíÆaOM;­®©Æçórøð,›êê*êëÉËÍÍ\ ssýÜpýµ,^´€ÆÆ=ôôõáp8¨©®fÞÜ9™²Ü÷]4îÙG`pà´º«¦Â0 \.·ßr3±x|Ìó§±âŠåÄbqV\¹¿ïXý¸Ýn–-[J(4œ¹ äsÝ5+™ÛP?f¬M®ßÏ]wÞIUUv‡—ÓÉe—\BÕç+Ù¶cÁ¡ %%Åøü>BÃ! òó2ahNC=ï~ð\¹ür:Œe·¸åæ©­©É,P—VWSÃÝwÜIKk+e¥e™€\Z\ÌÍ7Þ€×›ÃEË–žö k‘™d¢­æÈfö‘Í=²y/°"84øñLŽÌ.I¯«ljÆbD#‘ÔÌ‚à0Áà½}}lß¶|€’’’S*pº/~x8D("™»ÝJ­âra‘H”¡àPjºì¨Á|¡Pˆp$‚iš™0ŽD‰Æ¢Øív¼99 âv¹p:$ †‚A’‰^¯7³‚f,#Àn·ãv»2·'  GÂX6‹Ý{÷²jõjJJJ¸ÿž»3«¸&“Ibñ8Cƒƒ„#QL#5Õãñœpý‡D"ÁÀà ñx§Ó‰Çí&ˆÅâ8©OüñD"õißé$92Í8a³l  *M­©2¾Ë"}~‡ˆD##­®ÔÔÕ‘rÅãq†‚A¢Ñ(n·;sÞÏ…¾¾>’€Ûå:n|Gz¹ôþ@€¼¼T(H¿žx<ÎÐPD2ÇãÁa·‰D Œ vf^O4£««‹¼¼¼‘–.sä<¤¾&‹´œYÄã l¶Ô9ý\éßoÃ42e_Ñh”áááH˜‚ül¶±ï PTX0c ëèèà¿ø%K—-%?/'ÇËåJ v¶,l6[ækÆþ‘™É“ãýk`0á‘-:²Å€ÄÈ–1£Z@àXÓºÝnÇÏÄ3RâãgC¸&¸ˆ9œãÞð ò5›¦9á'R˲Žk*O&“†AnnjÿX,Æp0HgW×]sõ˜²ÒkKä`Yù‰LT–T9&30ú úNö.éó›?Él’ñÁî\šìü¤ÖYqO¸8]j­–±et8M0M×nYcÆ—¤m·[c~NÄf³‘““sÜtÜãžgä÷–q¿·S}¼ˆÈ…dÆ鬷·»Éñxp8ôõ÷³·© ŸÏ—éÒ³ª«»‹ç_|™â¢B|>GÛۃ뮹zÂOÞ"""³•ÈY4Þ<¾øùÏžïbˆˆˆL{3b!2¹°(€ˆˆˆHÖ×.˜ááa†††ÎgDä,µJ¬ˆÈÉœ×FÇ|·†ˆÌ\Ñhô|ADfó@ü~?ùSXgAD¦?9""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Y§""""Ygœªd2y¾‹ “0 ã”öW}Î<§ZÇQ‘#™Lèí¥·§“áàÐù.ŽLÀíÉ!¿ ~þI/RªÏ™éTêx2 "2#$“Iº:Ú ´¢nÞù.’L ÐßG{ëa"ÑE%å'¼@©>g®ñu|º@DdÚK&“ô÷ö040À¼EËÎwqdþÜ<ü¹yìݵ »ÝIn~Áq!Dõ9³¯ãÓ¥A¨"2í% z{º(­¨>ßE‘)*­¨¦·§‹D"qÜ}ªÏ CºŽO—Z@DdZK&“$“IBÁ!|þ\ Xœ!|þ\ìÛ©¿t+ˆêó‘®ãÓ¥™öt‘š¹&ª;Õ§€ˆˆˆˆœ """’u """’u„*"3ˆÆ\XTŸ³™ˆˆÌ»xaQ}În "2+½ðÒËüسoÁ¡ ÕÕUÜwÏ=Üï=Y+Ãç¿ø% øë¿üXÖžóBóù/~‰?>ÿ–eQ]UÅý÷ÞÃï¸Ó<óQáH„d"Ëå:íò©Ž'¦""³Îßù+lܼ™¿øàø«G%‹²»q>oÎù.šœ†wÞ÷výð‡…¬ý5¾þ/ß$ òþG>ãcÿè‰'9|ä_þâß…’Êh "2«<ûÜó¼¾yÿõ“““s,pÌŸ;÷<–J΄ÝnÇëõâõz¹ûöÛ ð£'ž<+DΙAÎ|ÐÀ÷~ø#>üçï''ÇsÂã% žøŸñ»§ž¦·¯—‹–-ã3ýqÊËÊxäâŽ[oá¹^bßþýÔÕÕòéO|œÅ‹òÙÿýEóÉO²yëV~ýÛßÑÑÑÁòË/ãóŸùùyyD£Q¾ýÝÇX½v]”–”ðçï{˜;n½%ó ñxœï|ÿ<ûÇç sÃõ׳qófþíëÿU••D£Qþý{óü‹/‡yëµ×òñ=ŠÇã>ãs}rgcÈØspÉÅÑ×ßO0Än·NzŽÖoØÀwÿû¤¨°›n|+ýð‡xâ?~Æòê²»ÿž{øô'?~Šçl¶×ñ‰i®ˆÌ¡PˆÃGްlÉâI÷ûÞ~Ì /¿Ä?ÿÃßóäÇa·óK]xÒ~ûÔÓ|ì£á—ÿù$Ë–,áÑO|’Þvã¬^·nÌw ¬^³–›nxë”ÊøÚoðùÏ|š_ÿügTVVðð>ÈÑö£üëWÿ‰'~ð=Ž´´òï=¤>ùWUUòÕü~þä¹ûŽÛùÒ—¿ÂÁC‡2ÇûÖwãÕ ¯ñõþGžøáã¦Áá#G2÷í_ÿƒ‡ŽðÄ÷¿ÇOô}Ž´¶òíï<6¥²NWÝÝ]âñ¸OzŽA>õÙ/p÷wð‡ÿ÷+¾ö•àÆë®àá÷<Äûy/o»é^]õ"ŸþäÇ3?gªã™1’É3Ûi%™L’›—Â}Âáÿñ³Ÿó¿þæo˜ÓÐ@Ey_üüçbÕšu©™Ixðþû¹hÉRŠ ‹øøG%?/—?>ÿ"+ß²‚P(ÌŽ»I&¡§§Ý{÷ríÊ•Ç=Wúƒñèÿ¿ã–[˜7w.ùyù¼ç]‘L&ùÓw=DyY9ÕUÕÜ}Çílys[æ1ï|û}4Ô§ÊùÈŸ¾‡ŠòòÌs‡BaþûW¿æ³ŸþóæÌ¥¬´ŒOŒ †L&appˆÿùÝïùÀŸ½¼¼<Š‹Šù‹þ9/­^}Æçz*3\ÎÊsŒ:‡±XœÝ{öòû>ï}è]S:GDc1®¾ê*|>/ õ ,Z¸ð„utªçl¶×ñdÔ#"³FqQ!---ä.\8á>-­mÄb1ΟŸ¹Íív³té<8ácLÓdÙÒ¥:|§Óɵ+¯bõÚµ,]²˜5ëÖ±âŠåcÆ›LU}]-¡phÌmÁ`0óÿ}}}<ûÜólݶ¾@?=½=„B¡‘×ÒJ<‘`á¼y™ýQÇ?xä‰D‚Ï|á #÷Äâ1‚Á¡S.ëùô³_þ7?ûåcåå<ôà¼ó¾·gîŸìÕ×Õqù¥—ò®‡áš«®âÞ»ïâŠË/?ásís6›ëXDDfÜÜ\ òóY¿á5Ÿ €D¢‰ñx|Ì4N‡eÇétžðØ6ÓÌLÕ¼ù¦yìû?ä#ú «Ö¬áæ)v¿ŒgLxÛ±[ƒÁaþìÃᦷ^ÏþìJKKù«¿ùtæþX5xÑéppíÕ+ùú7¿Í%_„÷­/RXXÀàà¿úõoèëëã™çžgß¾¦Ìý9wÞ~_ùÚ7رk½½}üð'Ofî·,‹?}÷»øöcßãµI$´wt°³±ñœ”÷|8Ù9êà÷O=MgW¡PˆM[¶âv»ñûý”””°ië›=ÚÎððpÖÏÙ…\Çê‚‘YŲ,þý_¿Á/~õkž{ñE¾óøãØ “ºú:ÞqïÝ|òãÉ·¿ûŸú܈Åb¼eù|ó_Å8öÑ“+/¿œo}ç»tuw³lébûÖ7±Ûí™ûoºá>õ¹Ïó¥/|–Úš>ú‘óØÄwœ+—/gÅËÇìó©ÿ%ÿò­oó‰O›ÍÆmo» Ó\ÿþ‡ß‹ËéäëßüGÛ;(ÈÏçáw?Äâ ÎY¹³édçhp`€V­â[ß}ŒàPÚšjþéÿ| çHWη¾u¯®ç]¼Ë.½„oüÓW²zÎ.ä:ž¨ûÉÙ,À>²¹G6àV‡¿1þÉd2³Åãqâñ8ÑXŒh$B("&¢·¯íÛ¶óàƒPRRrî^ˆdMGG¿øÅ/Yºl)ùyyx<9x1‘³ìð‘öîk⺫¯>ßEapp=ñSþ÷ßÿ%Åżãí÷pßÝwïbÉY4SëXDDäýøñïNzuU%ë_~!K¥™ÜÒ%‹ùñ÷¾s¾‹!çÐL­c‘¬S ˆˆÌÉ3ýò ™VTŸ³›Z@DDD$ë@DdFpyr ôŸïbÈ úqyN<Yõ9ó¬ŽOFDD¦=Ã0ÈÍͧ³½í|E¦¨³½ÜÜü ›S}^Òu|º@DdZK¯˜šãÏÅãõÒ¼w·>9Ocƒ~š÷îÆãõ’ãÏ=nÅ[ÕçÌ7¾ŽO—¡ŠÈ´gš&6›È`qIDAT ^!–ÍAgG‡4ü’u.nŸ›Í6áWÄ«>g¶ñu|º@DdÚ3 #óFçÍÍÅíõ’H$INó•gÓ42ßù“þÞŸãöS}ÎXÕñéR‘!}ÑJÿ«)œÓSº‹Å4ÍI¿lPõ9sMµŽOFDDf ]¬f†©^”TŸ3×™4™qÎÆ›ŸLªÏÙI³`DDD$ë@DDD$ë@DDD$ë@DDD$ë@DDD$ë@DDD$ë4 wŠD¢  208H4Åápà÷ùÈñx°Ûí§}ܾþ~¢Ñ(999xÜî³XâÉ%“IBá0ÝÝÝø¼>rsýY{n9= ³L 0À‘–VŽ´¡«»›P8ŒË墤¸ˆùsçQUYÀðð0ñx—Ë…Ã1µPÒ¸g/ÝÝ=Ì›ÛÀ¼¹sÏåËRÁ#ŽÐÓÛˡÇÙݸ‡K/¾ˆ‹/ZvΟ[DDÎŒÈ,³~ÃküöO0§¡'‡žž^š››¹ãÖ[xà÷aonßA À’E‹¨®ªœÒ±_{}#Ûwîäm7Ý•‰Di>p€?<ý,|ñE’É$yy¹ ""3€È,Çéíëã÷O=Í¢E ¸þš«)-)Á4Mâñ8ápŸ×‹Ëåb`p¦ýÍíh§¼¬tÊä÷½;o»•ü‚üsüj «»‡ç^xõ^£¸¸ˆî;¯¬Y{ΟWDDÎY"‹ÑÚv”ž¾>ÊJJ˜;gn—ë¸ý‚Á ¢qϺ{{yýMDÂÊÊʨª¬ ¿¿ŸŽÎnrr õu ‡B¼´ê÷5Q˜ŸOey9ýÖ®{•îž.Z¶ä¸×c3MrrrˆF£Y>›""r¦@f ›ÍFaA÷Þ}O=û,xæÙL¹öê•4ÔבŸŸONNõuµ4Ô×ãr»X~Ù¥\~é¥@j @(bé¢EüÉï ¢¼|òç5M®½z%ïþ“°¬Ô¯[``€£íìmj¢¦ºŠÎÎ.^xùîºý6n¾ñŠ‹  ©®\Åïžzꜞ9?@f™Ë/¹˜…óæ²w_ë7¼Æë›6ñòê5,]´{﹋«®¼ò¤Çp»\”••×-2Ëfa·Û3á`nömßÁàà ÃÃ!÷îÃï÷S_[CáÈVËf£´¤øŒÖ%‘éKd–±Ûíäææ²xÑ"*Ê˹þºkص»‘—_Y͆×^§¸°Ò“ Ã00Mó¸ñ#Såq»°Y6‰$Ñh”®®.r<œNç˜cš¦‰a§õ""2½)€ÌB†a“ã!'ÇCyyåeeìÛ×D€¶£í' gjt°0 ›e#“H$ÎéóŠˆÈô¡ï‚™%’É$±xœH$2æBoš&ùùäxs°,Û˜Û#‘HfÜǹâpØ)/+#ÐÑÕÅÐP0S^…‘ —Z@f‰x"Ao_íGÛq:x<l6“D"Aoo]ÝQ^VŠÍ´áó{ého狼»—Ó‰û|¿‹Ó墡¾‡ÃÎÎ]æPSSÍðð0Í1 Ÿõç‘óOd–‡Ãìܹ‹ï~ÿ‡$âq*++Èõû‰D"lÛ±“Úšjn¹éFæÏ›G4eé¢Eüæ·¿çÏ<ËÁÇY¼p!×_{õY/—ݲ(+)áÖ·ÝÌïþðÛ¶o§¡¾ŽP(ÄÖí;05DD䂤2K¸]©)µ÷¹ÏpäHKê‹è"œo½îÚÔšee†Ýn§¾®Ž~ä/8tø0†a—çÇ0 Š‹‹YyÕ[¨«­=î9.˜GIqåe˜¦™Ú÷-+¨©®³_UU%ñd‚â¢" 5Eøm7ÝHmM5‡!ŽãvsÉųê•Õ']`Ì4M ò¹þ𫩝;¾\""2ý(€ÌæÈÂ]s(-)a($‹c³Ùðzsðy½™©²†aàt:YºxÕÕU$âqrrrR¤¨«Þ²‚œ ºcæÏ›G4ÁëõbE…E\õ–+뺩ª¬L-Åîpdž/×ïgñ¢ETWU‰DI&ìÚÝH^^.çñKÆmùùù\³r%>oÎY:c""r.)€Ì2v»üü|òóOþ…q999™ÕFÓÜn÷ Ç‚äçåÛ×…Û]vÜ~>¯Ÿ×;æ¶d2IŽÇCŽÇ@?û›PXX@^^î¤å4 —ÓIeÅä‹¢‰ˆÈô¡"ç]2™äHK+áal¦ Ã0èèì`_S×^½’²’âó]D9Ë@伋Åã¼²f-͇ár8°Û-ZÛÚp»Ý\´té9_—DDD²ODÎ;»eqÿ½w'HMz1ˆ'â¸=îÓ^qUDD¦/™ÎÅ#""2}飥ˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆdˆˆˆˆd]Vˆac6¹°èo\D¦êœÑo>½é JäÂr¢¿é“½ˆÈìtN[@F¿!¥6MÓ0õF$r2 Ó01Ms¿‘´¬tÁŒn’5M3³‰È…eôß·ºbDd2ÖÙ>àøO<£ƒ‡ašØl©mË–­Øívb±‰D‚d"A< ™L’L&ÏvñDä Œ6› c$lX–E4Íüm#ï™ ÂØ±! %"rÖÈx†1¶ûÅf³áp8(,,¢«»‹p(D$%‹ÇˆÅb$“ÉT  ""ç×èéPaY–ÍÂn·ãpØqº\áp8°ÙlãZAÎó ‘i' dlø°l.—‹ššjÂá¡pˆh$B8&‹§ZC’ ‰ ð!2]¤CHz—eYX– §Ó‰ÝáÀåtát:p¹\X6ë¸""2ÚY †aŒ ™O?#Í´6›-ÕDkY8ŽL7K: Äb1âñ8‰D‚DB­"Óɱ2ê…eaÙí8ì{ªõòFºbFÈ BˆB‰ÈìvÎZ@Æ :M$Ƽa9FZ7ÒûÙl&1ËN,ž Éd’¤Z@D¦•L7ÌH H·hZ–m¤ÆÃéÄa·cYÇZ@ÌQÝ6 "’–½.› kÜØ JÒ­ñx"3DD¦3@Ž}¨°Ûí©–M»ûH±, ÓfSð‘ óÇÖ`äÍ*}›aÄm6Ë">2ø4Ó¢¨"ÓÊøn¶‘paŒj³™c‡ÍfÓš?"rBç´ Æ4Íã„eóaš&ñx+n#nÙÍ~ASpE¦«ô´Úñ-!éÖôϦi;D-!"2Ê9  6;F¬‘µ@RoRÇ&2-ZDdú¿ž‡9fùÈÚ Æ¸u@´þ‡ˆŒ“Õi¸†aŒ„ ƒ„af‚ˆÂ‡ÈÌ2Q<´ªˆL本„šéŸG¿ù¤ß”L3I"a4M’IÆv»(€ˆLo£Çƒ`dœ¨ÅcôØ‘cW ™íÎiL:|¤ƒÈøŽÑaet«‡Z@D¦·‰ÂD:€¤ž¨õCÁCDÒ²2 &mtIÿ¿ˆÈÌs¢2Qk‡ˆÈDÎi6N´Ïh "3ÃDÓ“…-+ƒPal°˜èMêdAED¦§“ýÍêoZD&’µ.˜“µtèMJä ¿e™Š¬ŽMoR"""³—9ÅýÆÌеˆˆˆŸ ¦4˜ód$9îçäO$"""³[‚c9!mÒ 2Y™(|ŒÞDDDD&Ë'Ì Sé‚I§šÄ¨-~ÚÅ‘ Iœ±aJ½%' ‰Qÿ¦GÝ0"""’2:Œ“f…‰fÁŒoB=ö#Ä€˜'Çû1À1²ÙGŽe#jL@Ó\DDDf¾Ñ½ é"#[ldBÆgˆãºbN6 w|øH?ñ€kdK‡‹c!Ä`ê3lDDDdúJ‡ŠL#ÇÂGhdK‰BÈ„N@F'–‰ROº•ƒQ÷ÛP ˆˆˆÈ…f|ˆs,€¤·(c[AF‡ ƒÈd- ' £ÃÅèÛG‘ ÁD½!QÆvÃL@&t¢1 ƨŸÓOh06X¤ïÝ*b›`?™¹F·d¤Fº+&:n?dô1Ƙ¬$=zÕ`lI(}ÛD]/ """މzEF ™(|¤÷Ðdc@Fw³ãî=et·Kz\ˆ Šˆˆ\8N´,Çè 2zêèàqÊc@ÒOdNp tÝê1¾õC­ """3ßDËrL´@é)-F6Y ë~}{úàã»\Ôõ"""ra¿äúøÐ1¾ëå„QOF‡ŠÑÝ+…ŽñDaDDDdæ›è»áFÿ<þËjO>`j!a|°0'¸]ÁCDDäÂ6Ѭ–Ñ!c¢á'4Õ°p¢qï!""2û$Çý{²ÛsºÁA-"""³Û¤ë|ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÈ…ïÿ³­×äHIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/drag_and_drop.png0000664000000000000000000002630015074673150022734 0ustar00rootroot‰PNG  IHDR­G¼M¿sBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timedom 25 dic 2022 22:26:49Hÿh IDATxœíÝyœMõãÇñ÷½3ƒ1–ÌØ—±‡Šoýú¶)dK}‘Ð××7%iÑ·R_¾‘(!¢UÈÒW–ŠK}#b6ÆØiÆlwæÞß3sݹî,Ÿ13w–׳Çç1wÎ=çs>çœ;λóùÜs$€2ÈRˆõtÝÀœ#›×WåjNò·Ÿîï ð>‡<‡ÛO#ù9É»‡×ß]_[óÓ P ì?]ƒ„{¨È.ddË$@¸_q°ºüô|L EZÆO÷ a÷0ÝõgŽ|ó¸rOW¬n¯­nÓ¹€÷ùèr`ÈüiWú¹:»ÐkˆÈË÷« î!ÁG—„kðËCÝ pÙ”58d–4e ®W%ríÒÈí „{xp->º|%U“,©²$ÿ<Ô _ª¤DIq’NK:—1ÍGé!"Méçz×.Ìs¶!"¯'y÷ðà›±b_IU%5Z¿î¿Ãš5iÒMU‘ƒo`PlXäC>rä¿wÝÝm®¤IuùBAªÛvå"§½EYÇ8¸^mÈ,!’ZF=÷íš!„J&‹Tå»o× Qú ÊéòøÆÌoSæ(»á~¯÷ñ!Íš5ézµÞ“q.Ñåó{æ÷û=]!§oa¸wcdVî')ÐbµT–£ÀžÉŠ˜Åj©¬ô1~º<ö!Méç}‡²Þl*‹¼ÜÂýÞ¾’*:ì ßÕ är8I•µû"³äøUNOÂý™îc 2KÁ=x‹ë¹Ý} „ëÏ,§ýœQº_}píÊà9”®çvO¦ð(». Oëv»…5×(\Máià¤ÇqÙua¸ß}Ò/£”sò¥A9—âzWJy~r§$x…Rîéq/+<2R’d±XT½Z5Õ­][wßq«þzó_¼Üº‚³}ç.Mzgºzà>õÿÛ}W¼_\÷ƒk»Ü}¾`Ž*”/_Ä-Ê›~Cÿ!ÿ ´àƒÞn à5ù\€@Iòé$«Õ¢˜ØXýòÛoÚ÷ë¯ÚúÓN{f”·›V r{þnqÝ7¶o'?¿¬ÿY¬ÖbÿïLqoP˜®â :( Ò?§Oücˆ*V¬(I:|äˆÞ|{º~úy—6l٢ηþÕ› , Žl^gVüöCz»Fަ*•*eû~ñUÜÛ‡Ò¤ÏCƒuMËæzaôHU©’~#è?ãã5ùúõ·ƒZþéÇEÚº0Pæ4kÒDƒôÓ´™³µný&牳ÿÐáº¹Ó ®^]ë¾ß¢š5ƒõÂè‘úô«åÚûË/:{V­¬›;uÔÀÿ¦r~éÏKLJÒG ëç°½²Z¬ºëŽ[µòÛµê}O7 xðþ,ëþóÏ?s­/³þ*hûŽ]²;ìêÖù=Ô÷r]‰‰‰š»p‰vïÙ+»CjP¯N¡î‡·&¼(»Ý®¥+Vi˶uúìYÕ«[Wýí>uhw³ÎþC‡«ë]w*..N»vïU@¥õéyºv¾Ã¸}’ôŸwgjÛO;4x`?Ý׳»bOÒ¨gÇ«jÕ*zãåqZ¾ê¿¹îË›:Þ  å+è§ŸwËjµª{—ÎêxC{}ôñ':t$\5ªWÓ?}D­[¶È÷6$%'ë“ϾÒÎ]aº”˜ V-Zhتœ¯í<©_¯®<¤—'NÒë/Ž•ÅbÑ„‰“¥zuÌÿ ¸Zùÿ:¦ƒB)%“ÛôNÚI’¢cb²Ì»é‡íúrùJTTÃúõUί¼vîSÍÝÔñFÙÓìZ±ê[}µl¥s¹©3fiý÷[T-0P-š6Ѳ•k”””ìq½y©O’6nÞª]aûT¿nÅÅÅëó¯Wh÷žýÎy¦¼7K6mQP` Zµh®ßñ¸¾‚ÚrH.øD‹¿X*µ»îZ Ðë“§è·‡²,»bÕ·:|$\×¶i¥³gÏ郹 ´ãç°Û5söÓYÖ|·ArHÃ?¬Êúbé ?Qsæ/’-5U#ÿ9LU+WÍÓ¾ü~Ë6íÙÿ«êÕ­£ó.hÑg_êé±/)ÅfSõ @EEÓÛᆵ”[Þ·ÁmþgÚ{ZóÝzµhÞTÛ·Sؾýzó?ÓdO³{ÿo€RjÊ«ãžUíZ!ŠŒ:¦—ߘ¤—ߘ¤ðÈ(…Ô¨¡WÆÉÝùÄ”Iþþþò÷÷Wbb’ÒÒÒäãã#I²Z­zó•Õ¼icç¼½7ÍùúDì)=>æyíÞ·OúÞ¯˜ØXý¶GÁ5ªëí7^•Ö¬Û ç/ô¸Þ ÊçX_¦€€ŠzÊ¿åë뫯W¬ÒÂϿԯ¿P‡ë¯SLl¬v…íͲε7郹ó m?œ9{Nßmø^õëÕÕ”‰ÿ’Ö}¿YïÏ™§e«Ö¨UËæÎ:ƒ«jÚ[¯ËÇÇG[Ú¡·§ÏÔ·ëÖ«Ó í³mÇO»vgùÝêã«îwwVÕªU4tÐMŸ5G¯¾5Y‘ÑÇÔ£ëݺ®u+I9×}9sÊ¿eµZµä«¯õÅ×+ÔùÖ¿êñ •$|îEÑñ˜ mØÀx£¢´{ï~uh×Vcž!IJNIÑö?+&6Ö+ÿgˆÒ©zµjzã¥ôÒo)2ú˜$)¸Fu½öÒX…Ô¨Qäí¹ŠA”W[€"æÈø/SJJŠ’’’T«f°¬>Vç{þþþjÖ44˼Öêµëuø£º÷§‡âþŒ—CE‹‘$]צ•³žÀªU<®3/õe²Z}äãë#‡jÖ¼‰$éâŸqrÈ¡¨cǯXgåJY¶´ ÷CDt´ìv»Ú]w­s¾[nê¤÷çÌSôñãYêôóõsÎÓ±C;Y,?›c»~øž*»ÈœÿŽ[ÿO[¶ÿ¨½ûUíZ55¨_ç{yÝ—«E9Ô¼Iz ²øXœó4kÒDÑÇcôg|œsZ^·Á!‡ŽOÿ ìÞ³O} Îò~\||ŽÛ ˜òññU9¿rÎßý|ýäççç•ÏW P&íÿßor8jX¿AŽóÅÄÆjÂÄÉ Ö“ÃU½zu5|Ôçû¶ÔTI’… yZonõyâ듵§1-Ín´Îœäu?dvɤÙӜӒ“Sd±XrüªeRrúr®ÿàåGõ ÀŒWY¬é÷·ÉϾ´Z¯ìµõñɹ'7·m¨”|:´k«¡÷Ïòž7þ¯¥×ù õÊÄI:v<ÆyeëXLŒ&Lœ¬×^« ÀªEÚÆ@PJwÉä2íĉSš·ðSY­V=xÿ½9Îûûï(ÅfS‡ëÛªM«kT¥R%92ŸBëêÔ®%IÚ½g¿l}艉‰ëÊK}ÙµÃuZZ5¯\gBR¶ë,ˆýP¿nmIÒ®°}αa{÷Éáp¨QƒúY–MLLTÂ¥É!íÛÿ¿Œ€R7Ïír/{öý¢ ›·ªZµ ˆ=¥/–®Èÿ¾TÓL¶A’Ý‘>¾¡AÝ:²Z­:tèU©TYukÕv?_?ïÿ PJMy}òTgxxí¥±zí¥±ªW§ŽŽÅÄèõISò_w>qeÂì‹äãã£S§Ïèð‘£JMMÕàýÚ ~ŽËÕª™~²^÷ýfIÒGÕšqÕA’BÔWËæÍuðÐ!=ûÒ¿Ô¨a}íÜ–ïúò¢Qƒúº¦E3øýðåuîÊ~®ò»Ô«§v×]«=ûѳ/¾¢Æ iÇî0ùùù©ï}½³Ìwé’Æ¼ôªZ4i¢{öÊb±¨OÏî9ÖÿþœùWÜbÔ?‡Éf³éý9óT¥Jýçµ záÕ7´lÕýßM d_f'·m¨Z¹ŠNž>­%_.Õ}½z¨ëwèÛõ4nºý–›uæì9]JLÔ³#GH{I ˆThÃzyìUM¿ÚðÚKcõú¤) Œ*òö\ÅC±ŠA£Pr-é¶lûQ›·n×Å‹uc»ëõöÄWÕûž.çuvM‹¦ê{_oùøøhãæ\½šË@ºôyžúquìÐN§ÏžÕ‘£úË <Ö•×ú®\öʺžêIuº¡½Îœ;§ðˆ=9|¨ªy\gAìÉ¡çFP—η+1)Y»÷íS‹fM5éÕ3®ˆ\^¶r@€j…kÇî0Õ ®¡Ç<¥fMBsl׎]»µõÇYJš=Mó>Y¢³çÎkpÿ¾ªTUd€ìv»fΙ§Í_žÌyžÜ¶að€~ ªZUÿݰI‘Q6x€õ{@V«¾^¹Z‡Žü!ÿ ååpسÙn ż,[<_Sßü—‚ªVqN ªZESßü—–-žuç§§l¹>u3óþ¥¢¤J’:ýñûÿ¦æ{­@)¶vý÷š=¡{t°ºt¾ÝÛÍ)Rþþ˜ªTª¬YïþÇÛMÉ·Ò° €‰¦-Z?#i‡¤xI ’3Š-£¤êò31œx,7p•ÒÒÒ²ü¾s÷IRƒõ¼Ñ(ù‘ÿ«@©²þû-Z¿i‹š7m¬¨èýïàAµmÓZ-›6-»'¥a»KÃ6…ˆgaW©JåJ²ÙRµaó ¬RUݻܥÞ¯²ý7R¶½4lPxò?âௌ „kÚ²M¾Æ@ð8o`Œ1Àc €1¾Æ Œ €1QcW1ˆ’@YE0–ï+ǣ ² Éw€èô×ÎÙP‚Ð…Œ €±«¸%`îhx¸V¬Z­»Â{ò¤$©VÍšêxC{ÝÛ³‡‡†z¹…¥—ÍfÓ‡ÍךïÖéìÙ³W¼_£FuuïÚUÿ:X~~~^h!€’„"a³Ù4í½™ZöÍJÙíYè¦ðˆ…GDè˯—ëo}zkÔã#8‚9óhѧŸeûþ™3gµpñY$>¬è D*µ"))I‰‰‰räã~þüå_Ñ¿ZU6Ùl6~~œv…íQùråtß½½Ô¥ó mÔHRz€X»~ƒ–³J_~½\Qš:ù-BD[óÝw’¤93gèÚÖ­¯xÿ¯¿jø£´zíZ€\•Ú‘˜˜¨ÀªUe±š óp8ºpá¢M{o¦v…íQ­š55uÒ›ÎnФ¤$IR«k®Q«k®Q¯îÝ5fÜxý¦éÌÒ˜Q#½ÙìRçÌ™ôn OáA’®kÓFm¯k#‹ÅR”ÍPB•ÚA”)))Ù†‡„„K:pðJNN¾â=‹Åâq:òçhx¸–}³Rå˕˒““õÀÀAê;ðçþnÚ¤±¦üûM•+WNK—­PxD„[^6Íž1]³¦¿ëíf(Jí›Í–í{‘‘ኋ‹Wtt¤š6mn´,̬XµZv»]÷ÝÛ+O$›6i¬>½{ꋯ¾Ö7«×è©'/‚V–] ¬_¥ö „-ÕæñyΟW\Ü%…††êüùóŠó¼, ÄΟwK’ºÞ•õÆcåË—×Ò%Ÿè«%‹T¾|ù,ïuíœ>eQx2Vz Òå•sç\Ä-PÜ•Ú+i©69$¹öæ:E‹’ÕjQppMEFF***J­Zµ¾bYŒS§NI’6h”ezß+úXŒ$é§Í³¼×(4}Þ“±±…ݼ2•ò«ô^ðÐ qæÌi%&&f™§óçÏåº, Ö—‹?ÉþÍÌ+G æ+P5jT—” 2åe`¥ë|©Ì»Ý®ãÇ9_ÿñÇ!çýŽEGgùº'¢à„„„H’""óþðµððIRÍš5 £IeV÷®]%IߥŽååÖ(éÊL€8y2V)))Îßk×®ã|Ý aC%$\Ò¥Kñ:îü7:Bþuêxƒ$iíú y^fí† Y–EÁøÇÐÁzdàÕ¨Q¯j¸je&@ÄÅe,ùÛoÿs¾öññQ\ÜŸŠWDäQ5nÒ´HÚXÜÛ³‡¬V«–³J9êœÞwà ¯9¢+WËjµªwîEÚÖÒÎÏÏO¦UK¿ä«š®Z©Dé š4iªÔlº&RRRdµX¡fÍ[ªj•ªEÑÄ2!´Q#ý­Oo}ùõr7^Sþý¦š6i¬//ºbÞÃGŽhÌØñJIIQ¿îWhÆ^h1 /Jm€°ÛÓd³ÙT®\9IéW|||<Χ£áájÙ²•«e3Ë„QPDD”~ Ó£=®>½{ªËwªqhcIÒÑð£Z»aƒV¬\­””uìÐA#G<æåV— 5jT×™3gµÿ×_&]íÿ%}ÀepEÝ4Åœ§ŽPkFñ•ä—Qü3JEI•$uJ¸?µ¨™‘‘Šˆ8ª´´´\çõññQÛ¶íHx(,6›MÓ?˜¥¥ËVd;ÆÄÇÇGÜw¯FŽxL¾¾¥6Û+3?œ«…‹—ä:߇ê±ü½Z ¨U ¨ôŒ¤’â%%HJÌ(¶Œ’*ÉžQœJm€@ñ¡oV¯ÑŽŸw+öä IR­šµÕ©ã êÝ£;ÝEÌf³iÎüµfíZ_Õ ®QC=ºuÕ߇<Â(RŠŒå7@”Úoa€ÂC€ÆÀ#@c`ŒŒ €10Vâ8ðòk¯«zµjzúÉ'$IÉ))rØíªP¡B‘¶có[õÞ¬Ùê÷Àzà¾{‹tÝÞæíc`·ÛõÅÒeZ»~ƒ"£"T½Z5=pßýê÷ÀýE²þâÄÛÇâRB‚¾Z¶\7mÖ±ècòÐ-7ߤ‘ W@@@‘´€w”¸áîãE‹}ü˜^åå"YßÁßiúÌs"6Û‡B•5E} Öoܤ]a{ôäcÃU§v-íØù³&¿ó®jT¯¦ÎwÜ^$m(®ŠúX$%%éxÌ =õÄãjP¯žŽÇœÐÛÓÞÕä©Óô¯—_,’6ðŽ ŠÚÊ5ßêŽÛnSŸ^=4fìxo7§LºëÎÛÕå®;¿÷éÝKaûöé‡m?–ùQÔªW«¦ñÏqþ^£Fu=7ú)~~œ[ (”è±èÓÏ4Ñ'’¤›¶¨O¯žznôS²Ùlš5ç#mØ´YIÉɺí–[ôÔ«bÅô˺C‡Ð_o¹Y?lÝ®ÈèH…6 Õó£ŸÖž}ûµbå*:uJ:´×øçÆ\ñˆïçF?UäÛYœyãX­WÝ ÔÙsç ƒ‹1o O““U·nÝBÝVÞW¢Qz¨¿†zXwÝy»¶m\ç<¹O™þž"£iþì´pîlÅÄÄèýÙ³³,»kw˜Æ??F_-Y¬ºujkÈðÇtòÔIM™ô¦æÏ™­cÇc4sÎG^ت’¥¸ƒý¿üO­Z¶(èÍ+Q¼y,ìv»âããµcçÏš6}†ôï[˜›  (Ñ“K úfÕj òˆ‚‚¬áÆjóÖmYæëÖån5kÚTÕ‚‚4°_?9 ì×Ouj×VƒúõÔëžnÚ¿ÿ/mEÉVÔÇ`ËÖmŠŠŽÖ½={Ö&•XEu,æ-\¤»zôÖSÏUHp°Z·¼¦°7 €—•è. O¢¢£e·Û5î• ²È"IJMKUBB|¶Ë4jÔP’””œìœÚP ‰‰…ÛØRª(Á™3g5iÊ;=êIFý{PTÇbØÁzô‘A:«Ï¾Zª!Ækñ‚yªU«fm €â¦ÔˆJ•%IófÍTµ  <-cñ8ÍÓTäEQƒä”}ùÝØ¡ƒzÞÓÍ´™eBQþ=X­VÕ­SGcFÔÞ}¿è»õÈ€‡Lš  )]©©©Î×µk…(Àß_[·m÷b‹Êž¢>iiizqÂkò¯PA㟓ûeHqø{(WÎOþå‹öÞ,ŠV‰!!ÁÚ³ïÅÆžTbb¢|}}5p@½ÿá\íܽ[v»]'OÒß÷vSK­¢>v»]¯N|S1'Nè_/WZZš•˜˜(‡ÃQ ë(©ŠúXìÞ³WÓgÎRØÞ}Š=©Ý{öêíiïêØ±ãºíÖ[ dЧß…qO—»µý§0t¨Ú]ßNSÞš¨¡ƒV…òåõλ3{ê´ªiÐCýtM‹²=J¿°õ1غýG­Ûð½$©ÇýYGû/ÿüÓ2Ýï^ÔÇ"$8D6[Š&OyG±§N) @×µi¥Y3¦)$8¸¶@qå©cÓšQ|%ùeÿŒRQR%I.ÅO-ªF€ÂQ1 Ò3’vHŠ—” )1£Ø2Jª${Fq*ñ] è €10F€ÆÀË÷} ¢Âÿ(Èv€$ߢAhÓ‚l(AèÂÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €1 Õ˯½®¿Üv§þrÛºùŽ»ÔwàÃ÷òýq䨷›V¬<4øQ-\¼Äù{rJŠ’’’¼Ø¢‚oƒ7¶Én·kÊôêÚ«ú=Ò3¦©~½zÚ¸i“üþ{‘¶(|½Ý”~åüü I TÛëÚ¨VÍM™>C7uºQ•*Uòr ½ï±üÝÛM(•¢¢Ž©U‹ª^½ºsÚ§ x¯A@)B€€W<ô`_}úÅWÚ²m»ºwí¢¡ÃGèÁîךo×ê·ô毩}Ûë4óÃ9Úº}»N>«š!ÁúÈ ÝÓång=iiišýÑ|}·~ƒuû­·*lï½3y’êÕ­“e?íÜ©Ùsç+<2R5ªWӷ߮LJ“”~©{ѧŸiõ·ÿÕ¹ótݵmôÜÓ£T»V-Ié—£ÿzËÍúaëvEFG*´Q¨žý´öìÛ¯+WéÔ©SêС½Æ?7F’$›Í¦Ys>Ò†M›•”œ¬Ûn¹EO=ñ¸*V¬pÅþ:|„î»·—z÷è®EŸ~¦ù‹>‘$mÜ´E}zõÔs£ŸÊµ¾ü´1;ùiÃÜkÓ–ôñœÙòññQBB’ú?2XÇ Õùó<Ö—“¼÷ÏL§:8—ÿ÷ÛSµbÕjIÒ·ëÖ©q£FZ4oކ¡îï£ݺz\onû9§Ï‘»°°½Z¾rµÂ#"T¯N=ûôSj{]›<­'»í3ù\…‰. xEùråÔ´q¨¢£9§M>C]»Þ¥ÙïÏPÛ6­åçç§zuëjÒ¯kÉ‚Ôãžnzý­IŠŒŽv.óþì9úiçÏúÏ[ohÁœY²X-Š>vüŠõÅÅÅk싯¨W÷{´ò«/4yâëºãÖ[œïÏ]°P7mÖ[¯ýKÏ™¥r~~zâé1²ÙlÎyvíÓøçÇè«%‹U·Nm þ˜Nž:©)“ÞÔü9³uìxŒfÎùÈ9ÿ”éï)2ú˜æÏþ@ çÎVLLŒÞŸ=¢ö$0 IDAT;×}3è¡þ:èaÝuçíÚ¶qóD›—úLÛXm÷ªqh¨êÖ©£Á¨NíZúíÀAIRrr²–.[®ž{FÍš4QíZµ4zä×uúÌiÙRSuóMT¹r%5 Õ5-[J’RRR´äó/4nÌh5iœ¾® ãÇéÒ¥KúaÛÎ:ºu¹[Íš6Uµ  ì×O‡CûõSÚµÕ ~=õº§›öïÿE’t)!A߬Z­aCQPP B‚ƒ5|ØPmÞº-_û*¯õ™´± Ûàçç§±cÆhîüÚþãOZ³vÆ?÷l¾Ö•×câé3s5rÛÆœ>Gžôêq®iÑBAA<ð!=wNÇŽÏóñtß¾‚þ\Wƒ. xÍé³gtK󛜿—/_îŠy.\¸ ïÖoÔ¾_ÕÅ‹uîü9%gŒä9qBiv»Z4kæœß’ͺ5l¨×_¯C†êÿnºI½{öÐíÛK’ŽŸˆUjjj–AŒþþþjݺ•"¢"=×ר¡$))9Ù9-4´¡%IQÑѲÛí÷ÊY2Z•š–ª„„øÜv‹Gù©/·6F®o{­îî|§žÿ’^?V5jTÏ®ºåõ˜xúÌ\ܶ1§ÏQnjת%%$$æùxºo_A®€«A€€W$§¤è£ázdà€lçIHHÒßG<©;o»UÆ<¢š55ú¹±Î÷SSSe·Ûe·Ûeµæ|1ÍjµjÆ;o+lï>­þö¿÷â+êо&O|]¶”dÙív¥¥¥e©§œŸŸÊ—/ï±>OAÅâ2µR@eIÒ¼Y3U-((ǶåE~êË­…Õ†ºuëÈn·«|¹ü_ÈÏ1)¹mcNŸ£¼°XyZO~Û%º0àŸù•êÖ©£Ž.ƒÞÜ<ô».\¼¨'®ÐFàï/‹Ëù¯Nݺ’¤½—äÛ_ßV/¿0VsfÎЖ­ÛtúÌÕ­W/½ž_.×c·Ûuð÷Cjj¸eéj× Q€¿¿¶nÛž¯å¥ô€TõE"¢¢´hñ§õøcz{Ú»ŠÏúÆ®õå¤0ŽI^äu?{úÆz j9 0 Pèl¶T%&&êÒ¥KúíÀMñž>_ºL/<;ZKöÿG\½z5]ºtI_/ÿF.\ÐÚõôÇá#Î÷üýÕ£[WMš2U¿8>Òá'ëú3.N«¾ý¯NŸ9£¤¤$…íÝ/U©REþþêÕ½»&OyGÔ¹óçõÎŒ÷¨Ž7Þ¯möõõÕÀýõþ‡sµs÷nÙívœ· @Ú`·ÛõÆ¿'ëáý5 ßƒº¦eKMŸ9+ÛúrZa“ìT­ZU'NÄÊápäº9}ŽLä÷xæe¹q/OТO?3߀!º0Pè–._¡¥ËWÈÏÏO6TÛk[kÉ‚T5—tÖ¯¯'®ç/Ðsçªã Ô±c֓ǘ§FjÚ{3õ̸åã㣮wu–$Y­YƒI\\œ6nÞ¢÷g¨„K jP¿¾Þzm‚Ê—Kïc~æ©'õþìõüK¯(55U:Ü ioOÊ1àäfè ‡U¡|y½óî Åž:­jAAôP?]Ó¢E®ËÞÓånmÿi‡ ªv×·Ó”·&^U}Ùù3.NÕ«y¾nچş¡„„D x°¯$éÙ§GjÀ¡êrWgÝоÇúrZaOzðMšòŽŽFDhү帹}ŽLä÷xæ´œÝnW̉X…„çwwyæé/ÑšQ|%ùeÿŒRQR%I.ÅO-ªFyuöÜ9õ¼¿¯6}÷m¾þQ/kºô¼W_›ç€¥mý¤Š•ž‘´CR¼¤I‰Å–QR%Ù3Š](U>¬zukò æÄ ÙRSÕ¶M›2¹~W‡. ”hQQŠŠŠV‡v×ë̹sš9{®öïïíf•ýý5åßoªœ—–·×àê P¢ÅÇÅkþ¢Åzåõ‰ ®¡ûï½W}zõôv³J„ÀÀ@µ¿>ç[Z—æõ¸:”hmZ·ÒüÙ3½Ý (sŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀ#@c`ŒŒ €10F€ÆÀËk€p¸ýn/膯p?§»Ÿó=Ê-@8Ü^;<¬”lv]>ÏgÊ1Hä <…×J¾œÎñÙžïóÒ…‘™Jì.%-ßÍÅIš²žãóÔÛ[€°»ü̬0MtcPZ¸žÛ]ÃCŽçz_ÓÜ/a¸Ž}H“”*)µb@¥‘’Êe¿Œº|”J¬’,ùßP@\{2Ïã6I)%5£¸†÷ pEW†§á¾R×ð¹âÝ’*d”Ìá«Ë!Â"¾" @q œt9<$e”Ìá)Dx”]€pMžRKæU¹¼ï#®@PܸŸËÓt9@d›²^…p ƒDNW ² ®áÀuºk€°ˆ@qà©7Á¦¬Ý9²aqy¹B‹²ƒÌ÷\¯Jøx˜xë•„Ì€Ù•as+îc!\ëÈ"§+™£/-Ê"2+Êœæ©ë‚ð@ñá©WÁuL„§ð9¯G9pí¦°¸½ç:õÛ"s\((>²»-ƒkpDéŒÇ@d®Èê¡¢ÌázÕÁýêW!ð>O·eðtƒH£›IåtBºÜ}á:=³r÷. º.(ÞÜoYíÜ».²H™Û ß5¸vOx î‚0€÷yz¶•ëk÷‡e椼ä݃ÕÃt‚Å›§oU¸†Oò•ד}vãï@Éãpû™Ûô+ä÷ÄÏJ¶<=¶ 4ûŒ½V9rÈ×IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/extended_example.png0000664000000000000000000001246115074673150023467 0ustar00rootroot‰PNG  IHDRàdŸ &tEXtCreation Timejue 08 dic 2022 22:05:23\¡õ ‘IDATxœíy|TÕ݇Ÿ™ÉdO&!@ÂBÂ’«ÔµÖJ‘M‘"U¡**Ö¥Õ¾no©U,¸Ö÷EË&Yñ-¥ YT [öldß™„L ™™÷›™ÌLf2“ $!9Ÿó¹÷žý^òß9çžs@ @ n8²›$O » ¿ž™]±ØÊCQГ°%¼ ÒY‘X¦“9&ÜlX Lï`˜C´WÖ„&kãÜÙr‚î€5±éÛ8·–®MÚ# KaÉLœÜâÚ–‚› K±™:ŵe|»8*k¢3Ïš"ô¬‰OgÃYŠÓ4½M\¨„-‹§09*€>@_ÀpkÎ[Pp3c*¤&à* Êj@Ûìt&GÓ´2ìˆÐž-Åg°pѹÞ@ø®±ó&Mœ0þè…à=z½N_}:þÜöyóçï2+Hâ”Ñ"BƒíŠÐžP,›œ¦ÂS}&Mš4ù«Ømkd2TNߘ@p“¡‡šYsæ>›p¨‘„h°ŠÖš¤­hK€¦ÖÏ`ù\š+à;qâÄÛöìÜö¹^ïPSV èQÈ5Ý?çÁE‰‰‰'€Zà’›0ï‚ Ú 5ËçŠÔÇ“{1#„åôfdÕ¡Ã"‰H}Dƒ­YÂVÈmåjqn¡¡éÙoÛÖ/æ"Ä'èõèý·|±é¤H%’F˜¿ÆÎÞ42Ó¦§Éòy#r.fì‡ë/Üäèuºª¡#Ò ’%4ô -eÌh«ïfmäÓ D™Lïw}§¥ 7'2¹ÜÉ)1Œ‘cg$ÔÑ÷€–ôD'^5zà‰yÔ0!¥M±€–t\…ñÌp¥E¦4¸v Â°Õ U\—* =SmXNÉ´‰5 hm9‘¥å×y]¢@p³c:=Ó–øZYBG¦¢Y›x­úÌ0Ÿµ Vië= µw¦™÷ ö:Lìî84 fþ•ÕÕÄîŽã‡'ʧº¦†ØÝqÿ)ÞèwìøIbwÇ¡®«kw½NžŽ'vw‰É©fþYÙ9ìýö€Y9š†bwÇqà»Ãí.Ë”´Ì,bwÇ‘•k3Î¥Â"bwÇ‘”šÖ¡²n2,õaM?­°×4$6ÍDȬ-Žê‰î›ƒß±}WW43ÿŠÊ*¶ïŠãû§ʧ²ª†í»â8~ê'£ßѳ}WêÚÚv׫¢²ší»âø×þƒfþ_ïû† _laÍú hu:£rZ:ÛwÅq17¿CÏ#-=“í»âÈÊɱçRaÛwÅ‘˜’Úåÿåpr-¬#ƒ0–5Ÿwõ-wòãµê×Þç`ß™<$36 €´Œ £Ÿ^¯#!9€ººz²²sŒaÉiéÄDGÝ çq=žÏws,ä·ßA­¾lôS×Õ²tùJæ,XØÁgbó‹6qvu¯i‚¶—ŠÊ*’R¸¢©'røp†……¶;â’2RÒÒhh¸Êðˆ0"† k'$8˜~}(¯¨¤¤¬Œ þýÉ¿TÈåËj† H^~ç@Jj:r¹œèÈQÆËWȹ IÌ`6×®]#+;‡ˆaCñòô½d9ÿúÑÿPsYmÌodD8o½ñ*îîn¤§g»+ŽÔ´ .$%0tÐ@«uþñä)>þl=6ï«»ðÖëÿÅÒwÞ%/¿€?¿³ ™LFnþ%ú÷íË›¯ÿñzÔ·]Bˈä­¿¾×fx]]=ÿ»~#^žž|°òm oÿõ=¶}µ‡_Þs·Ce³aóVúðÒsKhllä£5gßÿpˤ Œ‰Š4‹o`jFwÝq+ ÉÉøúú2nL4a¡ƒÉÈÊ¢¾¾žìÜ|šššˆ‰ @SS¶+õ^yñw aÝ_’”’Æž½ûøÍ¼edfçðÄcà¯òeDD8Ù¹yfuh¸z•µÿØ‚^¯ç•Ÿc`È6Çîä̹ ÝsgЧï,}Cá¥úõ `ÙÒ×èß·o§×Çiê»ÛOÛ fÖôixz¸¯+«ª9xø¨¡÷EÆÅ,êêê ëÏ÷Ç¥‘Q/O/´Ú2 ‹ŠpQHÚß}ó¿“§Ï Õjy`Öt†GHMǹsf°nÓ—œOL":j”YºèèHär9i™huZ’SÒ˜8>d0>f,sòHHI!/_úC==z.ææQRZÊ·NáÖ)“xæñ…¼ðÊs>1‘ó0Öqþƒ³™ù«{Íêjzž•“ƒZ­ftÔ(n2 €{î¼£Y€únùw¢P¸àªt5^+]”(•Ê.©«°€2ûþûèãß²ø##+›ƒ‡¯ë5éX_OAQ1Aý ìŸŸŠºÚ+vË(-+ _@€Ñ/d@0UÕ5­âûxyJVv.ç“Ð440v´483!f _Åý“s I—âáînì––•IåôkùÅ D&“Q]sÙ¬ eÛ"•U„ µ{ÝêšË¼¹b…EÆ>_AQY±šeK_Ã߯sWØ9/Àî÷Ãvc±6¸grÔ¿?¾>¾üñùg[%7 > Jå @qq)ãÆDu1€ý­>ó±ÑÑddeóÕž½R3Uaaøx{sö|µµuDGE¢+¤r|¥rŠŠJŒy^ÌÎC¯×d(ÇVŸÕÂß_%ýÁ–••›‡Ùº×.fùêâ[¶ô5Þ|gEE,_õ®\Ö©õqä= ÀB"80ôÌ,þ½ÿ?èt:ªª«IMÏ@®¦ÏÖ\VG Í#Ž5ÍVÇÐÇÛ½w)iääæqèÈ÷Èår&MoµÜqÍýº´ÌL‚é×W²žr¹œñc¢)¯¨¤áêUbš-#À°ÐP¼½<ùéÌYûâ’2öìÝÀ”IÛ¼O…‹ô›]U#Yä°ÐP<ÜÝ9uæGŸ ¸´ÔáÉ ]ANnC‡ –¬J…¿JŲ¥¯1tÈ`ròò;½>h‚v³Ÿ¶NÛ&P¡óÂ3OòÞßÖ°~ó6m‹¥©© •Šk>"$¨?þ*I)©,~áeÖò>‘#Gp*þ,o®\Í“ aú½?gæ´_²÷ÛüiùJ@Ò¢¿&tð@¬=óaxxx Ñhk|Ç'1>f GŸ`Lt¤1ÌË˃%O,䓵ŸóÉÚ Æø·Ý2™i÷Üe¥œ–ëQÃÑÉdìØó5…ÅÅüñù%,ZðkÖ}±…׬`èàAÆ×Ýíï$në&“+©nþ*_>\ù¶™_gamÈÔtÚ™aýŸ;Òz'Ÿf7%+=ùÃΪdWràЪ/_fÖôûðpo„©ª®æàác ÄmSn1ú×]©'!)™òŠJ‚û14tˆqt­¼¢’“?ÅãííÍm?›ŒÒÅ…“§ÏRQQÁèÈ‘ HÓÉ22/âêªdÔÈá„·YÇïŽý@yE%“ÆÅ6tˆY]öí?ˆ‹BÁÜÙ3Z¥++/'1%MÃÂB9<–ž™ÅùÄd&ÄŒ! @Ð…ˆ> @Ð…ˆ> @Ð… ]ˆ„º  E4A‚.Äi X˜Ÿs=ë!ôJœà-wÜ@º†ÊŠ2ê5ètÚëV1 »"—+ððð O¿@¼};¶‚¾CŸ¤(/)B]]EðàP¼}T(bÏAÏG«ÕRW«¦¤0M=}Û^.ÖN °N]ƒººŠðÈ1¸¸ˆOËz …•Ÿ?ÞÞ>d¦$àîáét^NÂTV”<8TˆOÐkQ¸¸4(”ªò2§ópZ= šz¼¼}»ý—‚‰·/…¹YN§wÚê´:Ñçôz ZÎéôâ= @Ð… ]ˆ @Ð…tpS À¡C AÇMÐë€V«%%5•¯÷þ‹m±;øþǹzí— ضc§1niY_ïý—CùÆíÝKzF†Ýx5j5ë?ßĵæ2M9sþ<ß8àà:!Àr1;›…‹ŸféÛË8u:žs ¬úà#Þ\¶€üüKlÝaŒäè1Þ}ï}jkkmeiäëÿÛKZF¦Ýx—kjXgC€gÏžã›ýÛqG‚ÎDLcé•,þÝó,yò ~ýÐ\㮸 YEkÌ›û ÷þâ|||:«š‚nL- ³Ú÷ ÷ɧŸòó©w0Þ\$íµ„)r“떰¢B¾=pÐ,®N§åøÉlÛ±“ÓgâÑhê­–wðСVi­ï%féoV^QÎ?ÿýo¾ŠÛCaQ¡Ñ¿©©‘|¹…¦¦FŽ;Æö_ëÒРáÐá#lÛ±“„ä¤.öÝË9h‚v€c?üȬ™÷·+e“T£Ñðìï_bí†Ï¹TPÀšµëÙÿŸC­Ò>zŒÕ|DTdÇ6;9{î<‹?Cjjéé™<öäSü@cc#kÖ®ã¹ß¿Ì¦/·p!1777*++Y¸ø~wˆ’Ò^ýï?³ñ›;T„u’Ò²2®Ô×3xà 6Ÿƒ!ÌÖqkìNÜ\ÝøôãL¶ôjovÉié,{wï¯\ÁÀ­Ê3\¶~#®J¥YXBR2^^^èõ ÓéxgÕjž~âqfÏ”vKŠŠÅš¿¯gÒú‰Æ|î¾s*óç=dÌcÍÚõŒŒˆàí7—ðàìÙüæ·OðÄ¢…=+mDÐIikj???§ó9tä‹ÜL|¦”–•ñÙ†üá¹ß1~\L›yyxxàêêjægºÅtQq1— ihh`ß7ßÒÖ×¹ùyfin»õgf×§NÇ3õöÛi”v¶®8†xŠN20$.fg3ÀÎþ}mQXTLß>þ6ß:…Z­fäÈvóZôÈoðöön埔œ€º®€êšã9Àã Û¶dµuu\©«£¨¤Äè÷ÈÃÛ­À>b&Œ“(rbÆŽaËöÜqÛ­¤°|VÒµ——'eVÂ%æÌ˜ÁOñgx}é›lÞ°oo/;y[+Gr!ÁALz;‘#,mm0Gb@pÃÃyôáùvîIÐ^Ä Lxù…HHJâý¿}Bcc£Y˜Î°DE&³ùJ :2ŠîÛ×ß™ –¾þ J¥’·V¬èÐúK•¯/1cÇðÅæ­íÊ箩SÙ¹{W®\qºluD´„ÊÇï­bù»«8|äÑQ‘(•JRÒÒ‰Å[zƒÑQ£¸¬VóÉšÏxèÁ9­òXòÔ“<ûâXò∉Ž&%-{~7³MFW=<ÜÜÜ ¹œ ãÆ› æ(•JîŸ6Áƒ¡Ñh`îœÙ¨:øE°žByië6nÚךéÖÔ†í©[áôñgNû0rìÄë{'ÁMHÊ…x&ülj'ï–y ‚v"a‚.DP èB„‚.D̺§(—ËÑê´(lÌaz:Öæ<^GhoJã¼&wêkÕN,ôêÔjÜÝ=ÁÉ‚ö¨·8ý}T”—¢kcš•@ГÑj›(-.ÄǿؚìkGŽX@ÓŒŒoõ}T*¼|Tdg¤¢®©éÐ繂› ­N‡º¦šìŒ4|UþøH3‚ÌôÑÕ®5t´hš¹Ð*•J|ý»¸R]QFqA®Í ÅAOB.—ãîî‰_@?¼}|QJ‹ µÍ®Í©g–Ø µ_˜ ÐÓËû%ÀpE𮿂dQ VÕÚ47àfÅ (ƒš¦™]4X ÝÇ8bMÅg(ô,ÒÜP¤y¢®Íy)ôLL¨EÒÂ5¤ùž¤¹ŸMÀ6Åšõ´ˆÇÔú m®Ò"4]³Ÿ¢ÙÉâôL z0X;ƒš,¡¥åk%ȶ, µ¦§Ahü”´X?!@AOÅÒ š KhX†d­)j•ö4A›vÍÄß` ÖÏ @ §b*@ƒM…Ø„ùò£6±'@S“+k.ÌL_Ló = kƒ’Á5š â´ûbÞ^”æBhÎÐào(À`õ„ø½[o }?[£¡Vq´ jeXˆOб&BS1Úž¶#³r4›5á  z–ßo4ÑòÜ2n+ì Ffqn)6K«'(è X¾Z°öQÕ6_?pD0–qlY;!>AoÂÑÉ×m6CÛ#[q…ð½[sh.¨³â¢Z#¾!@ ›ü?¥K&”j%IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/layout_box.png0000664000000000000000000001410415074673150022335 0ustar00rootroot‰PNG  IHDRàdŸ &tEXtCreation Timejue 08 dic 2022 22:10:48——R,¤IDATxœíw|”EþÇß»›„ôBI H‡„н£¢ °‹w–óÇyè‡DDÏ;,€ ¥Då8šT)! -½÷Fz#ìîïÍnv7»ÙMM™÷¾ž×>;3ÏÌ<ó<ŸýÎÌ3ó @ @ ®9’n§@ÐUPvfd!cq! zÆ„×!A¶W$úÇIÌôºúSšégm‡!¡IZÙoo:AWÀØ”­ì:®UÚ" }aI´6©ÞocBºúbÓÞz¿õÛÄ\qZx†6!BAOÀøF6}qjo+32aÌâÉ´¾e@_ ?à ôiŠ[PÐÑR#PTE@ oÚZßÚÇJ0!BSÔŸÚ©Eg8ÃvþòXàä€yHpC)'èHP*ʲˆÈ Û›7o \A%N Í"T ѤM E¿Ê©-«¦Ípž´¨ÞÚÔ £ÆX5TÖ)YzÚÚÐ’iCÐÐt"}J;y^¢@ÐÝÑžiL|-,¡9CÑ ¼– ý :h‹ÏЄƒ´öÐг@íÈ{%dW(µuu:î%ee„ì åä™0³â)+/'dW(§Ã#5n'N‡²+”Êêê6ç+,"’]¡DÇÆë¸§¤¥³gÿAtjëêÙÊÁ#GÛœ–6 É)„ì %%-Ãh˜ìÜ©TŠß˜Ñš8ª®\!*:†ââRúø0qü8¤RÕrBr £bxøþ{ILN!#;‡ Iã[Í󥘔J¥Ñ0]A}ˆOHâŸ~Ìò,A"‘ðIÏÌb ·wG¢n—&Ú*ÀæDºv9w:ÙY¹TVVi~çå¨v´þÃ""ùüËõÔÕ×#‘¨Šê©y2çÁû[m´Üö:Ì·?üHcc£Æû¾;oçÅgžn‘§ ~ã8tô8 )xpçRŒÊú-œ?å«×páR óžMCC)ié ¿qöö TYÎUkÿMyE¥&¾QÇñÞ;ÃÖ¶‰‰É„ì %>!‰K1± 4Ð`žO…åó¯6põêU£çÕUxïí¿²tÅGdfåðÏ#‘HÈÈÊÆ½–½½¸3òÛ&!ŠiDfòÞªOZõ¯®®á?¾ÅÁÞžÏV¾L&ãýUŸðãŽÝÜyÛ,³ÒÈÍÏgã÷ÛЯoþyW¯^eíº¯Ù{ðw¦à?vŒNxµã“’¸eÆ4¢bcqvvf¢¿C}“”’BMM iY4662Áo|þÕF®ÔÔòÖëbë·ü@L\»÷ìå‰ÇѤ‘œ–ÎsO?‰›‹3#‡#-#S'uõõ|óÝV”J%o½þgúxó}ÈÏœ»pɬs¾ÞôëÛ—KßQ‰0;€ýûñÁÒ%¸÷ïÝóÓn*»Ú_Û5æÁ{ïÆÞÎV󻤴ŒCG«[_$¥¦P]]ƒÇPwþ8­êu°w@./$7/+™ª¨ÕáµQ6}Â"Î!—ËyøÁ{1\UuœóÐý¬ßü£cð;Zç8?¿1H¥R’’‘+äÄÆ%0yÒÀ¤ ãIMÏ$*.ŽÌ,Õ6ÞoJ”¤fdRpù23¦3-8€—Ÿ]Àkoý‹ÑÑÌìaMç=2›î¹C'¯Úû)ééTVV2nìh¦pÛÍ3š¨ì’÷‰Lf…µæ·µ•5ÖÖÖÉ«°€f2û¾»èëÖ<ù#)%CGk~×ÔÖª¾kjÈÉËÀÓÃOw\]]¨®ºb2Ë…E è×Oãæãí@iYy‹ðN êKJZ£c¨­«cü8UçLÀv„þÆ…¨òó/cgk«i^.,T¥3 ùßËÓ‰DBYy…NVÖ­ß"Å%¥ âkòüºeå,ûðcrró4m¾œ¼<Þýp5,]‚›ëõa×~v½?¶k‹¡Î=­}OwwœœYüê+-× ‘6 ‹‹3ùù—™èï@Jj:ÞîË|¼ŸI)iìØ½@UMUÂð¡CqrtäüÅ(ªªªñ;™T¦JÇY•N^^&ÎÔ´L”J%žêtŒµYõÜÝ\T7laa‘®Ÿ±sµ0ËW¯Ñˆïƒ¥KX¶âcròòXþñg¬YùÁuÍ9Ïfà;x^$&§ð¿¿£P((-+#>1©L5|¶¼¢RÓS(kêq,o²:ê6Þ®={‰KH"=#“ÃÇþ@*•0É`º›Úu ÉÉxyx0 ¿ÊzJ¥R&ùûQT\B]}=š,#À¾¾8:Ø~î“&øsüôüýÆhüìXôܾøf_|³Q~ú” î¾íé4ÿ=b‰„ŸvÿBn~>‹_]ÄÂùsY¿e+Ÿ¯û€!ƒigtµû$tÛf­_ª¼¹¹8³fåû:n× C]¦ÚÃÎÔóÿlQÍwrjÚ‚Sc×\¯LZ’ƒ‡QVQÁƒ÷Þ…ms'LiY‡Žž` ·'Óƒ§hÜ«¯ÔKQq žâ{ƒ¦w­¨¸„°ðH™>5k++Â"ÎS\\̸1£â{ N–”œŠ5£GÀÇË«Õ<9q’¢â'N`ètò²÷À!¬d2æÌ¾¿Åq…EEDÇ%PW[ÇC}5b¸Æ/19…‹Ñ±LðgØÐ!:Ç%%§—˜Ä >Lð -=“ØÄDú¹¹0‰#ÇOâãíÉØÑ£Ì-ênͰ‘cÿCõr¦* ¨Cwf|‹3B€A'Ð^ŠNÀ‚ˆ6 @`AD/¨@`A:0F tÑ,ˆh D´ "(XÑ #Xt ETA Òn ˜›•Þ™ùz%íà”·P]YNIq!u5µ(òNËXWG*•aggGß8:›7‹º·–UO£=×Þz%EQA•e¥x öÅÑÉ™¬÷¬Ù"—Ë©®ª¤ 7“ºÚú{´>e¨7—UO£­×¾5Ú-ÀêÊr*ËJ6Æ+«Þ÷j™L†‹«ŽŽN$ÇEakgoôß°·—UOÃеo/íî„)).Äk°o¯¿¡dVVxò¥´¨ÐhQV=s®½)Ú}GÔÕÖààèÜåß„|=ptr&7#Ũ¿(«ž‹©koŠv[@…\!Ú1MÈd2ä …QQV=S×Þâ9 @`A„ "(XvˉNóe%hI‡(:õÌG”•À¯‚9vœ°³áý6lÚLQq±Yñœˆä؉šßÙ99üøÓÏ’Çž‚\.'6.Ž_ÿ»—­ÛCøýÈÊ++MØ 6mÖ¬­(®‹.àácÇ8}ö¬A¿õ›6kV 2EXx8GŽ5 0++›m!?uJ{q ,xþEÞûð#ÎFD’’šJÈŽ]<ôè\ªªªLGÐNY¿i3•U*¡‹ë¢‹šÑ ÈËÏçOo¼É⿼Î÷Ü£ãW__OŸ>},”3Aè„i±Ð½á‘‘¤¤¤áííÍÌ›¦XÄØ·Š¨ØXbcãé×·/Ó‚ƒpttì„s0Ë5W¯ýœﻇî¹»E>úô±iáfªŒ²sr‰8‰‚ñòôÔñ/))átx8µWj˜¬YÕI÷:§gdp6"ggg¦M ÆÕÙ…BÁæ-?pç·1h`órØÇNüƒƒ=s&<‚úú:¦M™‚OÇÖv·(¯‚š‹B¡à­¿/å› ›(*)fãwßñúâ·Ú4¼kÕ§kXöþ 2³²Ø²mO<ó!‘_wü„T*åêÕ«<úÄSœ:s–éSƒUá´ò¤ÿ}æìYŽýq’Ÿ·~“£#r¹œ×ÿ•u_¯gÅ{ïv‰˜8M Àìœ\ðöñÑäáüÅ‹œ»pQfÔˆá̘>Ýd•••óÉÚñïÏ>e\ÓZ†ß|»‰>]CèOÛ±²²bõgkxrþã,|ò RRÓxâ™gQ6]G¥ìíøný×888 P(øëßÿÁ_}ÍšUqǬYìúõW½ð‚æø+ÕÕLš„\®`ÅÇ«yé¹g™ý€jµ§±cF³îë nh}]îJ—°€VÖÖØÙÛ·Ø´ ‹ˆdРì;p½ûösð÷ø¹¸‘™iVÇOžâÎ[gáÔT’Éd<9w.áçÎwúùt%Ôk¡W”7/qÝPß@uUÕUU>zŒ§N¦Ë(òÂy|¼¼4âxjþã‘“CII IÉÌ™ý Æð æª¤[[;Õú‡OÍ›GdS³n¾™Ô´t .pâÔ)n¾y&2™Œ¼ü|²sr©««cï¾ýìÝ·ŸÒ²r2²Ì»º"]¢ÆoÌ^|ö™î65/¦XU]ECÃUò 4nÓ§Oc‚¿¿Yi\fâxݰÞÞÞTTT9¢gàááNŸ>}HIKgð AO "xJ®þD¶µ2R(ä\¦o¿¾:þöö¸ººPRRJMm-666mnWûøxSWWÇ•+Wpss%`âDNœ:ÅÜ9ðÇÉS¼üüsTVWPV^®ÙxvÁ‚6¥×•è0¦âR5Ü}¼<É%ŸŸ]hâXë»öus#¯ _Ç¿¬¬w÷VÒîL,S•H`jPßoÝÆ¬™7!‘è/ ÙÜYÕZI¥ú¹¹’Ÿ_ ãߨØHUU5ÞÞžH%R(-+¥¯›[‹ø]§’²Rpp°”Ü~ë,Ž?Îm·Ì$'7—ÉQß3gÞĘ‘#œG÷¢KTAÍá–38NBR²A‰D‚BÞ¨í€\ÞüÞ•À€‰:|„ââ[èo{˜yÓ´k–ç®Â¯¾BJZ«>ýŒ††¿ÚšZ;©2š0ÞŸœÜ\Ni~n»gï>†øÆËÓw÷ ôñaÛöæç|Å%Íq©©©­¡¬¬¹J¼û—ߘ1µù:Üzó .EE³ïÐïÌœq“f"³‹³3Æû³åûm=fne—¨‚šÃä€IÌó0¯¼ö÷Ý{7NŽ„EDðÙª•ôusc¼¿?ËW}ÌÆï¶ðÜ‚§7v4••|±î+}ä!îºãv9‚_â–3HÏ̤ºªšÿ¬ýÔÒ§vÍññöæ«/Öòîò•Ìž;ÿ±cqpp 6>¹\ΒŪžJSeäãíÍ¢žãí.ãö[g¡h”~þ<Ÿ®\D"A"‘ðÖ›o°dé2RÓÓñòòäÂÅKØØØèäçjÃU¾ø2Ó§“K~A>ë>o^pÙÅÅ…ñ~ãøö»ïYù¾nÙßÞ|“7ÿ¶„—^} É\.¤¯«+^ôÒ5.ÅkC»—¨>wæÄš1ã;Þótôø ììì lá·qówÌ~à~4­±Ÿ@tl ¥’1#Gà7n‰¥RIXDùùÜw÷]ôéÓ‡äÔ4Î_¸ÀÍ3nÂÓÃ¥RÉ™ðp2Ò3ðññaê” 7G{‰»ÉhÿIýâ£ÎÓeÕQêëë‰OH$)%+++|f¼¿ŸÎdasÊ(1)™‹QQ8;9„››«ŽNn.aX[Y3sútNž>Í-3gâääHvNé™Y¸¹ºƒ»û¦ã ×é¶û×ßørýzöÿúK‹WyTWWs6"‚ܼ|ôïÏ´à)¸¸tìíd!îR$Sg^ß5â;K€=…î ÀîÄ_~EyEËÞyÛÒY1IGØ…:az:¢¬ÌE©Trøè1ÿåuzz¹u›NAï!&.ŽŠÊJ¦öüZC·é„ôüÆŽåØÿY:×a bù± ½QVC´[€R©¹BŽL*Œ¨B!ךÕQV=S×Þm=R3©ËÖÎŽšªkû:ƒîBue%¶¶Æ×eÕsѺö¦&¶Ä” Ïj¥“K?Š rQÈ{÷2[ry#—ósqrëk4Œ(«ž‰Þµ7<Ù„ ͱ€Ú)š6¥“‹ N.¤%ÅSY^Þ¡×swGä •åe¤%%àìâ†S+ëÄõö²êi¹ö:úh jÒšÛÔŽ\È­­­qvë‡Ôʆ²âBòs2Pô¢K*•bkkk¿8:9cmmm4lo/«ž†‘k/oÚôEØ*ƨ4°éÐÞÁñMÀ°A5\Í •EU[UCÃÜ‚îŠZPj4¢fÖÔbX€ú[ ̱€ÚâS'zÕØP;TãDmšâ’!(è™h PŽJ ¨Æ{Ö¢û©=îÓ,+hH€JšÅ£mýÔ‰^êiš¢ÉMÖ´IâôLÔzP[;µêš¾ÕT[Bã³›hͪzª…¦˜ÚÍšfë'(è©è$uTm šÜ UE Ò–*h#*5h¹«-¢Úú©(ôT´¨¡¶Ñ~Ô*¦¨mr%M î?€vç‹a=C’jÁ]ÕúV‹ÓäƒySUPš¡)Bµ»:µÕâôŒ=P·ýŒõ†ÄÜ*¨Ztúu`!>AoĵÅhRxjZŒÄÀ·¶Ø OPÐÐ×¢Zˆúûúa[`J0½}}±é[=!@Ao@ÿÑ‚¶µ3ôàݨ%4G0úaŒY;!>AoÂÜÁ×­VCÛ"ca…ð½™Ö^én’öŠGˆN h‰xï@ @ Œòÿ¹;,ªË¦IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/layout_center.png0000664000000000000000000001662515074673150023037 0ustar00rootroot‰PNG  IHDR¬dÚÁsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timejue 08 dic 2022 22:12:52ÄPBøõIDATxœíÝy\TåÇñÏv@ÙQET\p-MKË6³ÔlOï­l»­÷f‹Ù¢mZ™-jjÙª¦¥fšÙ¾jî Š²(ÊŽ"( ÃÌÜ?†g`H~ï×ë¼€sÎ<ç™q<ßyÎóÌs@!„B!„B!„B!„Bœ3¥•”)„¢õ14gaÍ.öÊàBˆöÉ^P5)À*5§4p›Bˆ¶«f ¸­AÎ5Ll“RÇï=ŽBˆÖÅV8êøÝÖãêt.AR3ˆ‹EUão{Á%„¢íªN–‹¾Æß5÷¯WCÃÄVH™‚ÊÖ"¡%„í‹­°ÒÛYj†™åãírl@%쵨,~:¾@GÀ p®.[K!ÚËà©Î%@pÐU/z‹Ÿ–U¨'´ê ¬šaejA™BÊð¢¾\¹bâ€øþ“PðÁ %„íš‚Á 7œØ¾c÷ò‰“&}¤§1†™ÂÙÐ2W½¡U_°Ô¼hTjÀwÀ€W­Xöž¢ iôBÑf xì¸ñ÷%$$ìŠ-Æà2µºl]"¬¥®À²l]™ZVŽÕ‹àÑê•Ë>4tiQ!D;¥ T]=î†;·¥@%ÆÐªÂºo ì„V}e«e儱ª÷‘C)+@ZVB!B9Ùõf c—)´lµ´jQÙ+µÆï¦Ð2] ô[öùÇã‘°BÑ`ŸÏ>^z=ÆzjŒ™â€õ¨r°Ó˜ªoZ%ËKjŒ-+W [ú¡”/ðirý…B´½¾¨K×î7É@9Æ––©O«æ +uõ=Ùh .E1x7ï´†B!Ú:E¥òÁØØQc=øBE=#ú=¬šå†^†® !„8WpÃú’ i‰:5¤…U3°'i\ !„h$'Îæ‰e`™–stabï² C³TY!D{d™%5§ô³ËV ËÖíAj†–ª™ïË%„¢ý°œÞÏ^XÕji5dj&[Ý:H^ !„h$˰²5aºMöËÖ˜xËÐ’¢^UUU>r”#”•UàOŸ^=qqqnéªÕ²{o"Éiiæ¿==<éL¯Ø¥ùßîZ­–¯Ö­·¹Í×Ç›Ë/ÙìÇlSÓØ“H|ß¾DE„·tuDëU3OlåÍ9 k·|°e!  HKÔ%9õ﾿˜Ìì«õQ‘¼>ëùf9ƲU«Ñ骸ý¦›\Ö®½ ¬Û¸©Öú˜îѼðÔ8995ù–*µZ–¹Ææ¶¨ˆ.Œ¾P+9•å_®ÁÛÛ›H ,Ñxºwâ¹ÌÖ^cD–°-3+›§_˜…¢(ÜpÝ5ôŠéÀá£Ð\ï~þ…J­–Ûo𨠥ëô¿‡ Ÿ8$§0wþ"La×Þèß Ç¨}¼ @ž~ü«-jµ#îÿ/[7mÕ¸›ï$¦{4O=ú¼¼¼(9uŠÙsßa_ÒAÖ.ÿ¸)ÅÛ»ƒ½]´V. »Þ[ò:ާ˜AñýÌëûÆõ²ÚÏ`0°w_™x{kßgãåÂ?6ÿMU•Ž!ãÙ¶sÅ'KˆëKXçP¾^¿‘òŠ ô:=+¾ZK ¿?#† mP¹§NŸæ²K†±}×N–”2røEæ:9::âââL߸^\îW_¯7^¶uufOÂ~<=Üп/®..uþ›/,"a_§ËËè-­¯6¢Sh¦ðìK¯1ó™i(ŠÂs/Í&ýh¡ÁÁM)ºQr®uö òáJØPrê“SèÌ þýì¾O*µZfÎ~ƒÄýPƒÁ€Ÿ_æ¼ø<Þ/~ûk ‰û“X¶ê+ ŽàààÀŒi×3–µ6RQq€_®!®g,#.Ú r÷'ä—ßÿ$%í0ŽŽŽŒºdØÙŠU7Μ©$95 ///z÷èa~ø‰>]FUÕÙ»úòQÜ=ùv‚زu;G3³ &:*‚¹ï,ädI s_™eýZTÿ®ÕjÉÎɵzm|4šzËÊ?VÀ}>^öx..μðÔ4ºu¤¨°˜_®á·?7“›—oÞ§Wl**ÎzèyÝýwOáò‘#Xµv?ýú……hµZ‚yå¹gÐh¼j½NoßÁ[óQq挹¿ï¶I?öÛÿø¢ÕxþÉÿ2}Ö+ÍÈâÙY¯¡( G22ñïØ‘O>Þ9pNÁUß÷°„8'™YÙ„†Ôýékõº $î?ÀÄqcYöÁBî˜4‘‚‚BV³Á¼Ï™3• Ï볞ãŠËF¢ÓéX·ÁØÏ´tþÛøxkpwwcí²yáé'\nyEåå ÿŽÏ{}}+ƒ4±„ •••€1êzìNH0î¯Õòõ†TTT‘•eõ¸Q#†Ó)4¿Žlúéròój•kùwCË}ô©t 3?Þ´eÈÀxBƒƒ¨ªªbçÞDöîÛÏó¯Îá•çŸáïí;Ñét\?ö*¢»F0~Ü5,Zú){÷Ñ+6†Èˆ.\3ærÖ}ûG3³èÓ+–ËG´[gÆ“+G]fµ-¢Kg ê-kÔÈádåäp %g'E!'7·úù÷‰Œ£_\o¶îØÅÏ¿ÿÁàñDEFÑ%œu7‘ì8:½•ÊøùÕ[£á⡃¸{òmìܽ—ĤƒVåšžCÊ¡4N*# Ÿ?6ÿ €»›;:Ý1²srèÖ5ÊÞ[@´Ž8©Ï~¨S;ªQ«Õ-’rãEѬLý1GŽfPUU…££í·XYYyùù¨Õj.2ˆÈ.á6÷÷ôôD¥R¡«ÒÕyü†–k¯^Æ f`¼±¯é†±Ws网œšFñÉòàסƒyÿà ŠN›×Ý<áz¾ûñg*++¹iÂõu‹×xi˜4~œÝíöÊÒjµÌ™7Ÿí»vÛ½¡¡Á(Š‚®Jo·,oÓÝ€Œû¨T*4^æ×Ì¿P©Tœ,)±¹½¬¼Üø³¬Œ¬êK›þøãí-wjíNŸdÆK¯‘•cî³ÊÊÉá¹—fóâôiæ>Óó¥ñ% ,aCB‚‚ÈÎÍeíúï˜pí~Œ€€2³ssÙ¥ôéÝÓzc;žšï5‹j†Û]®ß]]\ $=#“Ò’RsNnn>}{¤J 8Àßü¸MÕ°jÍ:¦ÿï±Ú/@ÛÙ+koÂ~¶ïÚÍ•£.ãž)·ðËoÖý<ë:¦×ãÈ‘Lôz=þýj—e€@ã¥N/O/ð>ûÏS´J3g¿i«§O`Ƭ×ÈÊÉaækoðæË/ž×úH–hvS§ÜÀç+¿ä÷?`çžRÒóý/¿²;!€¡âøxù/D¯×“t0…ÒÒÒÇÓÓ“²²2’¦ Ó隥\½^‡^¯§¼¢‚¿¶nçHf'!ÁAôŽíÀWßl é` éGŽòÓ¯ R©Ðß82'/e_®!:*‚þ}ãØ¹'?·lµ{<­VKvn®ÕbdRWY¦–MfNåååìK:@•®îÖgC/*bÃ÷?’›wŒÕë¿`@¿8ª[¦EÅÆexçNœšÆ·›~D¯×Stâ’S›¥.¢e¥9J—°ÎÆÖ”FƒFËӧÑ%¬3éG3Î{}špIP>: ÛzÅvgÚ#²péÇüüûüüûæmýûÆÑ·wOF JÂþ$~ýs3÷<ü8jµ­V˽SîàŠQ#©¿9—ÆÒÏ–óÌÌ—ñïØ‘÷çÍib¹ðÚ[ïZýíééÉã܇J¥Ð3¦׎¹œo¾ûžgf¾ /«Ýyó„wE¯×ñöÂ%TUUqï”;puu%a_K>ýŒ¸Þ±xº»×z¹ùù<øß§¬ŽÕ%œ×^|¶Î²úöŽÅËË‹}I¸õîûQ©Txzº[”m«ùØð&Ö’?3ÿÞ=º+W_10…¢(|±z-Ù¹¹<þà½ügê¿™3ï=òK—­ ªª †Þ›ûÌ"Ο5Ÿ/µøËøþðÑxñæË/X­;_l½›,§a2ÝÿÊãýK<«—ÁiÉûß<_•­Syy9)‡“‘™ƒƒ¡!AôŒénîÜH=t˜CéGaá„u³lÞJN^WŽiþÂâª5ëpusåš+F›¿/é i‡ÓñõÑpñÁæ²Ï¥\€= ûHN;;ÔÛÉIM€Ÿ}ãzÕúRÚátRRáä¤&¦{4!AÆ~¬Ü¼cü¾y þ~\r±ñ;a[¶í #+›¸ž=èÝÕ\†V«eõ7ßÚ|Ý|}¼éSoY'Nžäïm;1 ÄõêÁñ‚"2ss¸æŠÑœ(.æûŸ£SH0C a’S:0ÞÜ×øí¦)=}𝋢(Üòï{ñòðä‘§’œ’F`€?ñ}ãpp8{ƒ†”ÔC$%§Ð)4„þ}Œ:N.#aß~ ŽàG—ð°E&Z‡¨n±¥ÕKPõ‡k}²’ÀB˜™ká¼9-]ц56°dÐ…¢6ùÿ-.@Ò‡%„°Aþ‹ |Ka¶lÉ‚–®‚v5a¦ !„âü‘>,!„­‚ôa !„hd¦ !„­‚–BˆVA]!„hš0èB"K!Äù#—…B´ naeg¤7g=„Bˆ:5:° 3ÞÖûTI1…ÇQQVŽ^ß<÷ã¹P©T¸ººâ뀇—ÜMUѼÚâù´9Ï›Mšš© /‡’EuÇÃScu ‚¶H§Óqª´„¼ì£T”—Ñ1 ¨¥«$„h#Úêù´9Ï›¬S%Å”œ("ªGoÛÇ”„h¼}ððð$5)W7ii !š¬-ŸOm7«Ñƒ. #¨sx›{qÂÁÑ‘ÀNákéª!Ú€öp>mŽóf£_Šò2Ü=¼0´Óáíž^dIkéj!Ú€ör>mêy³Ñ-,½Nßf®±6†ƒƒ:½¾¥«!„hÚËù´©çMù–BˆVAK!D« %„¢Uhâ”¶ÝA(„çœOëÓ¤ÀjãZ„⼑óiý.ˆAÿyyùìØ½›ÂÂB|;øÒ·woBCBZºZ¢Ñét¤¤¦’švˆÓ§ËèÔ)„ññ8;9µtÕ„hŸýC‡×ZÄ5WŽiT™z½ž>ú˜I&àååÙÔ*6I‹÷a-_¹Š›'OáÏÍ›ÉÍËã—_gòÝS)>y€¿¶ü͆ï65ù8z½ž7ß~‡'Š›\–h{§§3ùžû˜1s[wìdOb"sæ¾Íó³^j–òõz=o½ûž¼ÿÄ?ê§_å·?ÿ¢ôÔ)«¥¼¼¼ÑeVUU±èÃ¥””–4cM§E[Xyùù¼õî{|úᢣ¢Ìëõz=*•1K÷ï'3+‹«Ç\Ñäã-_¹Šñã®ÃÇÇ»Ée‰¶ãøñBî~à!¦þk Ç_¢(æm:]óM@ºbÕW\ÝXyÿ‰T¿>q<öÐZºÿˆtqèðaÔj5‘]­ÊR©ÀÀÞÄDvïÞÃÉÒR¸”Ý»qÑÐ! ö$$’š–†^¯§_ß>V·æ›o>t(™Ù9$%`ø°‹Øôý¬üj5Þ wÿkr“ê.ÚŽw¼Ï¥Ã‡qã„jm«ùeÎm;wr(í0ÁÁA »h¨ùƒÕÖ;éàãCUU{÷áææÊ¥#Gàîê ÀGŸ~À—«× Ñh¸uÒ¸VoK;t˜Ý{öâæîƈaãîî@fV6&3h`<¿ÿµG®¼|ô?ö:ˆ–ÖX‹¥¶Ì¬,Ò¥[tW6oÝŠöL%_4”à ë i Ù¼må§Ëˆï߯FÙ-§E[X]ÂÃÐjµ,úp)ÿºóŽÚ}Š‚¢((ŠñÄ¡¨ŒŸ|?ùl?ÿþ;ÑQQÍÈ`Þ{ ˜ñô“æÿÌk¿þ†ï¾ûü‚ºFE2h`<ªêJ¥jß( ÷Ç_1wÎkuî£×ëyjÆ Ñ»g,ø‘Õk¿æ­×g£( Û¶mçÛï¿'8(ˆ˜nÑìÚ“ÀgËVðÉ‹pvv¶ûþ[þÅ*¾\û5Ç]Dff6ï/ù¥‹ÐÁ×—ÌÌLæ/^Ì’>"( €˜îÝÿÑ×A´}™<7ëe:øúÒ¿o²ssygá">Z´€Èˆ÷'ñØOÒ'®î,ùè“®õY-:J0(0ˆgžøo/XÈʯÖ0úÒ‘Ü4q"]ÂÃèÛ“>q½ÉÌÊbÊ·›yÛ-7sÇm·šËyû½ù¬Xù%cFWú4€7óß~Ëü 8<,œù‹3~Üu„uî,#rùÇŽqº¼œÎBëÜï»~ä`r2k¾X†J¥B«Õrãmw²eë6†@˜ÞxÅØçuº¬Œ1c¯çÏÍ[¸läî¸åf.þ€Æ]GX§Ndeç0ñ–}ô!BƒŒž›ùË¿XŃ÷MàDÑ æÏ›Kl˜ê%ˆf9'`÷ž½Ì{w¾Õê1W\NtT8::òÙ‡Kpvv`ÊÔ{Yµæk¦=ö(³ßx“[o¾‰;o½0^¸eò †–ÉØâ£¯½ú*F_v)ëÖo`íúõ¬ýf=£/ÉóÓŸ±;s±)„Š‹‹ÉÉÏG£ÑÌzà!ƒ™÷žŠ3g(+/ÇÛÛ~ßÒ¶í;éÂÆï0¯óÖh8rô¨9°<Ý=ÌÛÜÝÜèÛƒœ¼<»eîڳƋ„}ûHØ·EQ‘ž‘aÞG£ÑHX‰sâ¨Vãêf} G‹V½“Zm+€¡ƒ±ÿÀAÀx)ð`J*óç½eÞ^߇¹ó©Å ÀÅÅ…'ŒçÆ ãÙ²u+O<=õ72îÚkmîŸìϾ8“Ê3•ÄÄtçTiéy®±h+Bƒƒqttäpzz­ëø–JN•R©Õ’k@ L\¯^vãêæVçìÛ¥§N¡ X•LxçÎçø,„8«WÜ=erƒ÷w³xŸæ;†““õ<ªe\p3] 4>q½9rähòÏþþÎüDGEòßG`ûÎìØµÛÆþ¶ßò‡âÂáàà@ŸÞ½ø|ÅJ.:Ôî~!Adçæq×ä;›íØÁA”•—ó¯;n—«‚æ=/ÕW–­s¥>>TVVRt¢_Ÿû¶ü¹³Eÿ—œ.+£¸Øú{)'KKI;œN÷n]P;©É;V`µOÁñBœÎ6iÕ{,EQP«Õµ. ñè$aß~Þxû´Z­Õ6}õ­.6Œ¿·n#9%µQǰõþë߯Š¢°jõÚÆW^ˆfäïïGhHŸ/ÿ¼îxaa ÖÈZ‹^ܶcϾ0‹îÑÑ„†† ×騲m;úõãòQ£V¥Rñ¿GfÚôJO'((Ý{öâtÌöbk|·b±¨ª÷qÔ€sõ:õ®)Wø7éàáaaÜ0öZ:øúàääDpH0wÜr3“&N0yÓ¯cG.2„òòr‚ƒƒ ëÜ™Ø1ô¬îˆîÙ#†Ç~'''zÆÆ V)ÄtëFßVÇ»dø0<ÜÝqrr"6¦éÙù9øØï÷­Ghp0㮽†118©ôàê«Æ0iü æËuC d`|ÎTTâììÌ5WŽ!¬sgã{UQèDxX˜¹L…¨ˆü¸døÅx¸»ã¬v"2¢ DFtáòQ—¢R©¨ÒéÏàA䊂ÆË‹^±=Zä5çÏñü\šz>ã#OOOÔjµÕâ­ÑÐ5* ã@ó¹Òø üý‰ŠˆŒá6úÒ‘¨Tøûùsÿ=÷Ð)4„nÑÝš%¸ òsXôÁÒM@PY½h*@_½Ø¼ö¨ØYg +SP¹n€gõ2xç–ßßìßäÊ·fI{wÓ»_ý; !D$좽œO“öî ÿá¥ÕKPupÕê4»à]!Dû$çÓúÈÐ$!„­‚–BˆVAK!D« wBˆ €œOë×èÀR©Tèô:Úé7ôõzÌN „híå|ÚÔóæ¹>Ò<‡‡‹«+eÀ([Ê©’\\ÜêßQ!êÑ^ΧçͺoÜeG}e¨ñÓ¼ÞSÓ‚¼lôÍxGÖÖB§«"?7Oß–®Š¢ hçÓçÍZ™Rã§M iaYdþ²§Fƒ»§†Ã)().FW=çZ[¦Óë))>Áᔃxi|ðôÒ´t•„m@[>ŸÚ9oZåIõ®õ¶¶Ú‡eY¸ЩÕj¼|: rtâÄñcäf1OÚV©T*\\Üðîà‡‡§jµº¥«$„hÚòùÔÎySW½Ô9SMöË`c± ,7wGWÀ ãôMŽ[l¦V›­iŸ„B´}¦2åFÆi—*rlVÍ¥–†´°,ÃÊtÐ]çtÅ8Ï SuYH` !D{gX:ŒÙQ‰q¾ÀrŒs6hÂ[K¶ËÀÙ°±l]™ªÎp6˜ôÕëª +!„hïLùajM™²£¢ú§)°L--{wÝ5««…eëR )˜LdZ§ælëJK!DÍé’ ©¥eº­ˆ­Kƒ6Ë%Á*ŒTi±ÞÔâ2µ®L%„BX–)´,ƒ« ëÛ‰Ô©¾À²lÒ)ÕëÄ´layóG!„í—­A{¦€ÒZü4…Y½_$®ï’ Õ¡º@ÓzÓL­* +!„5Ùin껲7ZЦ†^4…TÍk’VB!êb+´,ëޠ2©+`?-ÃÉVPI` !„°d9“…epÕü½æ¾µÔ0Jßk†SÍV•–BK5‡ª[¶¦l}QØnK«!Ss{­) +!„¶4t²Û:/ žKÈØÛW‚J!DCØ ¤Í%ØØ°‘BÑre!„B!„B!„BÑêý·¸=Mܘ,IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/layout_flowbox.png0000664000000000000000000002124415074673150023230 0ustar00rootroot‰PNG  IHDRHÏÌÝsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timejue 08 dic 2022 22:17:47šÿw IDATxœíÝ{xå/ðïÌH¶$ë;qçâ8Wr'wÒÒöœ¶Xh¹,h{ÚtO{Î.tËnÓž‡P(„Òð즻lÏÓÝgéžrh!- m(÷rJ¤P.uŒã8÷‹ïŽíȲ$;žÑùC–#+zeæyl? à €~$›§‚sM2Õ(Çl’c5²ÌSêôÆèP±iÓ¦ÍOì~ì) B#"’(ô^uÍu7×ÕÕ½ ÀY$ejV™í”û<¹dúì15st ?J7nÜxñS¿xü?ùª ]yõ_nÝ·oß›ú "Ù$‡0úÚ$ h’c5Èl3Ç$¯1®9v¸i7À™#9•ÒS»hÉçìCòeªIf›IžGUÍø}ªI¦N­+ûÙ#×Í‘ˆ-QþÓGþ÷µH. »‘ìaFße&‹c½L0ýÔÚäÌÑ à‚£‡›~®å–ÇODd£„at/X²ì&ÄœI¦®If.ÚŒ"šAÙW®S²\Q0MV""»(ªZŽäd.}™yÏvV¹äH}œß }¼•‡ˆ&€ç7È1{X®Õçl7†§­bK}W!"";•à\ÿJo©GÖ†–ÏâÙN³5öG"š@Îõ®^"¢¢IoŽÙÞP'«\÷Af»2½8ÑD‘Ù¿²õ·óún> iˆh)è½jͼ›Ïèï±?ÑÄ"úD¡|îƒë@DDNWPÏ2û.<#á’ˆ& S’oS6I¼ðÊïÐÓÛ›uÛM×]‹Æƒ‡ð~Ý>lZ·‹ÖÚ2†æÖV¼þÆÞ‘¯½¥TUUbý…kPRRbË1Ós+Š‚˜S= K—,†ªz‚D”d¡Aré$Ï¿ô Ž?‘uÛM×]ƒš°û—O£|Z‹ηe §š[°û—OŸ÷ýi¡ ¸ç.TÏš)ý˜¢Ü5óæâ–¯lŲ –J?&MœAN2÷Þyʧï»Ð]yÙ%Øú…›pâÄIüø§ccö¼ð¾ºõ ¶s×÷¢´´­­íxñÕ×ðÖ;ïážïÿ~øßnj鶗 wÍç¶bù²¥¸ã_G0„#<øƒA}C#~õø#ãsÙ¥ØßØ„!]Ïë¸'›[ðÿö¾…i¡ .¿ä0|y ‹ÌǦõë²æžUY ŸÏ‡9³ª±qÝZüã„×ߨ‹Gwÿ߸å¿ìwôø ìo:·Ë…µ«W¡rÆô‘cÔÕ€ë¯þ Þ««GsK ÌŸÕ+—#‰àý?ïC¸¯×]ˆYUU£ŽÝÚÖ†ÆFİtñB,Y´(Ïÿ[SÛ¼¹s°¿± wíØ‰ûî¼ Š¢àîï=ˆ£ÇO`îìÙŽè1œAN2­míˆÇã#_ý~¬û665áû?øôž |oْŸçŽoÃëõ`÷“O£zVÕHƒÜó‹xõ÷ÀŠeK±zå€ß<ÿþø§wpÙ'?žõ®ÿªªââÍ›ò:îìYUxó­·qüä)Ì=K/Ä~ø¯8ãìÈûy¸áÚ«ñú{ÑtèàÈ÷Ýý <õëç‰DžÒRÜù­¿Çê•+p é {â)¼öúhikù™O~ì£x·®=½g’5~þ¾ÿÝ»° ¦ðÛ—^Á} CCC#?s套à¿}ù‹yuªºçöoaûŽpüä)ÜuÿN(Š‚c'NbæŒøÎíßïá(ü6r¨í÷=€¯}óö‘ǯŸ)ë~CCCø§=Œþh ÿãÖ[ðÐÎû±jÅ24<„§~½U••˜?o.ZÛÚqf¸‘ý¹¾Š¢ ±ébÃM¸á@-X0ê´þ7/¼Œ¶~ŸÝúU¼ðÊïP>mfLŸž×q5MÃ×ÿú+PUÿþÈ£Øýô3hïìÄ—?£©k˜sªgÁår¡½£ º®£¾¡O>»ëÖ¬Æ#?z;¶ßÁ³gñ“Çvú¹™•Ó±ó»ßÁW¾”¼ðÊï_Ç•—} Þ{7¶lÚˆA<÷ÂË’‹RÿŸŸaFEv~÷;رýL//Çž_FÝ yuªš^QÛï@õ¬™8~òŽ8‰ÊÓqïöÛ0sÆŒñ 2Áÿõ_ÊUW\Ž›®»fä±zŲóöI ÃÇŽ£­½[6mÀ‡·lƼysð×õ%Àûûö!6o\Øð Nµ¶àtw7>ñ±‹aêêp¢¹áp›Ö_8ªþ’E ð—W]‰k?s6®_‹ÓÝÝØö?ïB8Ò—×q-\€O_~)ŽŸ<…§žù Ö®^‰K/ùxÎÜç}_TU…Ç㪩xwß>@ii ž{éÔïß¿ßã'›GÕÚ´q=–.YˆO_þ©‘¿¤ŸúøÇ°dñ\õ§-ííH ½o¿]×qíUW`é’…X¹â\wͧ‡³ÔûŸ‰‰ðŸ¦¹Pâ>w‡ƒÛå†Ûí–~œBñ{’¹úÊËP‘y 2‹öŽ@e幩«gUAQ”‘ÓÉÍ×ቧŸEã&t÷ôÀçóáó7\ß½þÞßWÞ3Éý6®[;ªöÒÅ‹pãu׌|}ûÝ;pàà!ÔÕ7À0Œ1 Ÿ»þZ<ÿò«ÄM×_ E1wŸo×én bÁüä©p4ôôž¦%ßkeÍÊå£þrf*/¡£« FâÜ×`è: ½£3™exv $¯@wOö[®èœžÞ3øÎý;qª¹%yÍÀ©–Ü}ÿƒ¸wûø/6lSV(”\5li9w½íðÑãH$˜U•<•]T[‹Šòrìo:„ÖöN\¸j*ʧaéâÅx¯nú£Q”O›†µ59µdÑ8xgúú0w¸ä:.¼ðJ²9ÀO?‹íßÞf*ß3Ï=ؼ>Ù¼gͬ¬\vþËM×›ª%’z[ÛÚ±îÂÕ€C‡fWÉ¿¥i²¹ïÁ]#ÍñÞí·¾³c'Nµ´à¾ÿˆ]Ü;Î#´r 2óc·ùßÇÿ_4-ùoawO/ͯ…¿Ì‡·Þy¿û¿@kkžzv`˦@P `ó†u8|ôê÷ïÇú × à¢ ëÐÖÞ·ßy›Ö­…’ñÞ%F"C70tvšðÇ?½ UU±|éÒ¼ŽÛÒچǞxK/Ćuâ÷ëð‡7þ˜3wgW7::»PßЈýûO°çù—0wÎl\}å_ `ó†õÐ4 Ͻø2ö7 àäÉfœ<Ù<ºÖXÏiÚ÷Ö¬\xòÙ=hØß„£Gã•×^‡ªªØ´aýøÿ™pøãè±ãX0¿&9[ …P áÞí·aÁüšä½­vüý0‰3È)bùÒ%P?êWhnmÅ7ÿöfüÍÝŠ‡þíÇxèßÙïâ‹6ãò´éÍÖáù—_ÅÐÐÖ­IÎ’6mX‹Gÿ9bñ86¬_{Þ±ö<ÿö¤-¹\.|ñ¦° fä<®axè_ÆÐÐþ毶Âëõ¢®¾?úS\¸feeYóýýíÛG}ýáÍñÕ/qätººª _ùÒçñ>Ž;ïûÜn7Ξ=‹‹·\„o}ýf³O'`ÕòeøÌå—â×Ï¿ˆ;ïû€äuÏ­Ÿ»µÃYIìéŸýä¼ï•‡BØõ½ñŸ9¦d»°“þÞ©éò ù¡7áÇ–Ã>ØU¬AÒØ^|å5ôœ9ƒ«®¸ ^'ë>ÆþM˜7w6¬]hïìD}C#â±8-¬Å²¥KFýÌÐО|v¼®ºâ²‘ïÿê7¿ÅÀà ®¾òrxJK$Wuÿðæ[#û¨ªŠÊéX¹|ÙÈý†)¢ã¶¶uà÷o¼‰ª™•øÏù0à·þ„“§šqáªç/•;u¼Ù³f¢f^ æÍ©Îú´wt¢¡± }‘jæÍÅ¢óðûqàà!¼¿ïlX»‹.¼üÚïqº»g$c,dzϽ€Ó§ã“ÿé##59Цƒ‡á.qcŲ¥˜SýØ4~]°r€½ú†QqŒþø×óæ›lD4éÚ >ŶpZOD4!ðFq""¾›ˆH€owFD$ÀSl""6H""®b p‘†ˆH€‹4DD¼ID$ÀID$ÀID$ÀID$Pøm> .ÒÑäÆ$‘$‘@Á§ØÍ'ŽÊ‘ãÜ /úè'eŽƒˆÈqxŠMD$ÀID$ õc_#á^œîê@<ƒaè2KLU5x½^TTVÁ åõ3Ìaæ`;dæÐuCCCp¹\#ý[i ²³­ážnT×ÔÂY”Lº®#ÒF[óqÄcQ̨Êý‘œÌa/æ`;¤çˆÇà•H~lñ¸7ÈH¸ážn,^±.—ÔI©eš¦!4­~êàñú„ÿR2‡ý˜ƒ9ìžãpc=UCY h¹®”k§»:P]Së¸'-æraÖ¼Ztwv÷aŽâag™L9ªæÎGwW§”zR’ÆcQ”ùƒŽù¡?Dó±CÂíÌQ\Ìá,“%G™?€X¿”ZR¤¡yçG%2'äSsn×4 ºa·ç›á#f‡fNpaÎͲr¸£'LÍŒ³¾šœÛe刴ì3=63ü³WçÜ.+Ǿ7kzlf¬þÐ_äÜ.+Ç??x·é±™ñwßþnÎícå0ƒ·ù °A °A H\ŽrÂ…[c`y˜Cn «˜Ã,i Ò [2ÆO Åúa,¡5œ0æ‡9Ìã)6‘$‘$‘il©asÈ­asÈ­aUñÆÀ$‘@qW±m^þå*¶ÜNsÈÃæqID$ÀID$ÀE[jXÅrkXÅrkXÅE"¢qÇID$ÀUlj8a Ì!sÈ­1‘ÆÀ$‘il©asÈ­asÈ­aiˆˆÆ$‘$‘ßQ܆NsÈÃrkL¤1HiªªB7thjî i‰.çü e:ÔcÌ7Çožì¡eÈý'@VŽXIuA£Ë_qrxf.+htù+NŽå›.)htù+NޝmÛ^Ðèòg-‡Rªx¼^DûÂ2JÙ*Ããñ ·3Gq1‡³L–ý}}(͑à ) 2šŽÎ¶fº.£œ-t}í­Í”W÷aŽâag™L9:ÚZ˜V.¥ž¤BY „#Mûîí…n2ÊJ¡½=8ÒÔˆ`¨`H¸/sØ9˜Ãé9ÁiðçÈaF¶ÿ)ÃÉk”n>áÇ–hdWúÅb1Dúú ÷"ÂpÈ“§ª*<|Áü ¼^oÎý™Ã^ÌÁvHφ (çZ[ii)|eþmöè~DÄœ0À@òâæ¨ œÒV±½^/\.<> ]G Ë]Eªið”–Âív¹?sØ‹9˜Ã™9¤Ô•øRCÀívçõ$;s8 s8ËdÉ‘Þ(ND$ÀID$ÀID$ÀID$ u‘&îÅé®Ä£1†3n&UU ^¯•UyßÅöaæ°C!9ò!­Av¶µ ÜÓêšZø!hš&«´%º®#ÒF[óqÄcQ̨Êýúcæ°s0‡Òs Äcð‡ä¼’FJƒŒ„{îéÆâkàrI”Z¦iBÓÊá÷p°¡¯Oø/ sØ9˜Ãé97ÖCQ5”‚–ëJ¹yº«Õ5µŽ{ÒÒi.fÍ«Ewg‡pæ(æp–É”£jî|twuJ©'%i<E™?蘻êEü šngŽâbg™,9Êü Ää¼µ¢”ièF^×"JJJdNhpp0çvMÓr¾À>ß÷—4=63î\’s;sŒ¶½ÿÓc3cGÙ†œÛeåøÛúgLÍŒ®º:çvY9®|èNÓc3cÏ­÷çÜ>V3x›‘$‘$‘€Äå('\¸å£Ë­asÈ­as˜ÅO5´¡†ÆÀò0‡Üi <Å&"`ƒ$"`ƒ$"à"-5¬b¹5¬b¹5¬*Þ8ƒ$"à*¶ 5œ0æ‡9äÖ˜Hcà ’ˆH€ ’ˆH€‹4¶Ô°Š9äÖ°Š9äÖ°Š‹4DD㎠’ˆH€«Ø6Ôp˜Cæ[c"3H"".ÒØRÃ*æ[Ã*æ[Ã*.Ò;6H""6H""®bÛPà c`y˜Cn‰4) RUUè†MÍ=!Få|˜w¡ C‡šcŒùæ¸-Z+yd™rÿ `ŽÑî)]SÐèòWœÿ´ìŠ‚F—¿âäxæ–{ œ Ör˜!¥ŠÇëE´/,£”­"á0<Ÿp;ss8ËdÉÑßׇÒ9ÌÒ ¡éèlk†¡ë2ÊÙBׇÐÞÚŒ@y…pæ(æp–É”££­iåRêIj!”B8Ò´áÞ^è†!£¬ºa ÜÛƒ#M†Ê†„û2‡ý˜ƒ9ìž#œŽf(‚ï)H6O7€ÀðcK´?²+ý‡b±"}}ˆ†{Ga8äÉSU¾`þ@^¯7çþÌa/æ`;¤çCP”s­­´´¾2ÿ6{ô ?¢âÎ` yqsÔNi«Ø^¯.— Ÿ†®#á„å.Š¢@Õ4xJKáv»ÇÜŸ9ìÅÌa‡ÌRêJ|©!àv»óz’Ž9œ…9œe²äÈo'"`ƒ$"`ƒ$"`ƒ$"ºH ÷âtWâÑ Ã7“ªª¯×‹ŠÊª¼ïbû0sØ¡ùÖ ;ÛZîéFuM-ü4M“UÚ]×é £­ù8â±(fTUçÜŸ9ìÅÌa‡ôñü!9¯¤‘Ò #á^„{º±xŸ\R'¥–iš†Ð´røýl¨ƒÇëþ Ãöcæ°CzŽÃõPT e åºR®Ažîê@uM­ãž´tšË…YójÑÝÙ!܇9Ї9œe2娚;Ý]RêIIEQæ:æ®z ˆæc‡„Û™£¸˜ÃY&KŽ219o­(¥Aº‘×µˆhI‰ŒÃ ùsn×4-ç ì§ZŽ–~{ߟsvYYÎí²r¼Y_ozlf|hÕªœÛeåØùÐC¦ÇfÆm·Þšs»¬g‡Nš›n×¼œÛÇÊaoó!¢I'uÀêåç^L "*ªi(--µ^GÂXˆˆ%!é[â Ò nùÁèrkXÅrkXÅfñS m¨á„10‡<Ì!·ÆDO±‰ˆØ ‰ˆØ ‰ˆ¸HcK «˜Cn «˜Cn «Š7Î ‰ˆ¸ŠmC 'Œ9äa¹5&Ò8ƒ$"`ƒ$"à"-5¬b¹5¬b¹5¬â" Ѹcƒ$"à*¶ 5œ0æ‡9äÖ˜Hcà ’ˆH€‹4¶Ô°Š9äÖ°Š9äÖ°Š‹4DD㎠’ˆH€ ’ˆH€«Ø6Ôp˜Cæ[c"AJƒTUº¡CSsOHK¢ö~óX C‡šcŒS-ÇÌR{?ß{¬‹é²rlZvAA£Ë_qr|ó–› ]þŠ“CÁ¬‚F—?k9ÌRÅãõ"Ú–QÊV‘pO¸9Š‹9œeªä0CJƒ „¦£³­†®Ë(g ]B{k3åÂ}˜£x˜ÃY¦R3$5ÈÊ!iÚpo/tIŸI+ƒn÷öàHS#‚¡r‚!á¾Ìa?æ`;˜Éa†"øž‚dótpðð ?¶Dû#»Ò(‹!Òׇh¸ñx†Cž ]G Ë]Eªið”–Âív¹?sØ‹9˜ÃfsäKâK ·Û-upã…9œ…9œe²äÈo'"`ƒ$"`ƒ$"`ƒ$"ºH ÷âtWâÑ Ã7“ªª¯×‹ŠÊ*øó¼7Š9ìÃÌa‡BräCZƒìlkA¸§Õ5µðBÐ4MViKt]G¤/Œ¶æãˆÇ¢˜QUsæ°s0‡ÌæÈ—” ÷"ÜÓÅ+ÖÀå’:)µLÓ4„¦•Ãïà`C<^Ÿð_æ°s0‡Ìä0CÊ5ÈÓ]¨®©uÜ“–Ns¹0k^-º;;„û0Gñ0‡³L¥fHIEQæ:æ®z ˆæc‡„Û™£¸˜ÃY¦J3¤4HC7òºáî|[Æá„ÎVnʹ]Ó´œ/°Ÿj9"‡^5=63ü‹?‘s»¬û^ý™é±™±ú_ȹ]VŽÞ±ÍôØÌø»í»rn—•£¤´ÔôØÌȹ}¬fð6""6H""6H""‰ËQN¸pËF—[Ã*æ[Ã*æ0‹ŸjhC 'Œ9äa¹5&ÒxŠMD$ÀID$ÀID$ÀE[jXÅrkXÅrkXU¼1pID$ÀUlj8a Ì!sÈ­1‘ÆÀ$‘$‘il©asÈ­asÈ­aiˆˆÆ$‘W±m¨á„10‡<Ì!·ÆDgDD\¤±¥†UÌ!·†UÌ!·†U\¤!"wlDDlDD\Ŷ¡†ÆÀò0‡Üi R¤ªªÐ šš{B+_+ãp9ä~æ C‡šcŒS-‡§ö£.Åɱüc74ºü'Ç×nßYÐèòWœÑþHA£ËŸµfH©âñzí Ë(e«H8 Ç'ÜÎÅÅÎ2Ur˜!¥ABÓÑÙÖ C×e”³…®¡½µò á>ÌQ<Ìá,S)‡’deŽ4íG¸·ºaÈ(+…n÷öàHS#‚¡r‚!á¾Ìa?æ`;˜Éa†"øž‚dótpðð ?¶Dû#»Ò(‹!Òׇh¸ñx†Cž ]G Ë]Eªið”–Âív¹?sØ‹9˜ÃfsäKâK ·Û-upã…9œ…9œe²äÈo'"`ƒ$"`ƒ$"`ƒ$"ºH ÷âtWâÑ Ã7“ªª¯×‹ŠÊ*øó¼7Š9ìÃÌa‡BräCZƒìlkA¸§Õ5µðBÐ4MViKt]G¤/Œ¶æãˆÇ¢˜QUsæ°s0‡ÌæÈ—” ÷"ÜÓÅ+ÖÀå’:)µLÓ4„¦•Ãïà`C<^Ÿð_æ°s0‡Ìä0CÊ5ÈÓ]¨®©uÜ“–Ns¹0k^-º;;„û0Gñ0‡³L¥fHIEQæ:æ®z ˆæc‡„Û™£¸˜ÃY¦J3¤4HC7òºá×Ë8œÐÙજÛ5MËùû|s””–˜›ƒƒ9·3Çh%¥ý¦ÇfÆà@YÎíòrØû÷cp X?2=63n͹}¬fð6""6H""6H""‰ËQN¸pËF—[Ã*æ[Ã*æ0‹ŸjhC 'Œ9äa¹5&ÒxŠMD$ÀID$ÀID$ÀE[jXÅrkXÅrkXU¼1pID$ÀUlj8a Ì!sÈ­1‘ÆÀ$‘$‘il©asÈ­asÈ­aiˆˆÆ$‘W±m¨á„10‡<Ì!·ÆDgDD\¤±¥†UÌ!·†UÌ!·†U\¤!"wlDDlDD\Ŷ¡†ÆÀò0‡Üi R¤ªªÐ šš{Bó] ãp9ä~æ C‡šcŒùæˆöÛû9ÌcaŽÑ¢ýö~¾wñþ\M–¿74ºüYËa†”*¯Ѿ°ŒR¶Š„Ãðx|ÂíÌQ\Ìá,S%‡Rd 4mÍ0t]F9[èúÚ[›(¯îÃÅÃÎ2•r˜!©A†PáHÓ~„{{¡†Œ²Rè†poŽ45"*G îËöcæ°ƒ™f(‚ï)H6O7€ÀðcK´?²+ý‡b±"}}ˆ†{Ga8äÉSU¾`þ@^¯7çþÌa/æ`;Œ•ÃWæß`/€¾áG@ÀYC $/nŽºÀ)mÛëõÂårÁãóÁÐu$œ°Ü@Q¨šOi)Ün÷˜û3‡½˜ƒ9ì`6G¾$¾Ôp»ÝR7^˜ÃY˜ÃY&KŽ|˜½<±‰XøIDAT™@–i(‘ÃÔ»Æj‰Œ_3¿OD4ˆzXÎ^–Ï 2½s3‰ˆ&ŠlýkÌ>–ï)vzq}øAD4Q¤ú–©Ižh‘&‘å1ªAúÊüßàP‚ä­@.$nªéf»…ˆˆÈ©†—êSCHÞÂ3 †ì 2óqž|V±Ó›cê ï"y_¤É{$K†ki`ƒ$¢âKo:’½jÉ{cHÞ÷˜~Ïc^³Èl 2sÍ-}ö˜:èY8×áïiÃlŽDT|©~•š-¦zU|ø×TƒLÍ$3gŽç5Ì\3Èl§Ö©F˜j€©ï¹qnöÈIDã!sB—:ÅNÍ$‡¿—íT;+3§ØCH6ÀÁ´ï§f”©ÙcªA‡ô™j’ér£_Z˜ÓX 2}ʪ Ý¡ÓgpIDã#Û¢rª!žMû5Õ<Ǽq|¬Sl 8wkOú9~jÖÈæHDN ºó&uíQ´šU¾§Ø©¦˜yŽÏæHDN“­I¦7Ë1cJ®†¦dù5½fkŒlD4ÞÒ_)“Þ(3Ÿ¹ïyÆjhJÆï3›a欑 ’ˆÆ[æ­;é³Ål7† g’ù4´Ì}D³E6G"rŠ|ßœ"çi¶™¦&Ú—‘ˆœJÔóz-v¡ÍM‘ˆ&¾ 9ÊÿH]¶çWD5IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/layout_grid.png0000664000000000000000000002363615074673150022504 0ustar00rootroot‰PNG  IHDR,¨Z+ÓsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timejue 08 dic 2022 22:15:32ÝÝÇ IDATxœíÝw|TUÚÀñßÌdBÊ”L*„$$! †é *" XAQP¬¸nyÕ]W,¬®e×]uEeõu}w¤ (E@e-¤B %¡†’NH1@™™÷)Ì$“ÂdR†<ßÏç~’¹sï¹gÎÜ<9÷Ü{Ÿ B!„B!„B!„ð…—”)„ðNfOæ‰àR_¸„è¸ê TÍ `î•Úë)šøžâÊV; ™›ø^“\n0q˜ üîîv„ÞÇUp27ð»«õt9¤v R8LÊZ¯ë \Bˆ+[íàä8™j½®½|£šL\)[ r5IТãq¬LõLµƒ™ãúõòiB%êëQ©~ª€` ЬeKÀ¢ãp <5@P%€Ñ:™~:®« ‘ ÕXÀª¬l=([ò4@ŠeŸß;xÐÀ)(0`–%D‡§Àl6™KRwîYzï”)+£À,ÁLÁ¥ e \­ÆKíC@Ç@¥‚R(лýÁ„W43”Þ9qÒÿìÛ·oP \ĸl½.W‡ˆu4°{W¶ž•uòtƒ ñå²%sÍæ&Z !:0ŠšÛ&ÞýÈþýû·ç€j,A«ç±-¨'h5°\õ¬|±ŒQõ;yüÈç =+!DS)Jb»÷¸ØeŒË´\õ´êPÖWj­ßmAËv(¶dñ‚IH°B\³á³óîÂr‚N%¦¨p¾ªêéL5v[ã¡ KÏʸêÄñ#_(ÀÐìú !:³ÉT×£×}Àa KOË6¦U{ÞICcO®Î Ú—A¡0yö¶F!DG P* X:;jœß•4r¦°©×aÕX˜äÒ!„;Ì çCBÛç jJ«vÀò|¥s%„h_.ÅÇ€e›.kÐݦ¾ÃB•Gª,„è¨cIí[úê媇å*=Lí ¥ôp^.!DÇâx{_}ÁªNO«)·æ¸ºÑY%ñJÑ ŽÁÊU—ê X®®‰p Z2àÞFL&§²³9••Mqq ½ž^Wõ KDDƒëe9ÊŠ5_3yâ®êÑÝå2ß®[Ï/eeÜ7é®:ïíIÛÏácÇ\®7rĵtéÜðöÛÊŠ5ßà£R1ñö[Úº*ÂYíxâ*Þ\Öe Ž+;¢ÒÁj}YÙ9|øñŽ;^罿¼ø×ôëSïºÛRRÙ¹{/1]»Ò³ž€õßuë9•ÍkwÚ>¾úö{—ë%ÄÇѹ¬å«×àïçÇ Xí[¹ó.'[C­y²ZSAa!Ͻü/ÖpËØÑ ¸¦/Z­–³g‹8q˜Ä«{ÒÐwr×·Ù%‚aƒ5¸œ…«÷-ó{h*ýkÆÐÐ&”ÙÖÚ{ýÚ§‰÷?ÂÕ½zòâ3¿G§ÓPvþ<3ÿù!Ò±z邿__ãz¹{Ó²¶²?]HUU5Oüz7ßtã¥7z$pÝð¡ö—‡Žcï¾Üuû­>zŒ“YÙ DiÙ9J)ãìÙ³é-;žÉdbçž4róò‰‰Ælnü:,4„訮uæ·n=¥eç¸nø¢"#1™L¬úæ[.^¼È„[ÇÑ©S'Òátv5/Ò­[4I}zÛ×ÿiÛÏÔÔ>d)»vqîÜy’úö!ºk$yù¤8ˆÊ‡k‡" À¾Ž}®¾Š{ör±ú"“’ ið3TVV±gß~Μ)$**’IýP(d—v%:ª+‡ŽðÊoó·?Ï@¡PðÚ39qê4Q‘‘Í)Ú­¿Ü€ui#ò«ÕTTT°;ma¡!ŒyCƒmøðQ>_±ŠŒCGH;p€¸è(2Ožâó«Ðiµ$ÄÇSUUÍkoÍäБ£u i ü¢¢brróì¯UJ%#"Ðh4ügîBÌàﯼȺ ›X´tãFÂßÏŸ?žÃúM?9•uíÐÁ¼ðôSlÚºýÓùì‹ V«sã ¬Û¸‰ššV~õ5üã |}}Ù´u;GŽCåãCIi)þþþ¼òüt{õtù™²ssùÛÛ³((,D¡P`6›˜”ÄË/<#AË…¿üé9^þû[œ:Í+…BÁÉÓY„‡†ò꟞õD¸¬F—´0^àtv.1]£P*-—Îí;˜Nú¡#öe AzÆe}4ó=ô½Ž«z$yò”S™ß|¿ŽCGŽ2ðš~<úÀýdž<ÉG³çQ]]Ý`]æ,\ìô:$8˜OÿõO®6”M[¶“º{ß®[Ïâå+ˆ cÚ÷pëØ1 ê ñqÝ8[Ṫʶ”TŽ8AB\UUÕŒ3”ë‡áÛuX¿é'~Ú¾§÷k‚ô:f/\Ìé¬l¶§îdäˆkËáɽïäÆë¯eÓÖí,ûr ³,âŸoýÍeýÿ3w……¼òützöLà£OæòsêNvîÙËàýý.:šà`þþò‹– •• XzÙ¯¿<ƒðÐÐV¯ÛË,]¬VsîÂyÀÒæ¶vß{à _®ùƾL\·n}£ýý)wOàŽ[ÆÚß·Í·•±gÿ~îºó6¢ºv!ªkV~µ–ÓYÙ.¿[ÛœÆÝõÒ¡€¿¿¿}ùßýêadâãy Q*•üiúÓtòóÅŒ™øønDEuaÿÁ Ïb ¿ €ìÜ<ºÇÅÚË=ò:¢£º2åßôAú ®»ÖrÈ{Ó #˜¿ø òò œê8vÔHÂÂB¸oÒD’7oåÄ©Ó\(¿`?t´}îêêjÒA«Ñp43“£™™¨T–ð§²³4àš¦)ˆJ僯Ú×þZí£F­V·I –ˆŽ²ˆSYY˜L&”J%wß~+ão…Ñdäžy¡Î:>ꆿڢ¢"{囹F Âð!ƒ\¾l0pûø±,_õýú$Ò»×Uö÷ö¤ígæÿ¢S'_úõî±Æ€ÉhtYVPeœÍño"((£Éäb P(„…‡ræìY~);ç°**ª0™LÔd[k %× Jlttã¾*)ý…Wßx›ìœ\û˜Uvn.¯½1“×_ž!¨u3L¹°¤ƒÕj‚Cˆ £ °ï~ÜÈ­cG@`@&Ç?ÞúžGÝùAz=yùg8s¦ðÒ zC¹ë+×Ayy9¬ãTû¤säh&=âX¼l%UUÕü{Ö;éu|ùõZËø™«zÖWwWõqxm2™8yê4J¥’àà:uÖë´øùuââÅ‹<ñø4üýü.Sð·™³ìÁêõ—gðêßß¶Ž¾Ç¬7_oÕú4v/¡h ¿}ìaæ,øŒ9 >#íÀAdb¥Ãaáåè“xµ¥¼…‹ÉÎÍeÇ®=œ),lt½ââròòœ¦Êª*æ~¶„¢âî›4³ÙÌG³çb´ö ÊË+0›Í;žIEe%‡] ö»iÙª5äðÕ¿çÂ…r’úôÆW­@¥RQ^YAU•elîÚ!C¨©©á?sPYUEEe%»öîóX]®4'Nž"®[Œ¥7¥×cÐëyýåÄu‹áĩӭ^ŸfÊ¿£ÖÔ¿_žûÃÌYðkø‘µ?üh/"<Œ)wO éO7sç-ãø9uû¦óûç_B¥RÙ¥3YÙ9 ¬s-†EÎó^~î(” ÖoÚÂÐA™r÷ŠŠKX·q_~½–{'ÞÁÈë†óùÊÕ¼ñÞû( ‚ Aµêéê‘v®Þ«»Î†Í[ø1y3`9,}ìÁûìïõ¾ª';vïåÁß<Á»‡î»‡SYYlÞº-ÛSKÏìÃwÞ$*²K½Ÿ»£ZµxžÃ+K›ô:f½ùW§y­¥ƒî¢µ];t0ý“úrôx&§³sðUûÙ™ž ÝñññÁ \Õ3)“&Ò£{œÓwT{~``3_…»öRVVF¿>‰(UJ¶lßáò»íŸÔ—€Àï@—ÈÎL?Ä”I=òzÌÀƒS&l@©Tb4™˜|÷ºÇq*+›Îáá HêËêµßÑ-63pýðát‹C§Ób”*S&MD§ÕÚëÓ-:š)“&Ò»×UNu|íOÏq*;M@û'¡Õhìï?óÔïØ´e;F“ &½^ÇÛ¯¿ÂÞýÈÉÉC§ÓC—βO{W×@8Þ7hKØç‡%á–Ö: ;vøà¬Öª¤®¼ùÞûìÜÆÇ¼KXhËŠö%áªÞÓŸ±<=çPTâœ*¹Îˆ© º ïÕ„âÊ"cXâ «£ë°„×zéÙ§Ûº ¢•É »ÂkÈ–ÂkÈ–ÂkÈ•îB¯!Ká5dÐ]á5š1è.!KѺäPá5Üîaåœ>áÉz!D£ÜXC¯ Àù²RŠÎž¡²¼“ÉuöHÑtJ¥ ‚Ã"Ð蜳9J[ oÔÐ>}¹šukNa~.e%Åt‰‰E£Õ£R©šUF£‘óçÊÈÏ9EeE9¡–MÒÖÂ[Õ·O»Ãí€u¾¬”²’bûáã#·$zŠJ¥Bd@£Ñr4}~þ€YÚZx-×û´{ÜÞû‹Îž¡KL¬üµ•£c)*Èì0K[ ¯ç¸O»Ëí¿€ÊŠr5º&=-X¸G£Õ‘sòfÒÖâŠ`Û§ÝåvÀ2M2ŽÒÂT*•ý‘VÒÖâJà¸O»C®ÃBx XB¯!Ká5šyÚI[´µÍ XrÒªõH[ ÑNB±!yÇ33ðññ!<<œÇ¤oÞeü­©¼¼‚5ß|Ãø›Çb j|Ñ$Þ¾oœ=[ÄÞ}iäœ!®[7®> …ÂÕã@ES´‹1¬õÉÉlÞº•òŠ ÏžeÙŠ•Ü1é^Òöïor&“‰Yÿû!%%¥Nó¿X¾‚´<]e§í®þúîšrŸuû%-¶­ŽÈ›÷/¿úš©Ó¦ñÍwßsøèQ^~ýoüþÙç05ã´~G×.zXý“’xúÉ'쯧Ïx‘9óðá{ï6¹Œ¥Ë–3iâ †K=œ7nDíëKRŸ>­/@Uu5Ó~ó[Ôj_þòòKüñù߆ðÎ} ¦kW–ΟGHˆå©Ô'Ob꣱=e#†k‘m^éÚÉ »™ÚÃ=êFœïê䫿¥ž§OâÕÖ®~K=Ô³£byç¾0h ­>–zÆv‹¡{|,§³²1|¨çš¨i‡„®¤Ê ŸÃ¾õÉIݽÛi™y‹Qp¦¥õJp¥Ri¿*\©PZ*P©Tö±ƒÃGŽ2õái¬ON&ãÐa~óÔøøÓ¹örÞ±ƒ'Ÿ™ÎÌY³8•Í’/–óÈã¿¥ªªªN=mÁJ´oÙ7\)<[LxX˜›Ÿ\´³„fØ0OæÎ //ŸmÛfÕ²/.mÃúO¶Î6­ó~`*ÿ÷Él&Mœ@·˜n3šå«V1bØ0îšp§½Îo½û“ï™Ä#Làö[ná©éÏ2ö¦›ˆ‹3ôNLdÖ?ÞàÂ… Ü|Ç6oÝÆ˜Q£þ(®êèö,á´olOI¡ºªŠ¡ƒuÜï³™ÚeK§Ó¢ÑhyéÕ׸pá‚GË..)á`zw[wR€AЫGvíÙcŸ§ ÔØ ¤oïÞäæå{´.âòyë¾QYYÉûÿúˆ§ÞO`` GëÝ‘´›A÷¾‰‰üzÚ£ö׿zôî™úk¾YËÔ)“=¶¼ü||}}Ñj4Nó###)*®ÿ _@`€dKh#W¾ñ··ÞÆd°÷Ü„{šÙÃ2{hª[žVHÿ~ýÈÉÍÌ( ***\¬×Ðëºe‡ TWWST\ä´\qI ‘]:×[w?GK´MÇšê~~oÛ7fÏÇôtÞøË+(•ŠËZ÷ÊœÜ×. ÁríÌéì,º'ÎÏ©©ö÷«ªª0/]Ï¢P(P«Õœ9ãTN'ßNNóÂÃÈŽêÊ’Ï—Ùç8y’CG3tð –ú8ƒ¼ißXº|+V¯æ_ÿ|×~yƒp_»9$LÛ·Ÿ>ž @Ee{÷î#$$”;nÀ„;ncÅêÕüþÙçéÅŽÎg… Æ fæ¬5òn7–¸ØX®6„Oç/¤²ªŠþIIŒ¼~3ž}†~•Ì“'ˆˆˆ`Óæ-<ýÄrö¦òÖ}ãû×óþ‡1dð V­ùÚ>_«Ó2í¡›Ñ"—«¬p ‡Ii]ÆP¬SÔoŸ6.,"Ò#•P(h4T**•Šððpn¿e<=üJ¥¥¨Óé?f,f³™ÐÐ0~÷ø¯è™@÷îñX¯yÃõhñõõ¥{|<š@ }{÷&..–š‹éGhh(]##7v >>j‚ôA<þè£ :Ä© ¢£"éÓÍaŽ‚„øx"Â#êÿÀ€k®ÁÏÏÏ#íPX €§ÚÚÛxó¾QPXHt×®D„‡£V«íS@` }[¸åگ‚\>ùtÞ÷@6Pm.5€É:¹î%’¶¢K©Tb4Q)¥“ÖRL&£ýÔ½´µ¸8îÓîp{M?ÊÏ•¹½aѸóeeøùH[‹+†mŸv—ÛK«¡0?“ÑèöÆEýŒÆ òrЂ¥­ÅÁqŸv—Û‡„Z½ž‹Õ•dÉ ¼K:²x€ÑdâBÙ/äå ÓÐê,[¶Þª¾}Ún,µZ΂ÒÇ—’³gÈË>)Éõ=@©Tâç@PH­µZ m-¼V}û´[e5§"þþþ¨Õ*Œf£œÅò³Ù2À®V«ñ÷÷·Ï—¶Þª¾}Úͺ¬¡0?—²’bºÄÄ¢Ñêíù²…ûŒF#çÏ•‘ŸsŠšê*B#ºÒÖÂ{Õ·O»Ãí€u¾¬”²’bûáãÓn²Ôx=•J…>È€F£åhú>üü³´µðZ®÷i÷¸½÷=C—˜Xùj!*:GÇRT‡Ya–¶^ÏqŸv—Û•åh´Þñ¸po¥ÕéÉ9y ³5:É)/¼žF«#çä1·×w;`™Œ&Gia*• £õl ´µ¸8îÓî|XB¯!7? !¼†\.-„ðrÚÉkHwV X^B¿…€%Ú¹ É›8ž™ €áááŒ>Œ ½÷]Rc4Y´d)£FÞ@·˜˜¶®ŽW’1,Ñ®­ONfóÖ­”WTPxö,ËV¬äŽI÷’¶“Ë0™LÌúß)))ušÿÅò¤8àé*×kÎü|ôñ'œ XÂë¤Ê _Ÿ>ö×ë“7’º{·Ó2ó-¢àL!Jë]J¥Ò~Ç€R¡´þT R©P(,A?|ä(SžÆúäd2æ7Oý?k/÷ç;xò™éÌœ5‹ÓYÙ,ùb9<þ[ªªªê­ïý›ǑԷ/ÍýƒíèdÐÝKtس„fØ0OæÎ //ŸmÛfÕ²/.µ‰õw6²Î{ø©üß'³™4q‚}°ûæ1£Y¾j#† ã® wZ7Ã[ï¾Çä{&ñÈS¸ý–[xjú³Œ½é&âbcÁ ½™õ·¸pá7ß1Í[·1fÔ¨:ÕOÙ‘ÊÎÝ»Yøé{ýÌ®ê*š¤™=¬¶îZv„I8Òé´h4Z^zõ5.\¸àѲ‹KJ8˜žÁÝÖ0hàzõèÁ®={ìó4ûïôíݛܼü:å•;Ï3ßáÕ—^¤“¯/ ª¹¤‡%Ú½¾‰‰üzÚ£ö׿zôî™úk¾YËÔ)“=¶¼ü||}}Ñj4Nó###)*.©w½€À—™4Þ™5 ???RRw’’º€’ÒRÖoÜÈñ'˜4qzÎcõï$`yŽþ¯ùÒç×jé߯9¹9€…BAEEuÛ¨vOµ¾^«e^ˆÁ@uu5EÅE„_z²KqI Ç ©µníßë–ݳgbb¢1kœæ›L&ë<éE_.¹ùYx“ÉÄéì,†@Dx8[¶o·¿_UU…Ñx)…‰B¡@­VSpæŒÓ›|;QpæŒýuxxÑQ]Yòù2~ÿÄï8qò$‡ŽæõWÿ|Ùõ|èþûêÌ[·~#cGfäõ#.»(Xþˆ<@¥R¡2pU~).â|Ù/ÒÎ-ÄU[»«],K‚¶lºw, Ú~¶¦˜…†´9ª?AÛöy¶mC_~6„ü‚ª««æ¥ìH »µîžPtö ]bbññiâ+ŠÊLJÎѱž‘vnaŽmí®6¿Òl Ú>´…X´™´=W+A›e4^¡Àš íýf$h ­õyjÿn¦öç]úÅ2Ö~÷}ûö!8È@ÆáCdeçòâóÓÑk5kŸÊŠr5ºK…û4Z9'aV íÜÂlmí®6ÿWrÓ(çma¡¡Œ¾ñR‚6€è¨(>_0ŸÍ[, ÚyðvïM#<üRÈ7_·&h«¨´ìM2™è¨(NgefO2hKÎ#e‡%AÛ”I–m6C‡ ¦¢Òùðsܘ1t‰¯S÷gþð#—0°ÿ5 <È£cW&£IOZJ¥²_*"íܲÛÚÍJà×ûI*×Òîµ ÷0´kreÛ¿;vn ûw§¸À¯]Ža !„+°„^£ÍǰDSÉ@pëvnÏ$`y 9qÕ:¤Û7 XȆäMµ’%†{U²Äå_®¢´Ô9çYÏ=yýumT#×¼½mŽ;FzÆ!*++¹úê^-–¦ér4k Ël–©¥'OZŸœÌæ­[)¯¨pH–x¯W$KX¸d ™'OQ^QaŸª«Ï¢ÑÚ¼½«ª«yý·xú¹çIIM%eçNž}áOuR<µH3,òIDATéau0u“%¾Èœù øð½w›\ÆÒeË]$KÜØ¢É*Ë+˜:e2}{'¶Ø6<Å›Ûyμù²bÉb§ä”í,¯á¡\>µ.m»/\¸Àò•_2çßào¯¯Â~ÅfÛ®f^Ö`–©Å§–å-ÉF#ÕÕÕ$oÞÂÂÅKY·~ƒÇÓµ$oiçc'NàççG|\,Ó3XºlÉ›·´›ükÒÃò=Ybee5®¹†Üü|T*_­ý/ï¼ÿÿœù6‰½zá)½ssó áíYï“yâ ñÝY´d)+׬áƒwfÚƒd[‘ G;0oJ–àÏ>ü€—g¼À‹Ï=Ë‹п_?Þ|»é*i+ÞÔÎÆšŽÏ$.&†Oþõ!/Lÿ#‹æÎaÿƒlݶݣuw‡¬Æ–,ñ×ÓåO=É¢¹s8rìk¾YëÑí´T²D¥RÉý“'sôøqäJó4omçÐÐPüüü˜|Ï$û¼`ƒÁpøèQÏUÜM°¼†'ÇÃ.ÍÓj­És³C²ÄÚë5ôºnÙ!ƒ5Yb‘Ór–d‰ë­ÏåLJ•e,G­öi‘¶éˆíÛ-šòòrrórëlWèáö¹|°:8K²Ä,º'¶d‰©ö÷›Ÿ,q™}^s’%þrîœÓãÖÌf3+WÅ5Iý¼"áž·´sDx8C‡ bö¼öyÅ%%ìÚ³‡þý“X³u´ÿoZx”%YâlÀ1Yb¨5Y"ÉŸ¯•,ÑB¡PX“%~ÐŒd‰auê՘ɛøà£3°Á†`Ò32(¯¨äƒwg6¿QZ€·¶3ÀsOÿ'ÿø,ÿÏSÄÇŲíç&ß3‰ž ÍjOp•­LsN,—òbu²NQ¿}|Ú¸°Î‘­UÏ«° €°ˆæ·µB¡@£Ñ R©P©T„‡‡sû-ãyìá‡ì×étŒ3³ÙLhh¿{üWôLH {÷x¬×팼áz4øúúÒ=>M †¾½{KÍÅ‹t#44”®‘‘Œ;5Aú ôQ†u|f£‚è¨HºÅts˜£ !>žˆð§º÷êÙ“ëF\K'??üýü5r$|êI C³Û °Àòü€ŽÞÎzž[Çä§“ŸM½ñcÇ4»]l rùäÓyßÙ@µur̃eË…UG³ø%& ô؇®¥§í 1I’%¶¤ô4K¢Diç–—ž¶Óí~rHè5š7X)šJÚ¹=kû'? !Dµ‹§æ!DSÈe B¯!cX^B¿[‡´sûævÀR*•M&TJ餵“Éh? n4¥­[ˆ´sëqlkw\îšöëëýüý)?Wæö†EãΗ•á瀴uË’vn=¶¶ÆÍ{u XæZ?íóµú ós0—³=ÑDFc y9h ÁH[·içÖãØÖ¸ˆ)µ~ºÔ”CBÇ‚ìW¡jõz.VW’y$ƒð.QêtÒ•ö£ÉÄ…²_(ÈËA§7 ÕY\ míYÒέ§ž¶vŠ'ÖEím5u ˱p#`T«Õè !(}|)9{†¼ì“í&+¡7S*•øù†F«C­VH[{˜´së©§­Ö©Á[qj«/`¹Ê á°5Ïþ€/–Ûw|°bÚþ%µmjB!D[² [ܨÁrÛM5Pë€Õhš¦ÖÞèn,÷úc¹ÏÐ×Z– XBç€eÄ;ª±Ü/XåÞÁ&ÝðìÈUÀ2s)Ø8ö®l½Tq)0™¬óTÖI+!Ä¥øaëMÙbG¥õ§-`ÙzZ®²:i¨‡åêPИlÉ6OÍ¥Þ•,!ÔíðØ m=-[ZW‡†.]Î!a –€Tí0ßÖã²õ®lK!À9`Ù‚–càªÁ9Lƒ XŽ]:…uCà1Û“ÿ !:6W'ílê¢ÃO[0kôBÒÆ ±nk¶ù¶ ØzU¬„®Ôw¥m쪾³….5õФj“J°B4ÆUÐr ^*›†ŒÂÅOÇàä*PIÀBÔæê™e&¿×^¶ŽÆŒ¢Ö﵃Sí^•,!Dmõ=ÑÕëÚË;iJ€©½L}½) VBˆú4õfç /'ÈÔ·¬*!DSÕšt/¡»ÁF‚”¢¹$¿«B!„B!„¸âü?¸Ö_Á‚HIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/layout_headerbar.png0000664000000000000000000001613615074673150023471 0ustar00rootroot‰PNG  IHDR¬wQ´sBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timejue 08 dic 2022 22:14:47ˆJØê¾IDATxœíÝy|Se¢‡ñ_––Ò…¶PZ–ʾƒ²É""‚²) ¨¨è8Îr¯:sïuÜ÷gtÁQ\FFD6dAdkKYl‹º'¹¤IÓ4)iiiÞöùòɧô¤999…óä=ç$‘PcCæ 0«.gVq 6ÂMS°PQÀjÿÛYB¼ÐxùÉâu!©iL…ÉRÍßk{?³Š“«š¿º]µjÿY|.V¿ïƒ… ÐxùÇÉ÷âôûÞÿçO+Ô˜Š”'T.D š–@±r¹øÇÌ÷öAÙCXˆ`#*›ÏW›¤–’’$µÔ¬|Þ šßð”I*–”/阤L ñ¼ßn8ûdÙrå?®©“'ªyT”wzN^ž–~¶B©íÚêüáÃêå¾—,]¦ãùùºfúåg4Ïc$«Å¢øøõêÞUÒRëb1½²²³µzͺ€×õìÞ]çôëS§÷WWÞýà#Ùm6M½tbC/JƒrþµºÝ†ÏWÕñ’4 g¬úíþ²+t0#CƒTqq±V¬Z­'ž~F/>÷ŒôëÒ<œN§žñ%Ýtà JLLðN_°ðõìÕSúö­¯Å¯%óŸK-YºLûÔÅVó¨Š<æääjþ;ïiØ:øyõrßÿ^ºL32uÍôig4Ïcð7eòýìúkÏhÞ¾2³iþ;ï¼nÚ¥uN¿Þuv_uiáû¨yT”¦^:¡¡¥‰0»PWÂv„%Iç ;~}«÷û»î¹WŸ=G~æéçñÖÛ 5}ÚÔJÁútùrEDF†a°NfÿõϲZ¤µ6éå¿ÏÖ‡‹—èªË§(.&¦NïgÔˆaºúò)•¦ÅÆÆÖé} ~4¦‘Ò´koT¯žÝuï·«E‹’¤ü“'5ë¹?ë›;õþ[sx Ï$XÕF¿.žTý¯!ƒjÉÒ¥ÞiŸ­X¥øq4ð\ïÏÌþç\Mž8^­“’ôúœ7$Io¿»H ññºþÚZ±ús>rT«×¬QNNŽÆŽ­Î:I’ŽççëË/7(ïxžú÷í«Þ½zzçûå†j™˜¨²2‡¶lÛªèèhs¡b¢£ëà±ú<äÆÂÿ#Ø\§ÿ“«­ÛwèTAzwï®.Ó½×ÈÈÔî={•ò¤RZ'iÈ sQñf N§S7oѡÇ•ž–Vñ"Ëçÿî‡)½CuNï¨ ›7«y³(Q±»2ÒnWtt´Æ_4F-YªŒÌ,9K’Ë}ß;vîÒÁ¬,••–ªc‡4 è[± oõšu:yê”ÆŽ¥ _}­OœÐ˜Q#+í&õ,g‹ØX¥µo_enúz‹vïÙ§î];kà€þÞùfeÖ𡃕־Ýi—¡ÌáÐð!ƒõå¦M:qâ¤ôë«´öí”}øˆ¶|³]v›]#άèòÇ;wïÑw»v벉ãõ寝t,'W½{vS×òÿ#•ø¬g—Ë¥-ßìÐÁŒ %ÄÇkèàŠ2ú=ðÂè?ãYZ”´Ôöúvç.ýáÑ'õÈÿÝ#‹Å¢þ8KûTj»va±JÂz„åoÇÎoÕßgT´lÅr¥¥¦V Öëÿü§¨ÖII²–¿ZÝjµz_¹nµXË¿Zd³Ùd±¸ù}·k·îüŸß«oŸÞj¥ÿúŠn¸îÝüóŸI’Ö­_¯ÅK>Qû¶mÕ«gO}õõ½1÷-Í}ýïjfôÌú‘‘‘¥ü'¼ßÊ>\ågÖmبçÿòŠŠŠ‹½¿‡ëg\©éS.ÕòÕ_è…—_©ôómÛ$ë™GRtt´Š‹KôÀã³´s×î ËPÝü%iáû*¥uký˜Ÿ¯ã?æ«wÏî•‚å‘}ø¨Žýðƒúõ饸x÷3Ï—^ý‡–­\]éçFœ7DÿsÇm’¤•kÖjûŽZ¾úsíÚ³Wv»]ãF ¸œ'O(+;»Ò´6ÉÉJm×N³žQ‘ö½ôÜ,Ï;®çþò7¥µo§+§^Ò2lÛ¾Co.xG9¹¹’¤ˆˆ»ð-]¾Reee’¤wÿõ/½ðÄcŠŒŒÔw»vëõ¹óõÙªÏu #S’û#/nšy­¦LpùKJKõȬg´mû·²X,r¹\jݺ•žzøA%”¯/„¿ÿ[Ý÷èã:‘©?<ö¤,‹öÌPrR’îÿýÝ ½x’ê)Xur†KÚ¶}‡^ùÇlIRvöa­Y»Nï½½ bþåÏÖ«Ü_ù´ŸÌ¼NyåUMŸ6U;t$]2n¬¾÷žF¦Ë§Nñ.ïãO?£«¯œ®g^'IºtâDÝv×ݺø¢‹Ô)=]rI}z÷Ö³O<.I:uê”.¹lªV}±FãÆŒ©ƒܸ<øÄSÕ^òd^|õ5ÅDGë™?>$›Í¦‡žxJó.Ò%cÇh`ÿ~ºýW¿P÷ÎUæthÞÛ‹´á«ÍúÏò•š6y¢>úd©vîÚ­Açô×Og^«½û÷ë¥W_WIIIHó÷ìÖ;‘©!ÏÕ˜Q#•˜Pù„žoù,’Ê9NuëÚE.—K‹E“.§Á瞣Î:ꇜ\ýùo¯iÍ—´gß>ïh¤°¨H……Eúï[nVTófŠŒŒ ¸.V~±F+¿XSiÚ_Ÿ›¥6))šyÕtýãÍ·4oá"ÌÈÅbÑßz³ìv{HËP\\¢ ãÎÓ¨áCõñÒÏ´låj­^»Vwüê—Jˆo¡Wߘ«ƒ™Z»a£Fá½ÿ¤¤Vúíí·ê`f¦^xùU½¹`¡FVeIÒ¢kÛöouÕ´)ºbÊd}üɧzcÁB-ú×â:=æw6…º :jt­æ¿~õÊZÝ®>µjÙRÞw¯7Z’Ô:©•¾ï%'%5ðÒ¹Õ:X®³<>lÑ"N±±qúßûÐ<¬˜:<Ž›—§í;¾ÕŸ|Ž 4P=»uӦ͛ÝÁ’Sq\!&&Fýúô 8r¨­³½NëÓ”IÝÜç,ÁÜ<-]¾²ü9†K»¾ß£“' ”Ò9Ù{¦\LtŒŽ£Ê:tH=ºuÕ…çЮ={”™uXññq’¤¬CÙrÉ¥ÍÛ¶I’.Ÿ2Y©íÛ*µ}[½ûábÌÈ yþ’­ßßu»¬V÷ÈÛ÷wpÙ¤ñŠ´ÛUPX¤ÕkÖjÑÉ*iæŒ+Õ¹sG¥¦¶Õ¶íßêØ9jÕ*Q‡Qæ¡lué”îÇ¿¾YÒ;V™·¯n]:kÐ9ý+M‹‰‰•K.Mžp±V­Y§%K—I’®»zºÒ;¦É%WÈË0vôùJKm¯WLÓ²•«•Ÿ óG¸O|¹è‚‘š=w²‘«ü$Z¬ëf\]g÷“}ø°"##çw »]»vÊÉÍ z»è˜èÆüæ”gdêäñj™˜èý~מ½Zº¼âYeAa¡ûkA2¹w‡µIIV›”d%$ÄëØ±=ðø,åääj@¿¾²ÛÝ»t÷§gçääHRàc+!ÌßÃjµycåoúe“¼ÇvÎíßW=ñ´¾Ü¸I3g\©Í[¶iÖ /ªY³HõïÓGŽ2‡$ÉépTšG(QѽKgÍrf£ÕjÕ ×^¥›¥æQQš6¹â̼P—Á#!¡|÷œËwšûd$‡Óànm’[K’ŽŸø1àõ’¤ÃGŽ(¢üãùÃÏ«ÍÆ*GJµ•wüGÝÿØ“ÊÌ:ä>f%)óÐ!=ðØ,=|ß=G×g[=«.7âóŠ‹Ñ¹ýû+ëP–$÷®™ÂÂÂ÷ç†ÿ•çÝ*1Q%%%ÊÉÍQ«–-½×ææåiø°¡~·õÿ{°y£:m’“%I-âZèîÛo©r½çYÿoók6D»öìÕÚõ½×'ÄÇ+ûðQ=vLi©UOX8Ýükª[—Î’¤ãù'%Is¾«ââ½üÜSJˆo¡E.®öxÚ™øè㥒ܻò©¦•¿þél-Ã÷ûH’’“Z¼>%%EYÙš0î"Ó¿±œyÛôþO?2ëYo¬¾ïIÒý>©ÌC‡ôÈ“ÏèÙÇnà%<ýÇ‹ç r©GN§S33Ôµ‹{wNJr²ÖmØà½¾¸¸Øû \r,ŽˆˆÐ‘£G+ͧYd³JÓ’“[+-µ½æÍÛ;mßþýÚ¹ë;7dp}=œª‚­S“.Õ=ŸëÒ;¤©mJŠ¾Û½Gÿ^ò©œ§rsóôíÎÝ’K*,pöîÛ¯’’RmýfG¥Û÷íÝK’ô÷9s•™uHë7nÖÑ£ÇBžµËZÎápÊép*/ï¸}¸X’Ô·WÉ%œ*”ËåÒž={UXX¤ï<¡e=øýÌÉ“§”u(»Ò%ÿÇ|É%­Xõ…6|µYÆ]¤Ä„½õÎ{:rähí—ÁšOûxégÚw C›·lÓ¶í;§]»H.÷Ç^ª¸¨DrI#ÊÿÌ™·@ÇŽåÈépjÇ·»t"ÿDÃÿ{<“Ãáâ,=î}û¨SÇîÑT|¼ããõð}÷¨SÇî×%†Á:ë]‚[¶nÓK{U’TXT¨¯¿ÞªV­’tÙ$÷n‘©—MÖ;￯Ûïþ:¦¥jýƯ*ÝÞb±hØÐ!šõì 3úM±:¥§kİ¡zmö**.Ö¹hô¨‘ºçî;uÏÿݯ½û÷)%%E+W}®;n½UÉ­?«Ä™±Ùlºýæ_è©^Ô«o¼©×çÍWYY™ããõÚKÏkÔˆóôéÊUZô¯Åzï£+..®ÒgM™8Aë6lÒÖí;tûïþW6›MíÚ¶QFfVHó÷œ5XŸÜ|[¥ïÓRÛë—7^/I}þpÍ÷}=öŒ{^-}^çWS+׬ÕÊ5k+M›6y‚.›8A¯ýs®ZµLÔ×ÍPÏÝôüKÓ˯Íу÷þ®N—Áß÷ûöë®{ÿ É}fám7Ýà=%¿OîZÿÕ׺þ¿nÕÓ>¨ GÔÖí;´âó5ú¯;îVDD„JKKõ«›nÔøqû„¤¡£.¬ÕíÖ¯^Q§ËQÞ›;»Ê´Äøx=ûdžYyÔË;]ÔÅa‹.¼ÐûÖL’”””¤‹FÖ¹xï#µ}ªÞš=[«¾øB‘‘úÉÌ™ÚüõµnÝÚ» =ô þ³ôS)*ª¹\.éÚ«¯Vjjª2f¨uR+¹\ÒAƒ5oÎëúrÃF•••éê+¦«SzGï|†¢¢¢ÂJmüØqj“’\‡ï;ŽOïjfÂØ1ÊûñG5o%ßÇ“Ô*A×LŸ¦Ôvm¼Ó{õèª?=õGmùf»Žý£¶)­Õ)½£,©oïžzú±µuÛvÅÆÆjè s´vý¦òÓ¤]Ši®YÿA6}­üü|õïÛ[V›UŸ¯]Òü%—®œz™lV«ü×»ç1xÄÄD«}Û¶зwùñ.—f\1UݺtÒŒL¥$'kà€~ú`ñ¥§wäÒÇ©k§tÅ·ˆ­2öíR‚¾+Gn]•‘•©K'\¢~½{)ªY¤F¦¼¼ã*..Vn^n—Áf³êšéÓç]¦ô´T]3}šúôìQi96óE6‹T™£LúöQ»6¿·;oû•V}¾VeN§âb£e±HwÜòKMºd¬¾ß·_.¹Ô¹cºÒ;¤}ìᮾM×lþf®Ãúèi¦ï‡5Ú%EHŠ’-)®ü2ìûï¶?h†ÇssÔ{ÀYÜÖHìØ²Q -[5ôb ‰û`ñÍž·@¿¹ùsÁȆ^œN۰ƺ]èÒ£Ï]’ÖI:Q~)T$©TR™$§ì@<ƒÓÚk-c­!\„ëᜳ'|}ø,IëýIœEõô^‚¨Ö)Ø”I4¥ü¤&þ=† ~^aûñ"Më€?¶ áû^‚Ð@؆…§º–Å"‡ÓQ~º0Bát:Bz]€³ L¶alªªó³mV› Nä+.¾î^ÄØØÌÏ—Õjcà„pÙ†±]¨ªÎOº°Úì:v8K1±qÞÏ£BpG™ŽdgÉj·³«á° c»XŸt!«Õª½»¾UrÛTÅ´hÑàCëpäp:u*ÿGÉÎR³¨ær¹<¯“ÐrÆv¡zu~ Ën·«¨¨XN—K‡³Ê‘áàf ‹lV›dµ¨´´TQQ|j1tÆv¡Zõr–`TT3••ÙT\\,I|fT‹E²ZÕ¬Y³>3 ÀÙÓPÛ0¶ Õ«·5b·ÛYáŒÅ6,üpp `„ÚŸÖÎn>ÀYÄ `‚0B­w fÜW—Ë@µj¬óF­Ëå Zì`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F X#,€À `‚0Á`Œ@°F¨i°\>j£V-9]°\~_ý§PSÁšRm[BaùÎÈY~!X€Ú Ô“Óv%Ô]‚¾3w”_¨ OGj4²™î p©¬è˜Ø;%5—))¢|^VUDÐR›G0ž'@žn”I*•T"©Pƒå©"X°üïØÿN¿’-w°¢äŽ–]’M š:ß`9änG‰¤"¹ƒU wKÊTƒQV `¹TßÑ•çNK%«"LÎòi¶ò‹EÄ š:O?<£)O;ŠÊ¿z‚åiù¬ª¬ºV ]ž0y‚䙡ŠÑÁøx<»=#­’òiv T“]‚er©ÄgºgÄå]y‚€o°<Ñò W™*v Öj— ÿy†t–ò;’*Ó÷d ‹aŸ´ç T©ÏWOÌNûBâÓíTùH§²ûî“ôŒªˆÀ_°3Í=Ç®‚-P¨»=‘òß'I¬Õ -ßx6TÕÆà«oœ…Š`|ù¾“…o¸üÿîÿ³Uœ.0¿¿ûÇÉTE°¾üOU÷Mz¡pБV(ñÿ™`£)b$Ô7»­v·`M"ìg  Á‚Ò{ Ö66D p&øÔïÿõèâzßõmIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/layout_listbox.png0000664000000000000000000004315115074673150023235 0ustar00rootroot‰PNG  IHDR¬8?ÇùsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timejue 08 dic 2022 22:16:34ô × IDATxœìÝy\åþÀñÏ9À‘EAqÃ5T,1Ó\Ó\S3K»Y¶Ø­¼f‹¦¹¤•]íª¥WË_–i7ArW\Ss—RQQÁ Tvg~ G@váè÷ík^rfyæ;3z¾<Ï<3!„B!„B!„B!„BˆRÓ˜H™B!LR‘…UDr)ª I\Bñh**Q•+•5©Ü»¦„Ë„B<¼îMHJ —•Hi“Ia‰IsŸŸËº!„¦¥°ä¤Üçç¶»¯Ò$’{‘&ߤ½çsQ‰K!ÄÃëÞä”2ÜóùÞõ‹UÒdRX’ÊKT…M’´„âÑRX²21Ý›Ìòo_$óQTÊ,ßßf€àØ–wË–„%„†ü‰Gd·k@sw2äû;ÿ¶ŠIZÅ%¬{“U^ */I™6€w௿<×Þï±áh¨" J!iÅ $=öçêç†Î©ä&3 '­¼ÄUlÒ*.±ÜÛ˜?QYíÛ·ï°æ—Ußh4Ø—ùÀ„B<´H~và7Nžñù“–t¸Ķ»IJNfpÿgÐétFËnݺÍâïÀ¯]žîÚ¥Lå_¾r…}©Ÿ­,­pvvâ±Ö­ 쯢ä€F£¡Žƒnõ\hÒØ­¶¸Vz! ÷æ“ÂòM©ºµçß8!@#,ñ lÙ¾‹˜ èÓ«÷$ˆès|ôÞÛØÙÙp;%…/ç/$ìL¿­^Qžâ‹Á¾Hem&AQåpýæM._¹¢ÎKOOç÷?´~¿ÿq€˜ q¬Û¸…ôŒ ²³²ù%è7öì;`T–™V‹ÎÂïF^ôïÝ}NŽñþRSùãÐaÖmÜÂñ?Ob0ä>ñr<¿ýÆÖ»Ôu#ÎFóKÐo ý³Èø]ê:áV¯~íÚðñÄw xÜŸŒŒL~ú%Ðh½˜ qlÙÉö]¿síú £}ü¼ƒÁÀñ?O²~ÓVNr¿Töþq[CHHL,°ï+ WÙ¹g/›¶nçì¹sEŸdñHs¯ïFxDŸ|ö·oßæÎ;L›õag"¨ïêZž¢Ë”CJû–õ¿w",ñ ò:Ì›7’ù%0˜Ç;¶ç‰Ž¸’p•IÓfpçÎ4 Š¢Ð´±7ŸOÿ„ß6m!##€_ƒiíÛ‚®7.óîÏ'NF«ÕòD‡ö꼈¨(>Ÿ¿ä[·ÕÕ›6öæÓ&áêìÌÁÃG¹pñõë¹âãíÅü…K¸uû6óçÌ*úÿÊ=Ç4lÐö8DTôYuþO¿üÊÚ ›sWW¬,-™<ñ]Z¶hNdäYVýº–={Ÿ –Ó½K¡'O’”|ënkø|ú'x6hÀ–í;ùþ§Uèõzu›gz>Í«c^,ö2ˆG˧Ndʬ9\ˆ»Ä'³¾@£Ñw‘ºŽŽLýð_‘J•¸ä¯xhìÙ¿Ÿ;wîðQ# üñ{¾_4ŸwÞÀÿ}»€Úµì©YÓšßV­`úÇ“Œ¶Ý¸mÃFå¹ÑcÙ¶s7µkÕ±Nôz=_/þŽÔ´tÞÿç›,øâ3|›7%âl4k7lÂÌÌŒ·Ç½‚V«eÙŠŸø%x‰×®1fäðRÝs«ç‚¹¹9‰W¯“““CØ™‚Öo¢m«–¬X¼€YS>"+;›Výb´]]§:|1}*¯¼”Û|¹sï>žéÕƒ/gLÿ½™™YlÞ¶ÈídòÝ?ãèàÀÓ§2kÊGÔ©]›M!;8yúL™Ï½x8Õqp`Ö”¨çR— /w'Ç:̘òux½hѼ Cö»{,aU~½åOõûcffŽÎâïOæXXX”«Ì²’ÅC£W·®¤ÞIaëÎÝl؆-!têàÇûï¼…Fsÿ–ïF 2Pýüá´YDžædØõ^•“Óß¿QÖsqF£Ñ¨ÍnÏÄÖ»ÈÊÊbÄÐAÅîó^×oÜ$++ φ¹Mwiii$%ßÂÌ,÷å2­Z43úò¸WíÚö\½~ƒò÷gÃÝûq‰W¯åËÝÚ#€›k=n&%—*^ñðKJ¾ÅÔϾàÒåxõžÕ¥øx¦}ö%3¦|@íZv„©²',¹‡%¤û œ}w™™ÖŒç `èÀg‰‰ãß‹sðÈ1bã.áÙÀPŠ*çžù½<‰<Í­Ûw¨÷ =>>A]çÜù (Š‚‹s]uÞ¶»É `Mðz¦¼?¡TÇ´nóV:´k ¸89ТiF Zô¶…SaÃà)`·zåJ"m[µ ú\ ®ùŽE€™_ÎS“ÕŒ)0uÖ\ŠgæÿfÞì4¹‡%LÂ¥ËW¸xé²:ݹs§À:gÏçÈñ?ÉÈÌÄÉ©¹¿Yê,°µµ%--3QäÜÓЀ‚Á`@¯×Åáã¡hµZš5ñ¡‘‡65­9r<”Ý{÷s%á*k7lÀ¿½ñ ¬ ÆÇÛ‹ÇÚ¶æø_'Ùðð}éÚ›\½~°ð÷›¶n§¾›+žé@¿v˜™™±9dg"¢Ôã/«V-š´ag"¢ˆ‰½ÀÎ=ûÐjµ´¬]™Ë§˜Ø x6l[›²·§¶½=3¦|€gÃjÜ©M‚ò«˜xp>žñ™ÑçG¸Õ+|ßBTï&-&‡€;w§4 㑇 4vKÂBñ@•5aI§ !„&Aîa !„0 ÒKP!„I(s KêWB!$¹‡%„Â$È=,!„&Aîa !„0 ’°„B˜ét!„Â$”£Ó…¤,!„Ž4 !„0 e®a]Ž‹©È8„Bˆû*sÂêн"ãB!îKš…B˜IXB!L‚$,!„&A–B“ K!„I„%„Â$HÂBa$a !„0 ’°„B˜IXB!L‚$,!„&A–B“ K!„I„%„Â$HÂBa$a !„0 ’°„B˜IXB!L‚$,!„&A–B“ K!„I„%„Â$HÂBaÌ«:€¢Ô°®YÕ!!Ä#)=-µªC(”Ô°„B˜IXB!L‚$,!„&A–B“Pm;]&11‘%K–о}{úöí[ÕáT˜ÌÌLþïÿþáÇS»víowãÆ -Z¤~¶³³£E‹tìØ{{ûʵX»wïæøñã4iÒ„~ýú¡Ñh ]oÆ „††YN¿~ý¨[·.Û¶mcìØ±•®„˜T kÕªUÌŸ?Ÿ?ü°ÔÛFEE1uêÔJˆªt ï½÷W¯^UçEFFòÆo°oß¾R•uýúu>ýôSINNæØ±c¼ýöÛøøøT®˜ÊbæÌ™üãÿ &&†7ß|“·ß~»ÈuÓÒÒHNN&99™ððp>ýôSõsrr2™™™3nÜ8’““Ë—âáPد¿š»“–ܘ`X¶w'ÿ´Ô”y•XaÝÚ;vìÈÈ‘#y÷Ýw‰ŒŒÄÇǧÄåíܹ“Q£FqåÊ•Š ³Ôrrr077'""‚&Mš¨ópqq)UY‘‘‘4mÚ”äädµF¥( óçÏgÒ¤I9r„víÚ•9¦Ò0 ØÚÚ²gÏÚ·oÏîÝ»0`·oß.vÛÇãïï¢(ʼvíÎÎÎeŠIˆêâæõk\K¸Lzz*ŠA)ðo½2h4ZÌÌÍ037ÇÖÖ'gllíJ´mewk·®i38ܹ;¥@6  €rwR™L“àùóçù믿رc?üðAAA|ôÑGêò   xê©§ÔysæÌᥗ^àÇ$%%…éÓ§ãèèÈ[o½¥®Í®]»Ðh4ôèÑuÙ²eË:t( ""‚-ZлwoîܹÃÖ­[¹xñ"O>ù$=ö˜ºÍµk× áòå˸»»3hÐ ¬¬¬˜={6‹-ÂÑÑ‘‰'¢ÓéøïÿË?ÿùO£&Á£GrðàAêׯOçΩ[·n±çI£Ñ0aÂöîݡ~HHHH™bªY3÷†“'Oòûï¿cggÇÀ‹ljLNN&--æÍ›‡»»{±ñÞϹsçØ¸q#ï½÷P¶kpùòeBBBHOO§wïÞxyy•+.!JêzB<×®&’£Ï¶–u]ÜÐYZa¡³ ;+›¬Ì nßNæNÒMÌu–Ô´µ­„¦( †99zRRîtýæ:n ½¨UÛ¡ÜåW“i\½z5]»vÅÖÖ–>}úhò d×®]FófϞͥK—ÐjsÕÜÜ333uü‘ǜÇŒ¯¯/›6mR—/]º”¦M›²lÙ2¢££yþùç8p ?þ87n䨱ctêÔ‰ÀÀ@²²²ðóó#88˜°°0&L˜@‡ÈÌÌP÷mff†¹¹¹ºÍ§Ÿ~ÊÍ›7Õý¾ÿþû :”3gÎðßÿþ×(9—Ę1c8|øp™c˜7oƒ "66–   |}}IHH(t8;;³iÓ&&OžÌG}Ä’%KJó½¢¢¢˜7ïïŠ|i¯Àž={èØ±#G%44”Ç{Œ;v”+.!Š“““Ctø)._ÄÑÉ™&¾mqs÷ÀÖ¾–VVhµfhµfXZYak_ 7wš´lKG'’o\';3³Èû¿%¥Ñh037Cgi‰­µÐétÄž :< ƒÁPAG[µò7Z‘Ûè4|NÀ{i©)JeN÷òõõU-Z¤(Š¢ìÛ·O”˜˜uùˆ#”)S¦mccc£:tHQEÙ±c‡âââb´<11Q±³³S<¨Îûä“Owww%++KQEñóóS¾úê+uùÏ?ÿ¬JDD„:ïµ×^S:wî¬~ÎÉÉQ¾qã†bii©lÚ´IQEÑëõ¶OIIQ%::ZQEÙ»w¯âìì¬Ü¼y³ÀyÈ/""B”äääËNž<©Jbbb™bŠŽŽVt:¥Î9r¤òþûïÏ /¼ Ê믿^lìù:tH Ì߸q£R¿~}õsi¯ENNŽâíí­,[¶L]¾téR¥}ûö%ŽMˆÒJMMQΜ8®œ ?¥d¤¥)Y™™¥šÒÓÒ”¨3§”ð“*qçÏ**xŠ=¥œ =¢„ýyTÉÊÌ,ô*ûûxïn.ñ½›[œîæ«»¹GK!·¬L¢†FXXýû÷ S§NÔ®]›µk×–«ÜÝ»wãåå…¿¿¿:ïý÷ßçÒ¥Kœ={VW«V-õç^½z`aa¡ÎëÙ³'.\P?kµZrrrçôéÓxzzrñâÅǵfÍž{î¹Rõ,ŒF£ÁÖÖ¶L1íÙ³GGG8ÀŠ+X±bZ­–ðððB×ÿâ‹/8vì:tàÆF÷ÔþøãrG~¥¹111DGG“––¦ÃÕ«W‹<!Ê+''‡ ÑÔ¬iKC/´ùZsJÊÌÌ F>X[[“šr§Ü5­{i4ìjÕF«Õuæ¤IÕ´LâÖêÕ«±±±aáÂ…ê<[[[™0aB™Ë½páBú¶¶¶899‘ ÞÉÏÆÆÀ¨ÙÆÆÆèó¼yóX¼x1mÚ´¡Aƒ¤¦–îæùóçéÔ©S©¶¹×¹sçððð FeŠ))) FCll¬:ÏÛÛ›¦M›X÷ÚµkL™2…'Nàè舿¿?cÇŽå»ï¾cÅŠÌ›7“'OVø¼â®ERRW¯^U˜2eJ…Æ!Dž˜È3Xè,©çÞ°ÜeÕs÷ ö\™™èt–±š¶öÜNNâ|Ô¼›úVxù•Á$Ö/¿üB=Ô/(ÈýMúûï¿çòå˸¹¹¡ÑhJœ¾²³³IJJÂÓÓ³L±FFFòñÇsþüy\]]8räH©Ê°··'>>¾LûϳbÅ õYµ²ÄäééIJJ S¦L1ºçW˜ØØXt:šàwíÚE·nÝ>|8ûöícåÊ•ž¬J"ï8??¿¾ñh¹žOzz>Í[UX™îˆ:sCÅ',[ûZ$]¿Æ­¤›Ø›@GŒjß$xäÈbccY´hÓ¦MS§o¾ù{{{‚ƒƒpwwW{Ĥ§§“““£~¶²²"))‰””u^@@çÎcóæÍê¼åË—Ó¬Y3£ž‚¥‘—hòzàeeeýv¯ÕjÑét÷mŽó÷÷gÍš5e~þháÂ…ìÛ·3f”9¦§žz Fcô`rQ¼½½ÉÊÊâ÷ßÀÃÃÀÀ@‚ƒƒ133£cÇŽe:ŽòªS§Ì™3çt#¶kWp®W­™–¿{d—o23Óâ\Ï´Ô;•³F£ÁÚÆ†Kqç+¥üŠVíkX«W¯¦{÷îjÍ N§càÀ2~üxÆŽË·ß~K¯^½ðññ)ЬuëÖ8880`Àüüü˜5k^^^Ìœ9“¡C‡2lØ0ôz=»ví"88¸Ì5‚:àììÌOÿüó*‰G<œn^OD¯ÏÆÞ¡ý»Q-G¯\ÆÒJ™YÅe[ZÕ -%…Ô”ÛÔ´)ÙsZU¥°¶ Æ›ñ÷Ä–w§ú“'Ü«2³°Ð¹ÍMÆ £AƒÖñòò"++‹€€Õ/KWWWfÍšE›6mhÙ²%vvvèt:FŒANNnnn4kÖ :wîLŸ>}ÈÎÎÆ××—¯¾úÊèáYFÃc=F½zõÔÏZ­–®]»ª÷‡4 têÔ NÇ‹/¾ˆ Lœ8‘~ýúáéé©&ÝAƒaoo••­Zµ¢V­Z˜™™©eš››3fÌ6lHFFmÚ´aܸqê³Qùc³¶¶ÆÚÚNG³fÍxõÕW™:uªÑCÈe‰ÉÞÞž–-[2räH´Z-ÙÙÙôèу޽{u}ÏÓ¹sgzôèÁ;wðööfúôéŒ9’Q£FÑ®]»¿pÜ{vvvtíÚµÀü:uê¨÷óJ{- ·Ù÷å—_ÆÑÑ‘””Z¶lÉèÑ£±¶¶.2!JëÂù³ØØØak_«ø•KI£Ñ•™IVF:]¥”Ÿ““ƒ^ŸM­ÚuÐggWø~òûlöìmÀ% ëî”ÿἇ† ÆZļjù¦ !„¨Žþ:ú <¼±±«œwx޹̕‹qØUÒ}¦¬¬ ²22iÞ:÷¡ûêú¦‹jK!ª;CŽ‚Î²r:FètVäô•V¾™Ö½>«Òʯ(Õþ–BT ff~ÿ*¹¹†œÊ{^Jk¦5ê¤V]I K!Ê©²Úx }\M #­Ô°„¢œ@¯ÏBgfU)åë³3ËôÖŒ’2ää`VHgªêFjXBQN­–¬ÌÊ»”••…VSy +Ç ÇÜÌ¢ø«XõO©äävÁtss£{÷îe~¸·,.^¼øÀF¿=xð ÉÉÉôéÓ§Ò÷%„(?+«ܹLÍŽ7UZ)·’1ÓUÞ×uvF&5í«÷3X`"5¬ÀÀ@Ö­[Grr2×®]cõêÕ4iÒ„üñÅð G¿;w.“'O.ñúÕe4e€ pàÀªCˆªN]WîÜJ®”7ª(ŠÂíÛ·ÐYTN/DÈÌÌÄÉ©tÈV“HXO>ù$óçÏgáÂ…ìØ±ƒ3fðÏþó½rgüøñÄÇǽ-¼²üüóÏìÞ½»Äë_¼x‘eË–UbD%·fÍN:UÕañ@ÕqrÂÌÜ‚[7¯SQ¯eÊ›’“®caa¹Eå4Ùe¦§aa©ÃÚÆ¶RʯHÕþMÛ$hccCïÞ½Õyµk×fþüùŒ?^}kÁåË— âàÁƒÔ©S§Àðaaaüú믄……Ñ A–.]ª-Dbb¢ÑKoçÌ™ƒ——vvvDGG¤¾AaÙ²e¸ººrâÄ ©[·®ú*¤;vðÛo¿‘˜˜ˆÑkžŽ=JPP¡¡¡äääàêêZà5P{öì!22’fÍš©ûjÔ¨»wïfݺu\½z•&Mš Ñh¸|ù2óæÍãĉdggsúôi:tè –UT,Û·oçêÕ«ddd°jÕ*222pssã›o¾Á××—ÀÀ@BBBÐjµÔ¯_ß(¾¢ÎóÏ?ÿÌÚµk¹uëgÏžÅÉÉ©À(ÉlÞ¼™ 6púôi\]]Õ!Pò$''³~ýzvíÚ…™™ÎÎÎêœ111qâÄ lmmÕs^žó^’k"ÄýhµZ²ôÙ\O¼B-'´ÚŠù÷““càÒ…sXY×,ô 3å¥( wn%ÑÐÓ«»o‹êû¦ “©aÝëðáÃxzzâèè?²ìâÅ‹éÒ¥ ¡¡¡¬_¿oooþýï«Ë‹±¸°ÑoGŒÁèÑ£Ù¿?ééé ÌÔ©S¹rå 3fÌ wïÞj-púôéôïߟ°°0Ž9¤I“ ýb 1ëkéÒ¥4k֌ŋsþüyÆÇèÑ£Õå…¦\\,!!!¼óÎ;<õÔSìܹ“Ë—/“••Å;ï¼CëÖ­Ùºu+'OžäÉ'Ÿäûï¿W÷u¿óœ‡V«ÅÜܼÐc6lß|ó ‘‘‘|ýõ×4iÒ„¨¨(uyxx8mÚ´á§Ÿ~âäÉ“¼ð êØdtèÐ}ûö±mÛ6† R¢c½ßy/é5¢8.õܰ´ªA|\L…•w+ëšÅŽ˜PVwn%ackooj/JµqxĈŠ¿¿¿òé§Ÿ*S§NU^|ñE¥qãÆÊÑ£GE)~dÙ+W®(ÖÖÖF# /X°Àh4ÛâF,.lôÛ¡C‡*z½^·ýÚø¿ IDATbÅ ÅÝÝ]Ý733SñððPGö­[·®TÔ@¥ª‰'*£F2Ú×ܹsÕÏ[¶l1M¸°Ñ”‹‹eâĉŠrõêUu›¼‘óΫ¢(Ê| 4kÖLQ”’àÛ¹sgeÉ’%E[þ‘óŽ-ÿ(ÆÝºuS>ûì³Û%%%)Êþýû ,+Ïy/é5¢$nß¾­œþë˜s6¼Üßçφ+gN„*Qáa>êð…óg•Ó'Ž+a-ðRQªïˆÃ&ÑK@¯×“‘‘ANN«V­"88XãèÞ‘e£‘ewïÞÑÈÂ>>>厩wïÞF¿ùlß¾ÆóÓO?©ó §oß¾¸ºº²dÉêÖ­Ëã?®ÖHJ"óf·nÝÐétÄÆÆhr+i,ûw''§ûî«wïÞ,X°(þ<—DÞ1ÇÆÆ’@£FÔaMn޼ɮ]»øõ×_ l·k×.\]]yâ‰'J}¬÷;ïå¹&BÜËÖÖg×$ÆÇq1ö<® <0+å¿©ƒø¸rôzÌÌuXVð+Ÿ”»Í€Ÿæ­Lêß¼ÉDÚ¹sgæÌ™Ã—_~ÉóÏ?Ï×_­.Ë?²lll,±±±èõzudÙ¸¸8£·—W–¤¤$233Õbccéׯ;wr;$Ô­[—îÝ»ãííÍòåËË´N‡N§»o‡“âb))[[ÛBGð-ì<—ÄÎ;iÞ¼9ãÆcõêÕj“+䎴lnnN:u lwþüù"¯ayÎ{E]!ò88:âæá¢(œò4 Acn¥UÅ%+ÈHO#éÆU¬jXÓ¼U»Jyû{e2™V~~ø!-[¶dÿþýtîܹؑe]\\ Œ,|¯²ŒX|/OOObbb˜6mZ¡Ë½½½Y¹r%‹-bÕªU¼þúë4nܘ€€€rí·,±”µL(ß¾£Fâ›o¾QÇÔúä“OˆŽŽrGZÖëõ\»v­@Íï~£0—ç¼?Èk" {{{,,¼¹q5¤×¹–˜€­=¶vö˜ëtX˜ç&Šl}ÙY™¤Ü¾ÅÛ·±°°À²FMÀ:_'ˆ²PCN9=Ù™dffba©Ã³q3ìk™æ=+“©aå×¢E   Ž¨[ÜȲDGG,|ï—_q#—Ä AƒØºu+¡¡¡….7r_^Y«V-Þxã \]]‰‹‹+Õ> SØhÊÅÅR%Á×ÊʪÈÑ”ó’QÞÈÇ€Ñ@’8;;ÚE¿cÇŽ„‡‡óÇXVžó^Y×Dkkk\Ýâî僃“3©))\Š=Ïù¨p"OÿEäé¿8y†¸óÑ\KLàö­dnܸÎ䛤ÞNæzâ•rM7¯'rçV2Yé™XÛÚáÓ¼%-Zû™l²­a|ôÑGtìØ‘ƒÒ©S§ûŽ,ëååÅ'Ÿ|Â!C>|8ƒ­[·µ 7bqItëÖñãÇÓµkWÆŒƒ½½=Û·ogݺu8::âååE§Nðòò"44½^OÏž=Ë}. Mù~±8;;—y_ÅàÛ§OfΜIzz:]ºtaÀ€ê¶æææ 0€1cÆ0pà@bbb8yò$ݺuÀ‚ÿüç?Œ=šS§NáææÆîÝ»ùé§ŸhÕªo¿ý6}úôaôèÑdeeñçŸrøðá2Ÿ÷œœœJ»&B˜™™akkKÍš5q¬ë‚^¯Ç`0¨¿(iµZµW­N§3©ûIUÁ$žÃÒh44oÞooouž››uêÔÁÊÊ ŸbG–}òÉ'éÞ½;z½žvíÚ1dÈ6oÞÌ„ €ÜÚÃýF,.nôÛ<½{÷æé§Ÿ&==5jðòË/Ó´iS´Z-ƒ ÂÌÌ ½^¿¿? .4zŽ(ÿñ6jÔH}«°}i4î;šrQ±h4šûÈ+3ÿÈÇyólmméÒ¥ Pü¾:u¢E‹deeáëë‹›››Ñ± <˜  Óé:t(“&M¢víÚ4oÞ___†ŠÁ`ÀÚښѣGãçç‡F£¡OŸ><ñĤ§§ãîîÎ{ï½§6–å¼—æšQFMJ–––XYYaee…¥¥%:®ÈÇ@ªJu}ë‘q8ï½€E5_ !Ä£JFB!ÊA–B“ðÈ&¬^½zIs B˜G6a !„0-Õ¶[{Ä©?«:!„x$5lTþW×U†j›°š¶l[Õ!!Ä#©²{ –•4 !„0 ’°„B˜„jÛ$(„¢t ±Ñ$Ä_"+3£DÛXZZáìZï¦ÕþÕP’°„â!AjÊóï‚e¾—LßOfF:‘§O—OóJް|L"aV`¾‡‡‡ÑPñeuöìY6nÜÈ{ï½WèòììlfÏžÍ?ÿùO£Á KëðáÃlݺ•çž{N}wÞÃàâŋꫮJcõêÕ¸¸¸ðÔSOÍ¿qã‹-bÊ”)e|çÎܾ}›Aƒ•i{!LQbü%Úù”8YXZÕ I‹Ö„ÚWíVõ®ÿÝȺuëHNN6šò§QQQQÌ›Wô«³²²øôÓO¹yóf¹ö3{ölæÏŸÏ’%KJ½mTTS§N-×þ+Baq3nÜ8’““KUÖªU«ØµkWùׯ_çÓO?E¯×—9Î;v°víÚ­[]έå•™™¥UéÇѲ´ªAf ›«’I$,È}Ûúüùó¦·Þz«ªÃ*±äädBBB˜6mk×®-Ѥù]¼x±Ðq¢´Ââ?~<ñññÔªU«Š¢*Ÿêrn…÷gM‚Å9{ö,ááá´mÛ–­[·’‘‘A¿~ýÔr®]»FHH—/_ÆÝÝAƒ $NHHôí۷СÚó;yò$¿ÿþ;vvv 8{{û"×]»v-mÛ¶eôèÑLœ8‘C‡©C•üûßÿfðàÁjÌW®\aùòåLž<™Ë—/óã?’’’ÂôéÓqtt4JÖäðáø¸¸Ð§O5Žììl/^ÌË/¿Ìúõë¹víO>ù$mÛ¶%..Ž;vžžÎ€¨_¿¾Z^DDû÷ï'))‰Ö­[«ãCǹsç 4©æääBDD­ZµÂßߟš5ËöþeË–1lØ0Ž9©S§hÖ¬½{÷.0ÃÎ;ù믿ðôô,P;+í1å)Í5BT.“©aÝOTT/½ô=zôàøñãlܸ___õ¾WVV~~~Æ„ èС™™™j 4ˆððpþóŸÿЪU+ÂÃËÜç¼yó4h±±±áëëk4zî½V¯^Mÿþýqpp cÇŽ-ÿꫯ8þ¼ú9>>žY³f©Ÿóz›Ý×yã75j‘‘‘|ñÅ´iÓ†˜˜õ¸ßyçÚ´iÃöíÛ9räþþþŒ3†¾}ûrôèQñõõ%66€C‡Ñ·o_öîÝËüÁàÁƒ7nÜ}㸷I555•§Ÿ~š©S§röìY>þøcV¯^]ä¹)ÎÒ¥KiÓ¦ sçÎ%<<œ—^z‰Q£F­ó /0vìXΞ=Ëܹsùúë¯Õee9&(ý5B}OOO£·µ×¬Y;;; wXëýë_…vسgŽŽŽ8p€+V°bÅ ´Zm‘5²5kÖРAZ´h@ß¾}‰%44´Ìç`ݺu >\½wdnn΄ عs§Ñzùï-õêÕ ½^ot®zöìÉ… Ôf¶ÔÔTNœ8¹¹9Š¢péÒ¥ǵfÍÆŽ[¡Ït4hÐ@ýÙÇLJ=z°wï^6mÚdt4 7V×/Ë1•ö !*ŸÉÜÃò÷÷gÚ´i%^ßÖÖÖ¨cüyóX¼x1mÚ´¡Aƒ¤¦Þÿ]Y5"--Û·oèZ””„F£1JˆÞÞÞ4mڴвV¯^••ï¿ÿ>ûpŸV«%00víÚ•ø˜îuáÂuèú<^^^\¿~œœœB·±±±)ÐáÃÆÆFíá—™™É믿ΡC‡ð÷÷W‡ /óçÏãââRìzfffdee˜o0Ðh4÷Mxîîî\»v Èí4ñä“O¹nYŽ©´×XQùL&a•Gdd$ü1çÏŸÇÕÕ€#GŽÜw›ÄÄDìíí±³³+Ü<==III)ÑsB.\ààÁƒ¼ûî»ØØØ¨ó»uëFPP³gÏrkÅ%Ñ{9;;}¡æÅíîî^æç—~øáN:ʼn'Ðétäää0wîÜR•aooO|||±ëyyyqöìÙó/\¸€§§§Q ú^ …Ÿ‡üÊrL¥¹ÆBˆÃdšË#ïË3¯W`VVIIIFëܹs‡«W¯ªŸ—,YB¿~ý€¿›”òzž=õÔSh4-ZTì¾ÿ÷¿ÿѤIæÍ›Ç´iÓÔiöìÙDEE©CÜÝÝ 1Š'?+++’’’Œž=ëÖ­¿üò‹QrXºt)Ï>ûl±q%>>­V‹N§(ÐÉ °8îåïïÏ÷ßÁ`¸ï¾úõëdž 8|ø°:/++‹ùóç3xð`£u7lØ Ö /]ºÄŽ;èÝ»7{=V¯^mtîý¹´ÇTšk,„x0L¦†µwï^µI-O£Fxýõ׋ݶC‡8;;óÄOЭ[7öïß_àK+33“öíÛóÌ3ÏpöìYbccÕ{AÖÖÖ´mÛ–É“'3~üxºvíÊ·ß~ËØ±c9tèÍš5ãøñãŒ=ºÀíêÕ«yñÅ ÄÔ¾}{<==Õ^zï¼ócÆŒ!55FSàþYëÖ­qpp`À€øùù1kÖ,^xáþ÷¿ÿѾ}{Hxx¸ú¼WY 0€Ù³góÔSOáããÃîÝ»ºÿǽfÍšÅSO=E×®]éܹ3GeøðáÞ„Ñ­[7&MšD×®]éÙ³'ŽŽŽìÛ·///¦OŸn´îöíÛiß¾=;vdýúõ¼÷Þ{ê=Á^x•+WªçáܹsœKFF 6¤~ýú´lÙ’‘#G¢ÕjÉÎΦGôîÝsó¿ÈÈÈàÆüãÿP;täçé鉕•mÚ´¡eË–ôêÕ‹ôôtZ·nÍÂ… ±µµåñÇr;Œ1‚œœÜÜÜhÖ¬:ŽçŸžæÍ›£×ëéÓ§Ÿþ¹º/Fƒ™™]»vU;Yh4 œ+///š5kF½zõ:t(fff4jÔˆÏ?ÿœ&MšÐ¶m[¬­­‹Œ#ÿùwrrb̘1ØÚÚ¢×ëéÕ«C† 1:7yºwïΠAƒ¨Q£uêÔaܸqLž<Ù¨9pÙ²e|ðÁtïÞNÇ„ x饗ÔåZ­–‘#GÒ¸qcEaÈ!L˜0‡2“……E‰®±ÕÉ•K¨ë⊹yÑÍé…ÉÌHçZB<îÐggWFxªÏfÏÞ\²îNÙ€0Ü }³Bnƒ'«¼DeX“ÛíÐðOKM)ú]F †uÙ2ŸöíÛóúë¯óÊ+¯Tu(BTkÑa¤¥¦Ð¤Eë¿¢)ïå·Ö5mñnšÛjQÙ8Z×´™îÜÒ€ Œ—Â=‰K~UBˆ‡D}o.Æœ%ôо¿ÐÒÒ GçzÔ¿[»ªÎ$a !ÄCÂÊÊŠ†šàÚÀ«Äï+Õh4XXX¨’ª3IX¢Ú;zôhU‡ „ÉÈ»Çÿ0z$ºµ !„0}Õ¶†qêϪA!I ùTu…ª¶ «ºž0!„UCš…B˜IXB!L‚$,!„&A–B“ K!„I„%„Â$HÂBa$a !„0 ’°„B˜IXB!L‚$,!„&A–B“ K!„I„%„Â$HÂBa$a !„0 ’°„B˜IXB!L‚$,!„&A–B“ K!„I„%„Â$HÂBaÌ«:€¢Ô°®YÕ!!Ä#)=-µªC(”Ô°„B˜IXB!L‚$,!„&A–B“ K!„I„%„Â$HÂBaªísXB˜šk×®ÂåË—qwwgРAXYYUuXB<4¤†%DÈÊÊÂÏÏàà`˜0a:t 33³ªCâ¡!5,!*€N§#&&­6÷wÀ›7oâêêÊÎ;éÛ·oG'ÄÃA–D«Õ’““CTTׯ_ÇÓÓ“‹/VuXB<4$a QAæÍ›ÇâÅ‹iÓ¦ 4 5µz¾MS% Kˆ ÉÇÌùóçquuàÈ‘#U•ét!DˆP{fee‘””T•! ñБ– C‡8;;óÄOЭ[7öïßOBBBU‡%ÄCE– fÍš?~œ_ý½^Ïo¼Áõë×±µµ­êЄxhH¢‚8::òæ›oVuB<´ä–B“ K!„I„%„Â$HÂBa$a !„0 ’°„B˜IXB!L‚$,!„&A–B“ KˆrúßÿþÇ™3gª: !z’°„(§7ß|“ï¾û®ªÃâ¡'¢¢¢°³³«ê0„xèI¢œÖ®]‹ŸŸmÛ¶ ..Ž-[¶ššJ«V­èÔ©5kÖ¬â(…0}Ò$(D9-]º”ÐÐPvìØA‹-صk111L:• .Tq„B<¤†%DZ¶l/¿ü2 ,¨êP„xèH Kˆ äêêʦM›X»v-éééUŽIXBT 3f0lØ0^}õU\\\øøãÉÈȨ간x(H¢ÙÚÚ2gή\¹ÂÏ?ÿÌ?þÈܹs«:,! ’°„¨@ƒNG¿~ýèÖ­qqqU•ét!D:t(iii´jÕŠÄÄD‚ƒƒÙ´iSU‡%ÄCAjXB”Ók¯½F»víX¾|9¯¼ò ŽŽŽtèÐ'NÐ¥K—*ŽPˆ‡ƒ¦ˆyr“™9`XÖ€íÝÉ?-5e^eVÃZ´Bˆªž–Z©å[×´™îÜÒ€ Ð@¹;©¤†%„Â$HÂBa$a !„0 ’°„B˜IXB!L‚$,!„&A–B“ K!„I„%„Â$È»Å#+((zõêU`ÙŋٶmcÇŽ-SÙÇgãÆh4\\\èÒ¥ M›6-WÌB<ʤ†%YlݺµÐeÁÁÁŒ7ŽäääbËY°`0šwìØ1¾ùæRRRHJJbݺuøúú2o^¥¾ÑLˆ‡š$,! 1~üxâãã©U«V±ë®Y³†S§N˜ïææÆÜ¹s™?>›6mâË/¿ä“O>Q‡ B”Ž$,! qîÜ9V­Z¥~6 lÚ´‰¹sç²råJ"""øù矉‹‹cãÆLŸ>Ó§OYf·nÝHOO'--M§×ëÙ°aóæÍcóæÍFÉìßÿþ7‡V?gff2kÖ,¢¢¢*òP…0’°„(DTT”Ú|g0èÙ³'“&MâÒ¥KüöÛo,Z´­V«þmnnŽFSعŽ=J«V­°±±àÖ­[0gÎ"##yõÕWéÙ³'z½ FEFFŸþ97n¤Q£F•vÜBTgÒéBˆbDFF²{÷nprr2ZöüóÏóí·ßÒ·o_Æg´,!!éÓ§žžÎþó¶mÛ¦.Ÿ3glذ­VKbb"-[¶äûï¿gܸqŒ?žŸþ™/¾ø‚‘#Gòõ×_sèÐ!ÌÌÌ*ÿ …¨†¤†%D1177gÖ¬YDFF–© 333Ú¶mË?þñÂÂÂX·n¯½öšZKsvvfôèÑìܹÈ­µ-]º”¯¾úŠ^xO>ù„&MšTÌA a‚$a Q '''6oÞ̉'hÚ´)ìÛ·¯Øí\\\˜6mÓ¦Mã³Ï>ã?þ Q£F|üñÇ\¸pggg£m¼¼¼HHHP?·nÝš!C†Ë;ï¼S±&„‰‘„%D tïÞ={öC«V­èÛ·/ééé¥*C£ÑпΟ?äÖ¨bccÖILLÄÓÓSýÏæÍ›©Q£Ë—//÷qaÊ$a Q EQP”Ü‘º=<<ø×¿þEJJ 7oÞÀÊÊŠ‹/–¨¬3gÎЪU+ ·×à¢E‹ÈÎÎ 55••+Wòì³Ïªë¿öÚk¼òÊ+,_¾œI“&_‘‡&„I‘Nâ‘¶{÷nÞ~ûm£yy%ò„††2dÈzô胃[¶l¡gÏž¸¹¹ЧOfΜIzz:]ºtaÀ€@níè£> ++‹Ó§OÅîÝ»˜1c]»v¥C‡°}ûvžxâ † À?üÀ™3gX³f 5jÔ _¿~¼õÖ[Wê9¢º’„%YC‡U;@ägff†&Là±Ç#00£Grûömf̘AÿþýÕõ'L˜@ãÆ‰ŠŠÂÕÕ???Þ|óMu:uê@ß¾}Ñét@îƒÅ¡¡¡lÞ¼™øøx–,Y“O>©n“œœÌêÕ«©Q£óæÍãÛo¿åÚµkz+ ñ((ì¡ÍÝIKnB³¬kÀöî䟖šR©ï˜©a]³2‹BQ„ô´ÔJ-ߺ¦Íàpçî”dÙ€0ÊÝI%÷°„B˜IXB!L‚$,!„&A–B“ K!„I„%„Â$HÂBa$a !„0 ’°„B˜IXBTSçÎcþüùU†Õ†$,!*Á‚ 8pà@¹ÊˆŽŽfÞ¼J}š&E–•`Íš5œ:uªªÃâ¡"ok<ƒÁÀ–-[8sæ õêÕÃÏϦM›ªË£££Ùµk†=zàáá¡.[¶lýúõãܹs9r„pèÐ!âââØ¸q# :”-ZpùòeBBBHOO§wïÞxyyÅÆž={°¶¶¦fMy´ùI K<Ò ={ödÒ¤I\ºt‰ß~ûE‹©ËüñGüq>Lpp0¾¾¾lÚ´I]¾téRFŒÁèÑ£Ù¿?éééhµ¹ÿ­´Z-æææh4¹ƒ"ìÙ³‡Ž;rôèQBCCyì±Çرc‡ZÖâÅ‹éÒ¥ ¡¡¡¬_¿žÑ£G? ³ „iáEÄ#-<<___ Œ1uõêU7n̶mÛð÷÷`êÔ©üðÜ;w Ú·o‡‡¿üò fffê¶Œ5ŠqãÆ¹‰±I“&|ðÁŒ;È­-[¶Œ#GŽ@£Fعs§º¯… òå—_–x4c!*Š /"D5äè船¹9³fÍ"22ÒhÙîÝ»ñòòRÀûï¿Ï¥K—8{ö¬:¯wïÞFɪ0111DGG“––ÆŠ+X±bW¯^%<<\ݗѾ|||*â…xhHÂ4'''6oÞ̉'hÚ´)ìÛ·€ .àììl´¾­­-NNN$$$”j?III@n­-66–ØØXôz=S¦LàâÅ‹¸¸¸TÀ ñð’Nâ‘×½{wºwïNll,sçÎ¥oß¾\½zgggbccÖÍÎÎ&)) OOÏRí#oýâççW`yaûB“–x¤)Š‚¢ä6“{xxð¯ý‹””nÞ¼I@@çÎcóæÍêúË—/§Y³fF= ceeetï©N:0gÎuùm´¯øøør©a‰GZhh(C† ¡G888°eËzö쉛›3gÎdèС 6 ½^Ï®]»V{þ¥OŸ>Ìœ9“ôôtºt逸æ›oxæ™gèÒ¥ O?ý4qqq899ñùçŸã)òsDZIDATååÅ'Ÿ|Â!C>|8ƒýû÷?ˆS „É^‚â‘wìØ1Ž=ÊíÛ·iÒ¤ ýû÷7êDÊþýû©]»6½zõ¢nݺê²eË–áççGÛ¶m ”»a⢢èÒ¥ íÛ· 99™bbbpuu¥OŸ>8::ªÛù·aÀ1JG‚ÞN_¬‚µ8ýð)Éû$¿$9Îõ&›ÎŽyt¯¨tc™ä)Éc’/V»^˜ V{áö¢&Yd¬wYGëm’y àgWë[ÖíxLòu°î³nÉ2LYcÁZe›zº*}Jò5›0=ÇæÃšE¬~v¥eš*íxK°Ê¤ÕNV/¶mÂÛ ,a*A*ÇN²™® €và)[‚eÒzŽm Ž:dKp™u«ãeâ*ÓU ÔÁ*ѪõÌf[ð¨-Áöbe¤› J~,f}³Å,&,ÆoÚ+zªKÌv~‘x×–`†‹$›[Ùë=É2U‰­©;ÍËgWSw ŽÚwK°DªÝ“+¶‹V¯¡*¶f6òXÇi,T‚@­þ%‹:\íóöµ/ì ̬yÞÆ©ª €Z{«z=M}QxrÒÚ'0ík¦¦)±`̾?v»u[ðÈL½V¨ØÇTöú-Ácc#RüþëÝûm 2»š?¤IEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/layout_notebook.png0000664000000000000000000002255615074673150023377 0ustar00rootroot‰PNG  IHDR@{ZYpsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timejue 08 dic 2022 22:18:57Û‡V IDATxœíÝwX×ÂÇñï,, Aª€ˆˆ½€Šbï=暘¢ÑXc’›®yS)šb®¹¦hŒ1EMLLbì½DJQªHAAzÝ}ÿXvÝ]–.ˆ—óñ™‡Ý©gÇáÇ9sfg@AAAAAát¬S@y'Wv'ªºuˆ áN©.øˆ )ýå¤:NA¨ý€SÖqZÔ7œ TÃë†nGÁPØ)kxmh¹Õ'˜ôƒMÒdzï« BA„úÐ;íA¡÷^þZÕ5œ …ž:ø "Ah,C᧨fÐGíå«e\‡BTWã3Òúi´ì+À´rÝ"Ah(í +J€\ È**…ÖOíe%j ÁÚP?üÔ5z¸ ”¡ Bu­ÐP“¸ŠšP»ö§®ùW&€•ŸŸ_ÀŽ_·|§TÖ©)-‚pÇHHåSfük^XXØi (E‚åèž„jB°¶4Tó3Auޝ÷µ¸èm j~‚ Ü-R¶{ç.a¨ÎªCÐPM° YukÕ{­AuÓ×~ËÏ›g"ÂO„»JióÓæM÷£ê€•£Ê(#t¯Bj*{µ}M»é+GUókt‹þE›F—_¡” ÅM.>Q@ªš úœ ~§ˆŽšÎÝêùU¡$)­ïì×’AêO’ÉlPUÆäèv†È¨¥'¸®×ê`[âRAZ¥´E· ¬þBFêRÔ@cÀDTþAhAL¸OÚ¨êÕ ¢V]3ØèŽYáÎÐÎ&ý¯äVËP ÐÐí¬ôCPv‡ïK(‚ÐÚ_Ï­.üªÔëòU8C7>0ù'B ¢~†nÈbPuhèílU ùù…\ ##3‹¶mÚÐÉÕ•®Þ^Èd2®DÇðÛ_3kÆ}tíÒ¹ÉÊðÛ_»062bÆÔIõ^6%-“AÈdFÌœ>#£Ûg0nܼÉÁ£ÇñòôÀ¯_ß;YdÙ99ì?|Nä׿ɶËÅÐ0üúõÃËÓ½ÆyÕûÅooúöêÑ%l¼A¤¦¥1yÂ8¬,,îvqZ ý|2”_õº F{aí•H€ÔZ*€ÁgùïúêŒ_0ç¦O™D`ðYÎ]¸ˆ›‹ ÞM€Ûÿü‹6ffÜ×€LJIcëo —ËuB4óF6[ûƒ‰cGã[ÇŒŒŽ!0è ƒúÒÃǧNËܸ™ÃÖßþ`Ìða lÊŒŠaëo`mmMçZP{¿è›1u}Zh?ȹ :ÄK€j ºi}î£7î?snåòù—ß —óļ9töt'3ë&×<Prÿ´É8wpÄ€ͳO²ÛËlû}ÃakcS9EÿBµKHJbçÞýØ;ØÑçk½ËдûÉÐÍ‚kžwØfÝ?]gŠ……E–¿Ûêò[–Ì£›7Ë_x+++róóY½æ Â/GòçÖÍY}uw¬¯VCobÐ*šÀѱq”––2 _¦L€7 2H3OFf&9·rÉÊʺ‘1±„†GðÀ}Ó¹NJj*îèÕ£¹ùù\¼Fn^~ýúàä訚mQQ1L›<àsȼq“î]»àåéQcù”J%—Â/“˜˜„µu;úõÇÌÔ´Úù;8‘š–Î÷?må¥g—Ô¸î´ôë\ŽŒ¤¸¸ï.žté¬ªÝÆ]½ÆÙ ¹FAA!cGÇζ=Y7n~™‚¢Bº{{W©…)%%Ã"HHHÄÕÅ…þ}{!Iº‡STL±qW133¥gn8ÚÛëLÏ+( 4,œ¬¬›¸º¸Ð¯OOd2Ã4äåå±ûÀaŒd2fL„\.¯2•¥]]ªŒ?ñ1qñx{yÒ¿OoN‘’–Îà~trs%!1™˜¸«äæçãhoÇß~˜Tn£% wKGW®DFóæû«xïÿ^C’$Þ~5ñ ‰¸:;7fÕ Ê¤úàíÜ[xÄ¢­9çB.²çÀa†Œ…E[y¢¢bØöÛXYZâåéITT [~ÝÁ±¤¦§kæ3|BCÉιÀÛ¶óÑ»oâáæFTT ›~ÞÆ‘ÿ” €$IÌŸýÓ'OÐ-Tå~/-+ã½ÕŸqI’P*•ØÛÛòñŠw°ngep™ÑÇ|.„“ÁŒ5Š^=ºBYe¾½³ñÇ-”——k&M?–'ŒØ«ñœ« À —B¹p)”¾=»c×¾=AgÏñù—ë).)фڜ‡`æô©šuŸ æÈñ4ëõ÷óeÙ‹Ï©6¯TòŸ¯×sìd fº‰\Î3O.`DÀ"££ùhÍäÜÊÕÌãÓÅ‹w–¿Š™™Ö/|eåè‹o6ræ|Ï~¹±Ü`E4?¿”Ô4]æäà€«³3«?ÿ/&ÆrÖ­YMNvkÖ}CGg˜>•£'NñŸ¯Öë,×ÁÉOW¾KÛ¶m›çXPÖóX¸ËÞYö2o¬ü„ÄdÞ\¹ I’¸–˜„ƒo-{éNäJ½‚°¶ë[5o/úöîIII)ë7ýÀ¼§—òñÚu$¥¤Öº¬ƒ½-«Þ}‹…sgpøÄI¦LÇêoã?À’’Röì?¤³Œ-_¬þ€Wž[‚ÜØ˜Ÿ~Ù®ù%Ñ·cçnÂ"®ðàŒélÙø5szÌÌìø{wµe’$O-˜‡L&cý÷?PQQQež”´4¾ýágìÚ·gÕ»o±òåØÚذûÀ!B#.3aÌ(ž^ø8 çÎæÏ-›ññö&?¿ÿn؈yÛ¶¬ûô#¾Z³'G{¶lßA^AÁíýbgǧ+ßeå›Ë±·³%èÜyÎ^àÈñ“;ˆoßÞ|ññ‡<»xå|³éGò (//ç󯾥 °ˆWž[ÂÚUïÓ³»‘1±?÷þÃG9s>ß>}¸oòÄj÷ËñS<óÒ2!3+ G{{f?8“¼‚¶lßÁ×›6#Iÿ^²cccú÷îųO-â‹Õ°æ£÷пié×9pô¸Îú[â±p·Ø¶oÏÊ7–ÓÁÉ„¤d®%&aogËŠ7^ÃÁήÙËÓàT¶‚’Lâ­×^bÙ‹ÏâíåIEE§‚ÎðükÿÇÉÓAšùô÷À¿þxwñdêÄqšÿØq£†ÓÅ˃î› @jF†Î2ƒàêêÌÿ ñHiYѱqšéÚÛ TýÿÚ½—Üü<““«|íÿ5O7&ŽMRJ*ïÛú zÞ ³ç©¨¨àþé“ñîâIî]™9CUÞ‹aáz뻽\t\,ùù…XÛ´ãd`ÇNžÂ¼­9¤¤¦j–ëÚÅ OÏNôèÖ•îŸ@ØåH”(ù'ø æ>Š«KFÊà¾GܵÒ32ðàËÿtìèÂâùs+˦óy“SSùî§-´·±áù%‹@ªz̪uéìÉÃ3gè ææ(Q2eâ8¼<=Øwð0—#£yhæ Ü;uD‰«v–Œ:„üÂ|bãâi×΀”Ô´{,´„FFƘÈM4ŸCn,G.—7j %ndZ I’äçË ?_ÒÒ3øù×ß8t–;w3tð ÚWØØ´ãzV–¦µic£º‹˜Â@ LÍÉAuÞ+'Ïð_}u¯tzF†æ¼ÖÐÁƒèìá^kyf?ø/NŸeÛï²ôÉ…:Ó2®g`ok«çâÜ€›Ù9Õ®³°¨HS®äÊæ¤“£NŽX[·#?¯ Ê2ÎNN€ê€ŒŒªÛvîP¹íœ[äWÖ$íío×:89"IR•ÚÑ™s!”””ÒÑÙssójË àÝÙ“‡fÎ08M&“ñØ#òöû«icfÆŒ)·k’™™7xûÃÕܸq“>½zbl¬º¼¨¢Bap]ÐòŽ…æ–s‹·Þ_ErJªæœ_rj*o¿¿šo¼†uóÞa¯áØ ÎêëàèÈœYr*è,·ró ?¡´¦NHC·f¬f™¸ølí Nwtt$)%‰cFÓ·wϪ۩ŽÚ¶iËüÙðÙº¯ùù×ßt¦µ«ž?ÿÞÿ¦O­a§Pã>Ûµ÷ EÅÅìÞwHsÑî‡HKÏàåçž!`Тc¯rú̹ÛëkÊcAkž wÁ{«?ӄߊ7^à­•«HNMå½UŸòÙ+šµ<â` ÒÒ¯óþ§Ÿsàè1¯Dr>ä›~Þ @7ï.w|{{!>1‰Ð0Â".cii©¹¸ÚÈȈÂâ"JJJ2À€Í[!3ë …‚Ë‘ÑäååÕi[ÆøÓ»GwÒÒ¯ëŒïÝ£;¿ÿ½›Ë‘ÑÄ_Kàð±“Èd2øª®ß³´T]{q™’’R înéàèHTL,{öB¡Pp3;›+Q1:ëˆ "2ŠøÄ$;@ÿ>ª íÛKõË»aóO$¥¤qöBW"±·³ÅËÓÎîîX˜·åÌù =ñié×5ç¹ü+÷‡š©Ü„%‹æ#IÛvüERrJµû"?¿€”´4!7WÕÉrìä)Î^aâØÑØX[³õ÷?ȸ®ÚgE…ªZïÕøk”–•q¹Nû¾.j<*{¼s*k½=šSüµ<:¹©j{íÚaÓ®+Þx NnÄ'$6{yÑnaZš@L\.†jz=ÕÜ\]Y8ïQ ÿY¯í½¡?û*qñ×xqù›€ê‚å¥óçÐÆÌPÒ£«7g.\dΓKødåÛŒ6„ЈËû''Ÿ ¹\NYYOÍŸË„±£j(Çí×OΟÿ—½¥ÕÛ«¤g·®L›8ž¿÷àÿÞûP5ç=2 w7W@IŸžÝ°³mϹ ytÑS,Y4Ÿ1#†òìâ…|üŸuløá'6mÙFyy96íÚ±qÝÍvKJËxã½5e˜0v=ºu”Ü7y"!¡áD\‰ä¹W—`iiÉs‹ab"ÇÄDÎS æ²ö›ïXûÍ·šu ÈÄ1#«|Îî>]˜8f4{fí×XµâM½ËeTó<ÍñÀÓ:{lÆ”‰L›4?þŒm{æ=: Ÿ®^|¾n=_mÜÌ;Ë_fØA:~‚ïæ]{°´´¬ü–MuU>ý÷ ;ºût%øÜÞú`5 çÎfÒØQõ8î®?~Þ¤õNõymÚYñÙïêŒk.†ºŒµ¿ö¦¾ÿŸªûmYVþ±QŸ5W!寮ü|"®D‘™u™$áêìL¯žÝ4¿HQ1±\ ‹À·oo¼<=ª¼8|ìY7³™1e"¦¦¦³sÏ~ìlm3b(;wïãû-¿°ð±G155¡¼¢œÞ={hΑ”””püŸÓT( òëGûÊ ™câ® PâÙÉNn155Ñù )iiüsú }zvÇG¯æ|–¤”T¼<Üñí×G3>öj<Ñ1q˜˜ÈéæãKå¹8Í~)(àtÐYJÊJéÝ£»¦Éš_PHhx™Y7pr´ÇývvdçäpàÈq&OË¥Ðp²³sèìéNw½ © !¡á¤¤¤bccCŸžÝ4̪]ÏÌ$ìr$ÅEÅtöt×ùLêýïׯ=Ü5û À ®Î·?‡z¿Òµ‹’‘ѱôêÞî>Þüµ{Å%%Œ5œö66Ä'&¹…}ûrúÌy¬ÛY1з_“ J¥’ ³ÈÊÊ¢gw<Ü;ÕùXø_åյNj@ª‡#å…@1ºw†®ò—I`  >èŸ]¼ˆQÃîvq„»H ÓÐ -د‚š8šœ8Ø"Ôçû«Âÿ6q,4§†7#ÃEX„Á˧gó6Åß&Aîuâ  ­–8(B«%¾ "B«%P„VKt‚‚Ðj5¢DD  ÷6Ñ¡Õjp 0%1þN–C¡Ù58­ÚÙÜÉr‚ 4»FÝßαCí3 ‚ 4¡¬Œ´Úgª†8(B«%P„VK  ­–@AZ-€‚ ´Z"AhµD ‚Ðj‰¡Õ(B«Õ¨o‚­[BRåbh׳2p°³§oïŒ3ŠN;Þå BÍD õV^^ηßÿÄÞC‡Q(:Ó““ILNf×¾ƒL?–…sgcl,3¡ejqGf`ðY“026ÂÙÉ ß~}icf @EE¿îø‹i“&`aa^ëú"£c(((À·_ßz•ãZb§ƒÏV;½“[GôïË¡£'6Ŀڲ¤¦§sæ|3¦Lª×ö[ªòòrÞþ`5¡á˜ÈåLš4žáCpsuTxüŸSì;x„]û”œÊ;¯¿"BPh‘ZÜ9ÀSAÁ;OAaׯgñãÖ_Yòï—ILN ¬¬œ-Û'¯ ¿Nëû}çn~ض½Þå(//§ °@3lûý’’4ï‹‹‹INMãËo¿#"2 €”´4~úõ7õ¤¦¦ó×ß{ê½ý–êÛï"4<{;;>ûè=Í{ o¯ÎHHx{uæ‰ÇçòÉ+°·µåRx8Ür·‹-µÈ?˽ºû°hÞc€*ˆV|ô1ëÖǪoÕ{]¯<·„òòòz/çåé—§‡æýÞ‡™2q<½ºwÓ™ï‡õë°±¶ ëÆ :ÊœYÔ{{÷‚„¤$ö:Œ‰\ÎÛË_Öœã+--åÉç_DBbýÚÏ011Á£“o.{™—^‹=û2iÜhM-QZŠWÔgllÌŒ©SˆŠŽ¡¬¬Ìà<É)©8|”;wr)LgZDd4¡á€ªùü÷žý—püŸ@þü{7Qѱ .[EEû!?¿€7³9rüŠ‹‹Øº}»÷¬qÙø„DvíÝÏác'(,,lpšÓÃGQ(L?¦Nܘ8n4 …‚ƒ‡5}¡žZ|XZš#ÉdÈŒŒªL‹ŠŽåW~%’+QQ|ðé֭ߨ™r)”SÁçUóyý÷?ðÜ+Ë9ññ‰I,{ç=9Ö ré7Çe’¤úi$C&U¿kÿܵ‡>YCFfÁgyæÅ×ÈÎÉiPšSHh8#†Ñobb†µk4µ?m#t–„–¤E6õŸ¡‡F2úu@ï.ùö¿ŸkÞŸ»p‘«>aáÜ9˜Uvœè{å…¥tñô ½5ìÚ͸Ñ#UFÛö6ŒÀù‹¡<ô¯ÕΗ–‘Áæ-¿°î³U8;9ðÉÚuü¹kóç<Ú¨24µ¬¬¸ºè6e?÷"©éüýëÏ:ÓÜ:ºp=3³J(õÓ"02&–­ÛwPQQÁµÄD®&$²òÍåç•*k]ÅÅ%¤ed “ÉP*•ܸygÃw¬¶0¿ÝcëÛ§;÷ì¿ó¢áW°²²àJd4W"£$I)©ÍV†;훵Ÿ1mÖlÃÕO¬ü„–¤E`Y™ªÖDnB€ÿ ^y~)¦¦†kseee|¹á;"cbñéâ…••e½¶eÖÆ¬Yñ™_P€„ÄõÌ,Í8g'G\]ZþãììlIJN!)9o¯ÎuZ&1);»¦,š 4H‹ @í^àÚ>v’k‰I|ññ‡£P(رsw—°á(*.á¡™3Éî‰S°ýûô")9…ãÿœªs;@¿>½š²h‚Ð ÷Öo ·[RŠ Õ7ndßD’dš m³snÝ­¢a"—“_P@QqÉí‘Th}[¢WîH’Ä®}5÷·DãÇŒB&“±ïàâ5ã?÷’Á×ñ ‰ì?t™LÆøÑ#›±¤‚P7-²XSSS<=Üùaë/L›8??¶ïø‹åï®ÄµCBÃ/c"—ß•²¹wrÇœ•«?¥Kg{xÞ^^äæåñÝ[˜2aŽö<½h>_|½¨˜:º¸{õ*cFgðÀw¥ÜuåæêÊäñcÙµïï}ô o.{Nn|³öÓ*óÆ'$²âÃ)++cúä ttu¹ %„šU½®$­AV91 L+×Å‹æOhkQ¿ómu!I]\èàäXí<þ~¾”–•aogG/Oü!“ÉèàèȼÙãâ쌧»;¦¦& I8;9àêâ‚$IÈd2zu﮹\CB¬=»ùÔR0èÕ­ææmuʪ½>¹±1Æ P(ioÛžŽ.Θ·mË ¾äÐÑUõÞÝ­##†A&“Q^QAßÞ½èß·F.óiiúöêIdT,W8tì·òr±hk޹¹9åå\½zßwîâË ß‘_P@ß^=yaéÓ÷\s_¸wä³~ã¦ý@2PZ9”倢r0x¢ßPלvø©ƒÏ h XVþçOŸøL<¸u*//gã[سÿ`•›!¨ÉdL™8Ž;'‚]¸wee¤á;xø‹@W9Å衽 ¼çšÀÂÝgllÌâùs™4n4#$4œë™×p°w _Ÿ^Œ=R4{…O Ð`n®®,œ7çnCLœ˜¡Õ(B«%P„VK  ­–@AZ-€‚ ´ZMzÌ[Ú4åêà·G‹îváž%j€‚ ´Z"AhµÕÎÊH«eÏÆ¬^¨ƒÚÿA¨N£°¿ÿ°§ŸñoÌÚ…ºß·Z· A'¼¬h ‚Ðj‰¡Õjôe0‡Ž%6.P=×ÅÕo¯.t©ã3#´qððJJJ0„•lˆòòr¾Ýô=>ôP””sëÛ~Ý®yommMŸ^½èæÓµÁ娯 ßmbòÄ ¸8;7Û6¡µjt ðàáÃ=~‚¼¼<²nÜ䯻˜3¯¾þ9·êþ|Žââb÷8GŽ#!1‘ظ«*WYY_­ßÀ­ÜÛe8y*¿wï©v™œœ¾Z¿7o’››KPp0sæ/`õ§Ÿ5ª,õñÝæÍ¤gd4Ûö¡5»#BûõïÇ+/¾ yŸ”œÌK¯.ãÝ•ï³æãÕuZÇ¥°0rnÝbÇÇ«5Ïú½ÓBÃÂHLJbÚ”É5Î÷ü3K°°°àÌÙs<ùÌRF Æ MÿÌcccqeAh&MòMŽ®®¼ûÖ›<2wCCéÛ»·fZЙ3ÄÄÄâââÂÈáÃÉdÄÄÆñçο)++ç›o70îc Iœ &!1 sF Š]åóeÕÍÕÅ‹jóRXÉ))L™8±J™.^ºÄù !ÜÊÍåë ßÒ£[7† ¨õ³ àG¯ž=8w!„AM`p0ׯgâäèÈèQ#1­|¾ˆögŒŽŽÁÕկΉ‹eôÈ‘šé×33 ¦¤¤˜€Áƒqu¹Ý“kllŒÜXܧVšC“u‚tó銷—aá( ^xå5¾üz=™YY|óíF–<÷HB¢êqŒêæªRë¡æ—.…²{Ï>Ã’$$IB’TÛdu¯e¶³²BndDYYÌ}œ#GÇ'k>gö¼Ç)--ÕÌ»ì7ywå$$%±é‡xdî<9¦™~îüfÏ›OÄåË\‰ŒâáÇætæŒfºÜX®yħ M«IÓ\]]ILJ`÷Þ}\¾r…½;ÿD&“©—8óAþ <Ͱ€!L?Ž‹ybÁ|ÍòŸ²ZçibÎ}œþÅ Ï=[ï²ôíÝ›þýú’˜”¤³Úäää΂yóËåìùëM™nåæ2vÒ‚ÏžcXÀŽ;ÎÙóøó×mXZZ¢T*yyÙrͺ ï¾ÿ>O?ùÿšq½zö`íº¯ð8M`AhNM^Õ°¬<—v:ø nnÙµg¯fšµ5ñññ bpYuФ¦¥‘•uWW×fé Ø¸ùLML¸•›Ë‘£Ç˜yÿ ú÷ë«)“B¡àZB"999¸8;“QY¦SL7KKU¯³$I¸¹¹‘‘¡z`PJj*‰Iɳs×nnÞÌ&þZ¼fÛÆÆÆ¢(ͤIÓ’““5b8¹y¹”––‘švû«[Ç ¥_ß¾Õ.|ö,}ü ŽŽŽx¸»“qý:NŽMYdòóó)•ËéàèÈšWÓ]ë™Á?þ¼…_ÿ®ÞÞ899QTtûn,iéøùö¯v½¹yyÜÌÎÖ¼xbÁÍkQ„æÓdMBRü|puv&95•§žXTçu¼þæÛ¼þÚ+Œ5 €u_£iR«;>ŠŠŠ077¿£e×îÖv-!µ_~Åž?ÿÀÞ^Õ¡™ngk«ðúÔ×ö9‚ݺœgù+/c_ÙÑ#BÓj’N´´tÞ~o% æÍÅÉÑ€Ñ#Gr*ð4W"£ê´ŽŠŠ nfgcbbª—uã†æµƒ½=’$¬WPX¨y­ÈŠŠ Í8Ò+›£ ‘™™¥Z©ª×·¬¬ŒÜÜÛ5 ndÞÂIDAT¹üØ»ÿ€f>Õ2™š×ÖíÚÑ¿__6nÚ¬Óy£¦T*Q(”——7¸Œ‚ ÔÝ©ž á³ÿ¬¥¢¢‚k ‰„GDðØìGY0o®fžüxdÖƒ,\üÓ§MÅÒ‚ÓÁÁüçÓO°mß¾Ê:ŒŒ5bo¾»‚Ñ#F’šJtl ýühÓ¦ 3ïŸÁÊVq>$„ôôtB.^¢G÷™áÓµ+_|ùÌš…Ÿo†øâ«õxû½•xwéÂ쇪×çìÙ£;¶íÛ3oá ôó#äÒEnh…òä‰صgÌ›Çè#IJIæRh#‡×Ìóú«¯²ôß/0ÿÉÅøHZz:ímlx~é3ÄÄÆñä’¥,^´%‹Ÿ¬WÙA¨?C'›$­AV91 L+×Å‹æOèàÚ I’°²²B.—caaAÀÁ,}ú)† ©rAsÀÁøHIq ¦ff̘6w÷ÊËS$¬­­éݳ§fþ1£FâäèˆÜDÎØ1£˜?÷1¬¬¬ðôð`øÐÜ;u¢¢¢‚aCxúÉ'1·h‹·—£†£¤´”NN8:8à`oϰ€ŠŠŠpuqÁý“Þ'—hcf†Ÿoƒçáär9S'O¢MÛ6´³²bޜٌ6 gggìíí$‰É'âÖÑ ¥RɘQ#177G’$† €mûö̘6kk ñöòbú”ɘ™™acc“£#ãÇ5Ø¡ª´äDÖoÜ´HJ+‡2 PTU›\¨BÎÐ8uø©ƒÏ h X–€ÿùÓ'ÖÔv;,^}ý ºùtU]Ø-Âw!è$¾ƒ‡¿y@>P£„Jô‚°¶s€J½Ÿúã= …BóúVn.§ƒƒ1lè],‘ ´ ÕeTYU—s€Ú+ª±:)ÀìÇçÓÉÍ ;;;ŽŸ8Éófišì‚ 4CùTkNÕÖ6âö¹¿6€9ªf°ÿùÓ'þÛø2 ‚ 4žïàáKQ5ó (AÕ® š&puUÐ Ušþ•ïÛ&•óW.#Ó[ Bc©ƒK]Ë+Gn¥¨Â®UTÅT @íõuoëoôªN‘6¨‚Фr]FˆáÎÓÀ TYTŠ*èŠPuzÔ©çW›¡Tr;¼ÔUFí–¡JVuÐ)*ÇU"üA¸óÔyTQ9¨³H»¶WNõMÞ*XS P;üÔ¨:uÀ©Çɹ]û(BSЯ©›Àêš úú?u<ï§­>MàrTWª5^]#T×þÔ(‚дP‚ÚAXŽîu5ª-µ«œRå†@7µ;?´¿E"‚p')©Ú2U^™ÖOu8ÖXûƒÚ›Àp»÷¤Bk¼zêZŸ?Ašƒ¡T÷OTh w´ ¬=ý6¸?Aš›¡ÔÃZƒO­¦À’ üÔ;CÁ'P„¦¦ýMí Ô­?oµ–¤÷Z?ìôk}"Ahjú—¶h×öôßëϯ£.¥?Ouµ=~‚ 4—ºÞü Æfp}B«ºyEð ‚p·TpuºaKCÃK„ž -¸K• ‚ ‚ ‚ ‚ :þBtÎ ùÛIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/layout_stack.png0000664000000000000000000002053115074673150022653 0ustar00rootroot‰PNG  IHDRh€‘ÞÁsBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timejue 08 dic 2022 22:18:23“«Í IDATxœíÝy\ÔuâÇñ×p 7J"Š€Gæ]™ÖjjæZvºÝ÷VVÛOÛ²Z×úUnÙ®¶ÕÖ¯Ú¶ÓÊ#--Ó5MÅ»ñ–Kó¹oæ÷ÇÀÀÀ^ñýÜÇ<„™ïwæ3ä¾øø™ï|DDDDDDDDDDDDDäœb9KîSDäl`;™wv2bZÛ}(Ô"r®¨-Ì'ìÆF´ú~7oiJªØææmnih<]…ØRÇ×}ӹб­Ž¯]íW§†„³zx-U.Õ¾¯-Ô""MIõW½”Uû¾úöõr7ž®¢\fWEZDš:Wq.«åR=ÞU÷¯•—ƒ¨mÆìYåOOà< |Êï[‘¦ªjhK€B 8d¥å—²*VÝ×B=‘®/ÐÕã\1C®ˆ²tøbά{_ÒkB°)È"rޱ`³•Ù2â7lþüÆqãæ»€\ìñ¶PéŠP×éúBZ}I£j˜½óz÷îÝgî¬ÏÞ´XhÖè'&"Ò„ØàøÕc¯hÛ¶mt {¨+fÕ®–¸ûÞØê‰óQnPËd¹¾·iW]ÚðÆ>sö:íÛ³s¶BNxü""M˜­¬,=¶ã|ì3éŠ5éê/:©kíØÕ‘¡±XhÞ˜w™——Giq16ÛI=¯ˆœe òÉÉÉ:ÓÃ3ÈÃÃ_BZ„|¦‡sJX<D<,|||°ú„R˜—OA~.¾~þgzX§‚•Ê~V tÅ¥Q3èÚ–9<º¼‘W>sVœE¤: ¼}|ÈÍÊÂ×·Iº²5O‰Q+WµtuºÐê‘öhèêqII1ÁZw—<=<(È/8¹g¼7GÕÓcÔç3éÚ³«ºƒ«#5|ñØfÓš³ˆÔÎbÁf+«»³SÕ8»:¡œKuíêXèªw.""î©ÞOW}­¡±g³³œäÞ)×$ÛÒ¨så7älvÎ×5ÉŸ¡ˆœqM·-µ}"U­{HE#—8šîO^D¤jfCíxƤVpˆH}šx&ê&wPrii)‰;w²s÷òrs‰ŠjCŸÞ½ñ±ZINIaÕê5Ü2þ¸ëâ7ŸŸÇÔ»í²¸ìÙ»///ÂÃÃé÷‡ËhÞLçž:[dfg³|åb£ÛÒ³[çZ·ûýÈQ6oûƒºu¿q«&¶mÑQm5®Ý_ÌRßavupõ‰u]N½={÷rÇ}bòÿ>Ϻø lÞ¶iÓ_eÊó/””̧³fŸ’Ç^»~=ËâVºµíÒ¸8V®^M^~>GŽeÎósýlýå·/)9™·ÿû¾ÓueeeÌxý 22Ž7hìÒp?¯ßÄ’e+™»à›:·;ôûa¾[ºÂíû[µ–É©׉îo††¶ål¸4N“™A=zŒûÆ?ƒ÷ÞÃM7\ÅRù/‰ÒÒÒ382×.êÙ“Çïø~⤧yïÃxcú?ÝÚÿ÷ÇùjÁB¼÷§ë?Ÿ3—ëÇ^CHHó“:^q¶nã®=‚Oç~É¡ÃGˆ;ÓC’{ót¾à|žžð(ÁÁö5eåäðÊ«oðëö|õùGgx„'2ƒnÔ/S÷êõ·ÞâÊýwãõØÛ\y›§§UrøÈaæ/\Èœ/¾ í`ZûÚµ{7s¾ø‚o/&''»ÆíÛ˜=w.ËW¬ ##£Ú“´ýëöí|üég”––¸5þÞ½.&++Ëñý²¸lÜ´Éi›?™É‘£G8rô‹/!¿ Ÿÿ¼ÿsçÏl|ðÑÇÌ™7Ÿÿ¼ÿùùyŽ}geòÝ?2kî\¶'$8ÝïºøxvíÞMÂŽDfÍËÂE‹ÈÍË=¥ÿ½NdVq¦>zŒ¤”Tú÷íCÛ6­Ù°y›ÛûÚl6wï凸Ÿø~ù*’RÓjlSRRÂúM[X²4Ž»÷Õ¸½¨¨ˆøM[Y²t»÷í?‘§b¦Ó4©jÓš„;ùÛ‹ÓÈÊÌ";+›g_œÆ¯ÛwÐ&2Òˆ¿ê'°Äa–•?­æê1£êÝ.ãøqúów²rÍÏŒ»ý.Çz0Àg³æðÄ3“I=tˆeq+wû]KOwÜþÚ›o1iòöî?À¼ ù÷ÛïÔxŒä”T&<1‰ÈV­Ü~÷äö ôèÖÍñýÒ¸åÄoÚä´ÍŸ|Âï‡àa±ÿ§óôôÄÃÃþµGùcyxx8=nâÎ]ÜrÇÝ,‹#aG"zäϼSeydíúõ<o!É©ilؼ•ç^~•5ñ¶™õå׬۰…¤”4¦¿õŸÏ[à¸-33‹g_~•u›¶ž‘Áëï~È‚Å?œ´çv.yî©¿Ð*"œÉ)ümê4þ6uû$Ê”§?ÓÃNóÇ©:Šã÷ÇÉÍË£m›¨:Ãf??>zï]üí'd¹û™ûå&Mœ@Jj*ÿ~ç]f}ü!Qmì/²Lyþ>ý|6Žˆ-[·ñí’ï™óéL‚ƒŸ—Íþ‹23+‡ O>ÅÍãnbð +\Ç¿ü¶wßÿ€ƒ±æçµ|9gvåö÷Y}„¶eÄð¡¬Y·Ž»ï¸Ý1†;n½…·Þý×½†è¶m׿ôÏéÜtÃõÜyë-Œ9’G&>ÎÐ+¯$6&lеKf¼ü¹¹¹ s +W¯aÈ AîýG8‡¬Û°…Aýûгk¾ùn)GÓÓ =ï¼z÷9t£†v|?kþB¾_¶Š¾½{9®=ôJ®¾j{öõãÅéoð‡Þ½ˆiÛ†/~KLT¸ûVõïËä©ÿdØ—ãççw2Ÿf“×â¼óxqòÓL~ñ%$§Ú‚ç'O"<4ô ήÑ3h[ÿw*—Ÿ_ï¶>>>Ž8ô½ôR<À¦Í[hÖ,˜m¿üÊ¢ÅKX´x X<Ø—”Àqq ¹rSœ«*).æ©¿ý./àîÛos{üÁÁAñÌ”gÉÍÍu{?w¤gdðÛö®»æjÇu—ôº˜ :vdãæÍŽë*ŸS@@Ý»v%­üç"•RÒ’’v‹ºw cûüýÜ^æ¨ø×Nvvû’’  =#Ãi›æÍ+æiÍùícÙž¸ €_vâççËOkãùim<{öÀË˃ß;OÏ mˉüÏÓÓ «·ÕñØÞ^Þx{{ŸôÇi¬&ñ"a›Ö­ñòòbÏÞ½D¶jØ àýýýgØËÊÉÁ‚…´C•aŠjÓš˜hûl45-î]»Öz_É))ìÝ¿Ÿ‰>RïãvïÒ…ûï¾Ëñý½wÝÉ ·ÜÊ‚oÔÃ:„Õj%(Ðù—Jdd$ÇÒ3jÙ üüuæAÖnØŒ¯¯•âV9®óõõ%~Ó6F ¾¢ÞýeçfRT\BltyùyõîÖ‚Ì,û'Ïäæç‘Ÿ_ÀÑc•Ën#"$D‡h6TÆñL¦LFJjš}ÍHIKãÙ©¯ðüäI„4?ó?ÓÓèSóxOO.ìÙƒ™ŸÏ¦¿¾ GåJ~d«ò ò¹÷ÎÛ3ªÛpôèQj{±±±\{õf¼ñoºtéLçNç»=Ž À.êуԴTÀ†Åb!??ßÅcUå¡úsÁéö!!q,ý-ªü<=#ƒ?\Ö§–ý]=Ž¬Û°™®:áëã㸮[çN¬\³ŽŒÌLBê9–}ö—_Ó¶M$·ÝtÛw‘¸»Î}2³rˆjÝ€°-hÕš‘C®8±'"¼ðÊ GœŸŸ< €)/N#%-¦MgÆKÏŸážö£8N‰>ʶ_埯½Nqq±Ómeeî°×ÅaÁœy_º¼½[—.ü¸<ŽìœœZï㺱W3tð•<5y ™ÙÙn¿¬¬Œ¤”d:´ï@ËðpÖÆÇ;n/,,¤´´òyøX­dçä—W¹¬c±Xðööæ÷Ç×…‡‡Õ¦5ŸÍšã¸nßþýìØ™È¥½/q{|{÷àhzwŒ»ž±£†;.wŒ»??_6lvu»…Ò²ÊÃ<ÏÂÛÛ»òû¬šŸÉxèÈQÇׇ%açnºw¶ÿ²¿øÂîü°b•cY¯æÃYœþžœ•NÓQûö 6º­}¶Ü¬!ÍšñüäIÄF·eß$#ŽâhKÚÇò¯Lã…—¦±>©ÓþÁ¯¿ýFLL4;5rƒ `ìÕ£YüýÜyß\9piÈ3OþÅé~žz|÷>ø0Sþ÷^}åe³qغíÞ|ç?ää³eË6Z´eÌU#¸fÌ(¾øê+}ü ¢£Ú°~ƒóÚw ((ˆ¿<óWºtêă÷ß‹———õéÍ+3^cÐÀ\5|(±11Lz|“þ:…½û÷ѲeKV¬ü‰ÇÆ'å—6=:~xC¨ ?Ÿ°–‘'6Úz´ŽŒäÚ«Çеsg¬V+-[¶dôU#wÃõX,`f͚ѭê:²ÅBËðp:´k@ûví>d0JJJéÓ»7—õ郧§'žžžŒ9‚V-),,¢cÇ\wõ5øúú¢ÚDÝ6OO{(33³ ¥Y°ó?{- Žû gôÈÜsGåÒJpp0#† Åf³ƃ÷ÝËù:о};üýýñööfØÁ”–•JLt4^^^ ПÀ€¬V+íÛµ#0 Ö‘‘ ://oš7kÎ}wÝÅ.íSuDޱW^c¡C»v´ ?uây(5 o«µþ qôX:}.¾ç…Ô¸-,´¥%%tlëô&)«ÕÊÅ=»“——GdDKºuîDûØh°@û˜hn¿é:¼¼¼éÐ.ƾƒn»éZ¼<½ðóõeÌð!\Úë"Çýy{yÑÿ²>D„‡QXXDófA ØÀ€:uh‡ŸŸ/>>V"#ξ`-).n’Ÿîýú¿ßúHŠÊ/Ÿî]V~q9Ïvu⎪q®³/öO¥ *¿\¶'ñ· àñôcté©ßèRióºUø•‡E ?7—–‘Mï<"í;u¬²Ë/y@Ρ®± Òè%ŽÆ-«è'©›*Q©É¼“PD¤©iü‹„ú5'"§‚ÚâpGqè§("§‚ÚR¡Iœ‹CD¤):}¶ØØ÷tqL°ˆ6›ýpXq8mGqxzx’—EP3H^Dj*--ÅÛê­Ž*NÛ‹„ž^9”J@`ã¼Å""ØlÜd0íÛŲ4.®Þ}ÒÛg¡-ÃÃOñèDΚAK ßý°”+àŠþýùlÎ\ ñññq¹ý‚o¾á‹ù xöÅ©øX­ÄÆÄðÄ„ÇHHLdÙò$¥¤b±@— :qãu×âçççØÿË )-³Ñµs'¾ýî{R"ªu$7ßx#-+''‡ù ’˜ˆÅb¡KçÎŒ=ŠÙóæ³wß>¦>÷¬Óö[·ýÊ»ï¿Ï´Ÿ'00°Þçž›—ÇË–ñëo =–NxX£F £G÷n5¶Ý»o?~ò)‡&&*Š1£¯"¦mÛÛ-]ÇÚuëÉÉËåÂ=¹áÚkðôô¬w,"šA‹“}’ص{7CÙ=°?òóóY»~}­ûÄFÇн{WúôêÅÀþý¹¨g²²³yèÏسoáá¡X­Þ¼÷áÇŒÿŸÇ)++s쟒šÆÿ÷6Oþu Å%¥D·bYÜJn¿ï~Ž¥§;¶;œÌm÷ÞÏ’–ÕÛ‡y_. 7/Øè–._Áž½ûœÆ¶hÉÊÊÊÜŠ3À{|ÈÌÏga+³Ñ¦u+~KØÎ>ÆOkÖÔØöé)S((( Md+âVýÄ]÷?Ⱥ Î/8þýÓyeÆ¿ &2¢ïü ÿó—IØl6·Æ#ç6Í ÅÉ?.%¢eKºtî Àù;Ò*"‚¥q+Ø¿¿Ë}ztïFaqó¿ZȨ‘#hÓ:ÒqÛâ¯æ9͖׬]ÇÄIO³iËV.¹ø"ÇõAAÌ™ù‘cÛ›o¼o¹¯¿]Ì]·Ý ÀŒ×Þ ºM¦O{ //翺!Í›ÈÒåq´o @II q+WñÈC¸ýü¸÷{x¼ãû²²2îøQfΚÍå}û:m;ãåi\س{ù~÷ñð„‰üóÕW™õñGxzz²nÃF-^ÂÌþKl´}f=zÔUÜz×=¬Z½†—÷s{\rnÒ Zœ|÷ãR®p9eeeŽKÿËû²zõÏ5øþªÆ Ï%½°X,$';µàçëã´mxXÑÑѤ$§ö.×Åoà–›ÿX#ÎV«•¡ƒ¯déò8Çuë7l¤°°ÁW t{¼¾¾¾Nß{xxЧW/’’RjlÛºu+Ç×þþ¾Ü×$§¤±ÿ@ß}ÿ=»wsÄ 6º-çwì@ÂŽD·Ç$ç.Í Åá·í ¤¦¥1kîÚ·‹åÇeËп óæçµ$îÚMfV&»vïqëºó;v %5•öíbIJI!))™»ÿôÓvÉÉ)t-ÿŠH]hqXòãD¶jÅä§ž¬qÛ³/LeYÜŠ:/¯€‰OM"''—‘Çѳ{7üüýY»>¾Ác³•Ù×lsrrjݦKçÎÄ´mËÒ¸´jÊŸVóⳓô8K—¯`ê+Ó>t^؃æ!,[¾Â­#Y 8LÞÞ´jÁ£ã¬±mxXXƒÆ%ç&ZûZëÒeqŒ1œ‹/ìYãöþ—÷å»–R\\Œ···[÷¹.>ž-[áÇE ^¤³X, _tTkã78fª®\5r8ß.þŽÎÎÇ×LJK{÷nÐãü÷£¹zÔ(þ瑇×mOHp¹mõúÖÅÇÛ`‰ŽàüŽX¸híb¢iÞ¼yƒÆ!Zƒ–rñ7‘ž‘QëRôëKnn.ñÜ[´§§ý¯×׋“•MFÆqfΚMiiÃßaÑ’—÷㣙Ÿ±jõÇúxü¦M””T.—Œ6”¤”Þûð#†‚‡GíÅ­V+$¨\÷ôôdã¦-$îÜEQQ¿mO nå*—ûÿý•éHN¦°¨ˆ•?­æí÷þËo¼ÁñËè¶?þ <9y Ê×ÜsrrX·>ÞégàççKJJŠÓ‘-" @K¹ïËÞè|Á.o¿øÂ ñ÷÷eYÜJ·ïóò¾`Ä!¼öÖÿ1|ÌXF޽މ;]+ìŽgžxœ‹zöä‰g&3høU :‚ç§¾ÌÁC¿;¶ ¥÷%½Hܹ‹«†«óþ<==5|ïü ÃÇŒ%;;‡‰~„cééÜyÿ 6’''O¡s§N5ö  ¢¨¨q·ÝÉÃFòô”ç;z4÷ßs—c›ÐÐüû_Ó),´o7xäh†Ž¾†¦½â4æ«Fg˶_:êjÖü¼¶Q?iš\ý[ÓR~ñÀ¾â øþ@Pù岼ܜ§krêmOHÀÏÏØ˜˜Z·Iܹ‹²²R—ÏÉÉaçî=tíÒ«Õé¶#GräÈZ·nM³à`’’Sðóó%,4€Ô´4233‡öUص{7ÞVk geg“’’BPP3ZGFÔ˜%Oíu6mÙʧü×­ç¾gï>ü‰hiSLaQIIIx[­DµnMYY ;oVÉÊÎæðá#thߎC‡~'3+‹˜˜èÏ»ªãÇ“švà`×c>tèwò ò‰nÛ¶ÎY¿œü'kìòKP%@`+¿8(ÐÒ¤”””0úú›¸å¦¸ãÖ[ÎôpD€ÆZ¿ª¥IùiÍÏ?~œ¡ƒ¯<ÓC9a ´4)_/^B÷®]iq¦‡"rÂt˜4)Ó_šz¦‡ rÒh-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆJ1”-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆJ1”-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆJ1”-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆJ1”-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆJ1”-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆJ1”-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆJ1”-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆJ1”-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆJ1”-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆJ1”-"b(ZDÄP ´ˆˆ¡hC)Ð""†R ED ¥@‹ˆª¡¶U¹ˆˆˆ{ÕÎúm«ögõëED¤~µ5´Î–º3ƒ®zGeåZDÄ}®úYoGÝ]â¨zç¥åqOE74Éõªåz›‹‹S ý'~€ð.¿/*£oi̳9 U·¢“%@1Päã:ÐÕ/5Ôèê\ýA7þØí‹=Ò^€' ´ˆœ{ªº{+‹€ìÎÃÞÎ0‹vh•q­:{®xÐb Ê—•_çY~± 8‹È¹§¢—³åŠV”ÿY芙tõ™s`×5ƒvµ´QâŠW\çMåìY‘sQõ mÅGÅLº¨ü:WK.5d‰£{€‹ª\_1£®˜=WZDä\T5Б®ê*—9µÄQýÁ*¦ì–òçßU_´ ´ˆœ›\TQäâ*VÄ»Þ7®Ô·ÄÒX­IDATAùƒ@å¡uU×X*fÍŠ³ˆHíG¾U¬=×v4‡Kî.qTD¹ú‹â,"âÌU¤«ÆºÞ0W¨+¨V±«0+Ð"r®«úNÁª¡®þuõmk¨/¨–j_WqõY³-"çºê‡ÎU-»zcJ­3iw‚Z}›ÚfËŠ³ˆˆ»'Gªs™£!Q­m[…YDĵÚìÖ¹8WEYD¤atP1Æÿí_Ÿ§ îŸIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/popover.png0000664000000000000000000021033415074673150021645 0ustar00rootroot‰PNG  IHDRÚ·©°—uzTXtRaw profile type exifxÚ¥™ir#;„ÿósÜÃ5bn0ÇŸ¬’,Ëêî×3VXU®…D"A›õŸoó/~‚Á„˜Kª)Y~B U'Å^?í|;Î÷ù™ÍÊ}õÛuc×}*=GÝ(é:ºÇõû…ÇÑ5ÎâË@eÜ7ú÷5\G)o]öX¯éù¼ª÷@^®î ]˲©–üº„¾î%Þã7]_¡|7ûÇßïÍÈ<^dyç-ßÞËe€×_1¾qCøyÐñ@ã–~{ïîÁpÈ'?=*m55||è[TžgoÑŠëµ·h¹ñoNNÏãÇëÆÅ·þ9¿¼ÎÊ&ß®”}Yôæ}ýÝ{–}ÖÌ*ZH¸:Ý‹z,ñœñ\g ºLK6ó"ŸOåS@õ ÓÛù W®í‚›®¹íÖ9701È2’9âÏÅâ³T^ãôã¶d_ýô…¸Žöàåi‹;ÓV;Ì™­0ót<*ŽÁý1ûÂÞš Ω/ã•§Ø%¢ÎÆ œ~óqûvj<~|Þ4®žFõ²¦Hűý¢G÷ÅþÚó`äxå Ëó1uÄç‰Qs>ºälÉÎáÈB€¦‹Ò‰€‹Q&FJð>›":5¯dw•(\6\‡ÌˆDôÉgbS}SÆ üäPÀP‹>†cŠ9–XcK>…SJ9))¶ìs09æ”s.¹æV| %–Tr)¥–V¥zH3ÖTs-µÖÖ˜³1rãíÆ­u龇MO=÷ÒkoøŒ0âH#2êhS¦ŸðÇL3Ï2ëlË- ´ÂŠ+­¼Êª«m ¶½ÙaÇvÞe×ÝžQ»ÃúãóQswÔäDJÌϨq5çÇNé$j̘˜àˆxÖhјÙâBœÆÌV!+¢`dÔ˜M§#‚a9‰Û=bg䊨FîÿŠ›Éá[ÜäœÑÐýeä~ÆíSÔ¦–¡q"ve¡:Õz²o³œ£Ÿc·:VΰKèÃE¿‹ÁÒŽÁi;™Í±(IKjêH$|O~û¶YM¤ÍòcJnnÊoHŸ>ïe\؃Ø׃2/í#4`[^‘ؘ'1MÿZÒzÝ«÷àwíÛK®Õ­UD´ÄËRwåñâSݻؑùnÍïuϤɮséºu6Ž:_d{L–æ]Vø‡©–¬\jÓ{ÒŸ;ëÜ1ïNŽëZ4l©loOXŽ›ïwÔ[ㇷÌñBˉ½†‡à”/+]ɈŠ12œê*ê„Õ‡2·ÍC­ªÉÌâçl‘‡Hë5S ³éªô ¿z³ð­©Jfj K' uŽÔÈš6ëSh¦-²3+(5‡¶×´ú[ÖDí,˜%.d…oäƒÈQH¦ÚVªŒê:,E.®Úï®O Ü7T¥]ˆP<2Tf'ÿóöÙ¬ö÷„Wý¯"ô[¬ãNs–¡QÇMI¹ó·ÃÆ«ûaßJ‚…d 7Þ ëŸbÝü;¼°!‡¢\c¬&yÙ=à²Õ d¥ö3äüU*|*°Áwšäù$ùýR¹Ì0/Y¾~—å7à‹· v®…h÷¸¤lËkÀÇL[Ý2V÷k•ÆDÚšQB†Õ²´Ô]ëM5‚‡¢%g©> §R©„Íàè©bÐbs•™»'#biÔ„_Gò^ûãj mŸÕ‡Z×Èi÷V¦™±ÍRaq¹„‡Å7ìï±íÞÚØJ,Ô…:iæ F&™JðkNºøjŽ„YuŠµØ‡ˆ)»«‚ÜG\E ‚ø±Ø¹nV%íf‘@xMϑҶ›ZÒìn‘±Ó§ª+“*ñÅY¹~­ìÇÊg Åëž‹*3ŒœÈœ ¿­ÐZ]#Ë¢†(ÔËô’ÕwJ:yì„t³]¢–rñ™x)w *$õYí[½R|ºyÌ(Ȱ¹Œ=4d‘»ºdÍgQ&êÓÁ¤QÌ XfÝ9$ß%Œj‹kóòF  àè ô£†F.‚A›M·ˆ;²áñºmMŽäcnzǰ|á Êè«XÕT»£—U€Œ{wäí­ïp$3:c_ýÙèbÚìÊ}‘V•¨È -‘±xÛü#4Ó/Éžu!∉¬‹iö*%ÐÖÑ2 ³<|¢¥¯Šñ+¤©h#Íeqh†@rG#l&âîWyi¾áÁ:$ÚH z†ÆFÌJ8WƒºÓ¶¨Ð¿0-gkÛAJ8»Ð¦'t`M2,ä¸RxÆÁt6M§üê?ñCóDÝÈQÖj3ý!!¾ò˜¥À+µœøIng+4ªVø¡Pú& ȃ¶‡úµ„÷†šcé±3o· ÈõËÛÎâ,H<]¥°Û­^ØX§ÍVTz;¢Éô´Z£Ñ *Kˆ4W5(v<å$&¡ÓrЃƒÒ¡^ ê×¢JW<˜|Ùb§¶L©U›Ñ…LÔÂGå àèÐßFúë©ó·œIk¨p;i[P@-ÎA³D¥$×Læf÷8X.M<UG©~*Ø&àÂG5DÝ4Tx‘=Å—p?® (‡›*J Yêôi =CcäVÑI? æ¥ÞŒîWEŠ0Ù1ʲC[JäáFíü!1È>ÝëwÔXñQjÚj^"ØÂ÷go¬6e{£±€Çu¬d&墼Y!¶Ñ®“ûör!*¯û3^=3ã¡©ùM8Ktãçñtëø6sã áAïÐuRÉ`lÊ DNI虂Ÿ²TrÊDâ"ÃY½è4P$DˆÐw³e‚v@ šN¥¦ŒR»ŒºLRƒR‘¨jlbÁÐ]€Š¼§Šé§r‹×¾¢² Œí¼£ËÓ`’~dg9ÓRy‘&¦Yõiê`Jì®$°nh>ÏŠ)A»×Ft;=4±×쫲/?³¦¥”Ïa¯~-:z&2ePÛ%—Ú£ípH‚ápÎ(p¹Ät»¼ >4€‰@>;‚½5š|Z&šxí¾a¬[&£BY½4$‡2"Ýu ŽŽìTÂ9ÐÏSi¾¨a‹T±âlÔ R”9dE/«¢k¨kÒ Æ™·H0Ä(ž›}dŠÀ¼œ6Gè½ç¹ÖŒ¦[)›ð‹ ,[ ê1kzøLh’"³nj1É2¶¨T¨¦»øpïâw+¹#˜û¶T4Øži¨0fÝ:O€ÐiŸŠÂÎñ'qÈÆ5‚‰Øeu´@©ëÈ êg[02® Ö“ɯ’î<·lP7‹Ôœ¢ƒÌ¡.ío–†ýëúŸ‹jA›E§Œ%œŠOA!×Lß/R´Ÿ§RU£Û:æ²jëçÙ“@3TÝ5F³MO¦?!ôh†&Ý,SࢶCâÇÙƒ~Ök_é£Ïé.`ÂmNÆÂj%i0T©:¤+ZèÌÅ5­™öNUHËi‡ÓÈœNóÚ©Jí{­"~Ñ ’:WoGu÷ªxTíá wÿ…pcÙU7j“Yœ´üD^|®ükŠ­ïïé-ë~àôí®5ô–¢›ù€7Õ¤e²Ìedn Hž]Û3%¦¿$ADR©Ð•†RßH™à®“ÑQ儎׆è興zÈ;’§ø‡®qË;áqý_‚¬©§òá§Sª‘qTŸÐbO:0û°Aôô_Ú¤z¤ÍüA×í1ìƒ+†®•&zª×ÍP2µSEGOt‚jÔk-Þ#qáî®Û[È.˜ŸÞâ´Õ;äV‡þÓAûàÛu‡\@p·…5)£Pt%[Ä]b4Îkƒ9:oô ¸ÍÁp1¡'ZÕ½#ë‘5$ðUú'ÈE7 žUÏr¹¨T£ÝOA ¦Ævê¦2¸wÖ 38U¯L%]ÚL¸–å#2iÞ'’œ Ýï·0´uOVªÇ@w ¾BYõrŠòüV”Ÿ5y‘gNMyžy‚ŸÎ£Ï=Â&¡5Õ15ò–J13õáGVaµJc©qçÞ m8ršºb¶Ø ÌTHR/'R¦ "Ј1{ŽTíîÆ(Uw,²Š €xÀA(OHl7Ž"”uÃIïè¾æµ3ä㘠Æ-Ì¢Õfnd+Öâµ£DVx¯iËk‹V͵~2T7l´ÖÍœ³‹û{ÝiKT»F÷tÿy×h³À‘9ÔË5Æ|²æìS‹M®µh7tV£°„Iu#è¶MîX½ùÝ+ú¯«ß %ï6Ó`g¿Æ|¼táøý5ýó¬!Þ›¬ÇÙ×2t+ѯºÐ•øË?Õîoy¹ö÷ÖE»^¾{¸T¾\j.9uñÝñj–*Á%µ™ßT0žJJŽ5Ø®üJmη¶õÈ­iz¥a’Ð"UÙ+#† ®2`/)©FE¦–1Dãv4ª=…»€2z†ÒˆÍQ: €OÏ’èlñÞB_#†œ«MÿÙÉT-/õB^VcXN¹!ÖKž{" ®Bú6šz]/¥^EýFQWH›¿GAGÊÄÆmaVü·ysœ¿?ãùì߆~ŽÆÞH2_!|Í¿Ïúæ# y/¨§©)·k)ûçk¼¥ÅøIæÇW~Æ÷\R¿…_øMÿ4H‰_ÂþF=ž]dz ¹(—ƒYTøÐ­ÖsH‹6 h 5H8ú4Q¤ ¡<0L³œZ•x½¢´5«ù/”j0gä}õ„iCCPICC profilexœ}‘=HÃ@Å_SE)A;¨8d¨NDEµ E¨j…VL.ý‚& IŠ‹£àZpðc±êà⬫ƒ« ~€8:9)ºH‰ÿK -b<8îÇ»{»w€P/3Íê4Ý6S‰¸˜É®Š]¯c}’™eÌIR¾ãë¾ÞÅx–ÿ¹?Gš³‰g™aÚÄÄÓ›¶ÁyŸ8вJ|NF€®] QsœïcÇiœÁgàJoù+u`æ“ôZK‹½ÛÀÅuKSö€Ë`àÉMÙ•‚4…|x?£oÊý·@hÍë­¹Ó M]%o€ƒC`´@Ùë>ïînïíß3Íþ~&r‚à£Ôã xiTXtXML:com.adobe.xmp ôè5bKGDÿÿÿ ½§“ pHYs  šœtIMEæ ]¯Ž IDATxÚì½{´~YU8×:ß-(ª@y¿5ÊËGÀ j ‚#JlG5&¶1bQ£IÛ¶éVƒ6 FTDÅ6vk:1m41jŒ1±µu´âÀà#¢‚P"ÚØˆ¼ †Š/U÷¬Ù¬ç¹e¤dŒßGïUãÂï÷»÷~ßùÎÙ{î½×ZsNyâ}ŸF   0Bj€BüG (ðŸˆBuÃé´áb;ᤠˆâßÏ÷ &(PÀxÁü7ÒQ~Xü¾Øê¿ì¯!⯿HÒ_‚Ò×­ („˜ÿ.PáŸßßÐÿ ŒÏ)ú‹I\ Å`bØ(P* ôÿĈ;Ìß“~­÷–"ñ~¡ »ˆ}O„qeŸ%ÿ÷ÇòcÇ{™€úÌþ<ýúânø+QÇs÷;ãoǾ˜BÆýóÏ–oMˆßc¨õ¸`|—Ÿ0~ÖÏ•ý™cÉ™>¶ 1.Fȼ>¿6` Uæ¿!"0!Lü3j½^l¿¾‰—gÅøf>23ȾCb¾øÐËOcOãÂüa9EÙãÉhÍ=‰˜Ÿš1ó3[ŒÉqAÅFØAn äµøæxæ¬g/1žóÏAÿ3¤Çƒ‰Äï°n?ãù u\#{ÆÄóg™×Œ˜ÏþÌu\‹Õ§ì§ÜŸ6LJø,æg’.¡?#Ï/£Ô<Ú}ìÖœÎ1M˜ f«¿³ «%„Õ¥Æ#¯<'ÿ¬ƽ$„êsQüù%&PÇL› Næ8 ñ!kÖÄü£o}ËïcaöÂì…Ù ³fŸfŸ Ö·(î±A P(ˆrŒ H½) Uˆn8m'œ.N¸PÁI´à"œ9F\c²õ$/ÌK2’0¹2©$~>“°¡ÃD^wO‰ôI1Ç¿ L{p3†XN 1ÁØ ˜€_ ›æR3®!ïÁ«W%)PÎÉB Ô ýóQ ­)‚+dCs~Væ"5'AŒOH‡U¥Åä °ñ•P8žº‰fB«·zŸZÜŒ1Ïü¹~"Rw·‡Ê¼k¹Ø±"‰…(ÁT,ÅŸ¶ü4„€±ãˆ}E½)ãYåG”@ýC‹¼¸4ìl𠶸–¼÷lÜ>Žs#€\” lìÅ»æHÖ½_*Ðѹcw¯o¸jqt¤@õseT$Äêá13®_4€Ž2Æ·_£á„ˆJ,ŽŸ+·‚ÚÈLÀ R.¨Þs|Œõ¤çqÞè\"eƒÔheRb±€ó¹ 'Y‹ŸúŽvظĦ•Ä)n£h€´( 4é£5q³Æ%Ù0 ½ÜsÉoŽÅ±!\˜½0{aöÂì…ÙçƒÙ§š6&€ö',²‚¸¬<—رA¸aÛ6l§ Û.N6õ›E&ªÅ‰+²žJÉ8SÑ<»’Œ÷ÝêÄåÙÂ4Q]!&Ø4Nßñ84ppWB=w™ E©|°ç •8­°² û ææà“7ËÐïí£´F™[ò뺒٠"0Nwô×P6\éÈìä©Ù2û!!AõÉnœï,1¬– Bý>’ óÀWÙ(@Ô:£” K, Œì‚0óQ+JP­N—R‹z€æ‚_‹¨Ô½Í¿“Ä&I¬Ç, AX<˜Ú ð\œéÏ׳ €ÅzFëE@P™'¥æ×ªõ¬zñó,^/ÞžÐò”I‰…Á°É©ÌÌOŽ4…Ä '¥ÊPÃF§ÁȼD&HºØ§øAj”H²¤IŠH,rc:Ê<´’ñà:»#œå¼ÈÅä[Vé´ËRdO`a@52M<­$JÈjîꀳ֯ƙuÊÉfµ0d™9O® ˆEi*{"jœ\c¢ÎS>zß h»è&f5E$€…ý<˜Ç~«q(y -J´j‡²˜gU¢IB$î›  H÷4b;”ç0©cé ³\ÎX쳜`5?K§kÆk@ëô}( Þ‡U²ë×ò¿l=k“Ï"ý™©“ÚÌdIŽDlˆ“é(>çb•ÒÅx¨6v–3³±¾h¿—cMkÌW ¯îl—úó‰µ!±¯RYÕÎÁ *’í#õ’í"›¾¼ $…Z Õá339Ö¤öý‡¸_…’÷ÁqÆ?Nfª; CÝz‘Z˜½0{aöÂì…ÙgƒÙ')0íž0™€mBQ( ®»¸Àéâ„MÄ3îâ@é§ÒpJhö²K{”3§ºSœJ!{€½Å­ÕCμÁ™1A^-®W ˆ(ó„çT€TëÆ(ÏB¼ÌJ€Ûáè«RàÐŒ¨ÕÙåÄš yŠ=£ŸUÆ@èºYMx¯\fù#NÛ¢1xwïãÉ)EâßEª^@FÖ!¥å¢UãºOy->.ÂcRÇÈÏ'‘åÏ.1¡2Xsâól‹¿ægÑŸ0&K¢‡Ã²‰À4NÑ*Àå¥÷¥Zö‡n‘ˆÏÀ*ŠF6J´¥ìeÖªoR2k!Ç‚­?C«¾7?ÕW™œÌ‡Ð2Ç¥ûî8º5uÜÓ,…åÒJv6ŽÎ“‘᪦í™÷ƒA"Ûšü{Ìeñ,ÖL'Õ†‰•[‚ÄX[öÑQaÖ÷Ö°;–PÆNÒ»…E8w—^AÎÄŠæb¤™Ÿ¨6Ë짌œ ¡b‹6ÙªqÈÅ|;d´ÀÊÌ é‰ŸØ`ì›ÝnaX˜½0{aöÂì…ÙçƒÙ§nØfi?éþ8›n8]lÐízá½nÍEáèǑÉ^ä8»?+û{ÆÈbd”?ûóVs½±'‘DIL¢œc*Ø«H£l™‘nÅ›1Ÿe€ú °.šŸàrÂ.n>ÿ(ä²CÙÓ&1™¤¹¥ôãg}hEÅâžH·­) cA•œÐРЍßɬO¼Ÿ Bʱy«û+Áî0srE+%3$µ8Z/9ð”Çbug–Ë3Sþi·Z€I­RW]7ƒû‰~)ö½À8¢Fy™£ìW$t »ÄÅêò'äX ³ÇRº{Q·S!ZôÆJÊqÜAc¼wñXèŸ×Ä:»Å¦‘Ôߥ{ýd\Kö£ÖØ(òX—+ƒÇ9Õ» šçÿÎJ Ðf÷«Ê¤j ‹‰Ü"##«€êÔš+Ú™Ñn‰Å(Pk¯ÇöQuU{-¶Ýâ 7™¬ž_!ŒV=½*[oÐbÓ*‡–iFf*ed'«Ñut¯ÎiDˆì‡vß™†È ¿¾F³.é/Ì^˜½0{aöÂì³ÁìS1.76»Ôzlr...pq¡N°P"ÆS5íóÀÿƸ±If1£eœ’u’<2íõýFˆI`:ú“Èè'ÔêÍÉïãlñúÂ:ýÚ••¥³f|÷b$E2±š<ýlªâñJeŸíx–öÖ¸ÍHÏ{3®¢´ê™eœ"Q.ãžV_MM«2®Ÿ’÷虓"ÉxöÅ™%'/#Q'ä~¯Ì²d©‘Du¼DmÑëè×£cJ|Võ†ÈêU3Û«4—$ÜiÅUb¯–T9  ¤Ì4“€¬Rº& ´=3«Æ+ªù''Xt)ÍÀÝbòke 6éEJ |­I&#ËÖI¼âºÇæŠcAµ+ ½±`m!P€™Õ“"Áhƒ14‡ó³¯0KîÂÙÇ9TÆb™˲ô\h ¢—mŒ{ß ™ßûÈÈ`›£6‚]î«þa!­LžÌ±\@k±Él…ni, Þ«ÙZZôvopÎ;²êÁñ‡ò@ý‡ú™)j •{½”&K~aöÂì…Ù ³f_ó˜}Úá=K›Œl´u»§ë×mÐè #é Äž<„€dЛíãpVÅ¡(¿eßWfIŒGÚú§;ƒu¿L2§£÷Çß!úұéÃ'¥¯C^Q±bÕË #dY‘3™ƒÐ8m ”K/+ I/!LY!rÉàíñ8µË8¡¡ EUŽ®A©’Á°!€ƒ¦OÎ;ö8Á¡N÷„Pç Ô’¡kRÏÍ™êMvi¶û¬:8ά€Ñ³h~ú”Èd–[—gd¶”R—^÷CâÉOÝ Ž%l©¬šp™á!«L]²aqù{š´˜õ¾°A™` î:û§"ƒ`äÆF&®@d2³!l¸ÜwÐ,žóåQ2îfº¹ýÑ"^•t—ùø’e¬^Dï#euÚ›‚ê)ìM„•Á´ZP¸îª«¹+Ñç˜}©MoQA”ÿgEB©ÁºR“X׋ fá”[5|ËþÌ$|Uf½;zA˜D†ŒØ ñ_éSe|®\É4ú‰%R‚–óh¨O0².ˆy‰ _µ “̹l&#~JÅ•U÷Û ”e™\¸aaöÂì…Ù ³fŸfŸ¶`}š9ÃJlÛî²]‡í¤Ð“ÆInÆ©V:E¢ŒÌ1±¤åd7—]ûz˜šRGìWLfhʺäÔ˜på ŠÅBT€•}C<x,&x‹×‚6Mü–½¹ˆEÂìGë’D ޏWŽ—1©‚´BÄ5KA;Vò_š®"¡ò£}(¬ÈV²MÕÃGz¦ û¸;’Cf¨”CýsX0Õë„Û’•`OXÚ¯²Û¸ÔÁ9žÐ Âø3Ëa’}“At y/cŒ9(‘|”Tà(qµ¦'@kÝ[Ï<âè˜Ô¾8·œ’B ’EÒ|/¨\ÀlÍÁÛˆ^hÄ"™¶mËÅ»”¹º`dýmƒM]YËìdr±”æ.ÑšÈ"=«Ÿ=ß«ŒÎSÑ1:H8-i†±ðYµ:4+\ú}­A1¥Ä¼ÚÈ’3:YF #";¨£ÑÙ(0±’¼ëžÒÎL¦D™½º|Ä&±ÀVÛƒÖü×I¶Š2²r‚yl¤·kížå{*wèè ’Žà.u.Ì^˜½0{aöÂìóÁìSža¨T/Búé„ Ý¼Üx ç)CJÈ[óUW\—Ç0$¡²ÌX'j™È•‘Ñà®U¦ËžŸÒ²—Ù#šüc=°n?ŒAbè|CKmô7É^E …Ì=?SöÇÕÕ†LŒ&‹WƒÀ,«Æ@§Å$tÐÝ$„Xlq —Õ³&~}q2Ü3›Ân¦Ìiž<[X?;/5iíË2HÏÔ³Ô6¢` #]ùŠ»S)ƒ ½$@’´Å"[í%ñÅ2i˜L}-R–#mn _ “:¢Y¢¡ø³ø½Óȼ±J”Û¡Hž`éÄ'fX`¢D¯ØŸoæy.p¥¤ èè§”$œÐÉ2n msã°Ëo;Æm¨Ô¶i€ÊP:‹438’7khvVf*Æ'âYevÃઇþÒì³…`7o?(ÅI  e‹ofF&°¡Œ†BA‚W‘U06¡n,»— £ —2‹’¢Ô%4i*2@ƒf…ÐÜ£(TI˜ó­pöo†TXepZMPf×bnî„£¿•¥œ €áJ½<6mIP3vT­ú/3ó›Yª,år4,Ì^˜½0{aöÂìóÀìE zÝN¸8]àâ¤Ø²¿%ÔÇq;Jûw³Tæb¹¼ÝB7>Wj$‹=€ÙdÂOöÎqº4t¶²úx­Õ J¹Ÿ­´Y[-Ab¼Jè÷ k*ÇÑU2cBi=àƒ¡ ºœ(C¥ ihO911¨£2Czb£åp ƒ–Y¢úìùù·9fv·–s`íµ2™ìg*pŒE|6di<úŽeº¾pŽ®& ô cÕrhßrôJY˜½0{aöÂì…ÙçƒÙ'=]`;pq:aSÅIÙºrDf&Ž^B„É£Êy$ÛÜüÒvÙÛu,€Ž‰{`çdFd8=ÙÔ7d{xÕ䕱¨°å]gY3{{Rï0O4MFVÞq"k‡")Ö7À e‰Dx+È8}ÅàÒÉOŽg}’”ñ°³‰ eŒq ýש ³”;°{ÃIy”V†m•ÆZëRÚiÚ¢ÒÉúÌq&ØäĽ‰ù*m£Ë©É+W––‚b-š‘Û†m®è (eL.šY#ÝGUÙ„8¹ i('–¡aPƽjo/â‰÷îEÏ™øÂ]2PB˜&qE±ï·ûî%*Ù†TÊ.ØÆBI¢J…µÁÉ{‹§ª¯°ŠÌ©P‘î~¼8hÀÎM“aš3ìh-2¿¶-åÆX‘²ôuûÖxŽ¾Ø°€–¬ƒtg[Ù·‹îCZã©›ô¨\PóÈ¢Gׯìk+dAxˆ<ÈqG]UélpNòÞÐTä^ÄŸ)G–nƒ²6´qgÖã:‡Þ…Ù ³f/Ì^˜}>˜}ºëuwÅÅ…ÖÅU3ºZi$¶-+ÛZ÷Pâ(ßI„HJZTÜ kC“1„”¼—oõLÊÔvv¨kE’nµ™»³v”Jf²õiÚμ·e ;„ÍE `R³잟<.®*~WCŸqT'‚„!W $zëX% zÜÑYh}Ú=IL®–=Cj«:óEŠ0Á˜–µøºCU²ò1z¾ò”ÜOyÇÒSiû¬‡…oJa‰¦°»²Q™ÅI‡§P‰icŒ -DÈÿ$ykdœ&#xËét3ÒK}Â-ã‹ PìÞ}}Z@Zy@&hj\С{ΰ‡‹\Ö¦´4n!N'åvé½lZVÀ»5Ó¡éꦬòdªLÊFö’Å£ÒK ·Ö›£t¸W:”eOœ‹~I›Ñuš³×WÓ—“ËmÕ¾àÄ—–™»²¼„áDËͱg¡Kž¥ûš´â@³éN]– W^O÷¥YŽ^í×–kÙ2™óþ hÖ› ÁôÏEÂÂ0: ¼Î†7«±(±¹(yåì&¡¢qû9HMÀÂì…Ù ³f/Ì>Ì>]\ç‚ÿ4ï}K+Y«9•¯Hô”X<*¥]Ö˜LÆé`·ÊhXçôå:”¤†è¼E¯œ´¦kÍgvÉŽbR–º¬L m2P¨2§¥ûК­ŒpðN‡sW=ÀvG겇΂ܰ£_e¼Ò¤ ë”Ýפ$Y={þ¼¢ÿªH'a¬•r£<•Jµì1›éÖ¤]–YÆjç*†ÃV5æevÉ^£_‡Ó6OûPx.¢Í±CS«\•R>Õ62zª]–I"ýAË20#›·‰Ê`UÊäpsÓÑóZ¥Ó(kY˜UÄɼЬÃPA™œ Û`»ìóaUó^–ƒÃé®ïypÜrÁÜ QýgÝ7VÊ™u¨¾Î0BFw’YdÔÂêZD°oMv“R#(*Éái²4:cÖf]Bvm©S+’–=³”¶“µ¦q<‹yeÝ(`(Q´7y ¡ºÁHy‚¦õÚY*Ïϸ+C]"$ïRº*MR‚”ª™éÏ-‡þÑÜÔ Ž}× ³f/Ì^˜½0û|0û´e# —0¿Èjw“fj&‰@»¿§ZÓëDz£Õ³$Åtu/‡ÄK”9¤ÅþkHd:¾Êž »ùº:4ý~Iðˆ¢‘È0p…|†î¡DÁ‰*Š=©:6²*уTÄ‘<Á—½¯ W, &º…í6,w‡ ¼(H«“Ï\êL|zoYX£eÉõ]ÓYIeË/¶+®˜Žßº»½@Žòg–c)Ø­³aåºÜ’6~dˆò[HZ)˜Y(a•ùÚá ¥™ýdi{Ø(S7:¡})óóò(‰4JÌqðŽëí>MÆIZx´à…E>®Íwþ|;ÒFW³<ÆÖâõ>ÇS[:gy”)yÖºÆ@7×=æNp÷¹fh)é*|v¸ÅÆ¢;-2`W@^2HÁNÑ!5•'}h34{97ò UáCLƒ5ß+cQ­¤á:3PZ$9”‹S”Kãó ­dCý¾".ØÝŽÐó]y¦f­ÍErNn˜û¦nð…h?äFd´QP§^±_·™zÛ »WבEk“S ¹¥÷Ü*¹@íñùC56t ³f/Ì^˜½0û|0ûT,Ü®<N‘¥uš|UæUãU…ÙüŸ éø¦r¥ë§é2t6«a £Ûð ª,ú Ì~-ŽÁÓ\P¦Çý±±åâ5º…U²“aÕÙŒÕ%$£šH«%obqZýsW~Vƒ\cCÞÉ{ÄÆç6¤†c-,%|²ÿ©ŒBSØ=×Ræ§ÏÝ2¯ÊœyöFI' 2£g.2´döÚ‰uožü)§oÎ2´^9ºÛÈ(9ì£<(Ò“Ë®Lîæ/k ЋX) ÌÓ§Žr¬³\¬ÌD+W–f’6¹3IBfM̪͂m£,Æ"yOó#3‰a=ÉaÍ™3èI@Ý€K`ßý}µÌ!Xý˜‚l•!¡A´Ù­m˜ó3¹æpoi8$òïS ¡S–ô—¥žn:.H»¡•œ’´–¬Á°‰àö˜»ãJǦ®ÀV¬µW«þ›mlù´J6%È*v›XÑÂŒrXd÷lhfÃU°²µ"ƒÄ²ïhv¼—·9$Ó’dçÃh˜¿DV°JÏñ³"cëª„ÙØ°ãFuaöÂì…Ù ³fŸfŸ4œ½,z44,%û¶lœæe¸ ¢\(ßfy%Î&É Z:œ5y->fœ¬N¶]j3ì2EÇ»Œäã$ΣҲA:¬h'«\†œÐ¥p¤ô˜KúXŸ®ÓQ4o‰Šzß nMWŒRcŸˆ½ö¡íL•I*ãaFS™!Lp×ÁÔnzNÚ‰L6«QWlt b ÒB7uzFà —·ü=¿×Z„’¤H·íïèMrq–ËŠ€\û\ÃæT¤‚D³ä%CŸW†}ò¡ «²KY*=–¢„‘2HšÔh¢+bÃÕäÈW˜bQ*‚¤rP VN‹jB#£§Î–³ÿvÈSäH!'6Àö´K·¶¥t'¬lY­<]wž`S Jv†€ý¼Ò IDATüYt‹ÍV¿¨“ºNÜv˜Óz(lóÑälc8VæýuÂúÅ"gŸ ·sã~Dy.@ÞØ%Á^š®m+ìsí-m¿™¹âïgïÏÞÌrD”yK‹©]+ÇÔD©Vº·Â‰@ÖÙãl/H¼úÜ ]×j‚-Ì^˜½0{aöÂìóÁìÓí–ÎXãÑÊù•ªwèû>œL+Ê‘9ÀðšoÓÍTõ’/jmÂ* ²µ?KË1EÐK´\ Ø,NjÍPn@yY ­Áj¬ù!Ž.)³o {@Œ{Yxj«ÅIØIVäCѺ>f14û’âóŠŽÓb”#yE„]%Mf%§tŸŠ2¦V#U J+2Ÿ¡Bi]ÚK X!TµJ¦$D«-zÜ mm{œ:>gj¶¥÷,Ά=OžµpÅ™1ÃQ¯•ü\Dܧä qô¢†q»ß%éó¥`¤—ìe“±Ö “ãžå&ĬͺØvŠË<…¶-xêÓ¼$$ì­Z R_CnVô.Y—³ËtÓ‘¹‘ÒËM€±Q"ÝDJÚéÀ1§J—éú–Û„½úgÿ\ä«÷‘I`ióºäx€`Ë{–µž-°©GÒªál 7·©ƒsŠÄeè«n1Ó}ÐbõÅÞ6R÷ Ôa–’Ò_Z þpÉQ-ó¹Òç8š+bѦ´ãb’g;Ë’Ùªÿ–9ÁÂì…Ù ³f/Ì>Ì>©”9o‘rrsÜ•îA™.Z}*¬£HÈ4¥õ¦ 2M—0‚‘r*ÉX •)ü:õ_Ñ$TP[ýÖ¥ ¦üQ˜hô!Vá)ôÉðbZ¼ŠÃ_eNÅP–Š÷ßëñh;B4CºzÒ0$Œöáê‡ 6ü°d¢¤»êÚÉѽÄ&%pÞ,»R®ËòGšRèÑ=mº&ŒbÈsV¸.ùÌå5Š24]q°|ŒÚdF[8¤~,†¾|dm„Q‹Ä`ÉçP¤ ‚‡$¼pèÃJ[T§ s.€–€/<’Ä’|D³mh6»—Lå Y¥Š:21"žUôÅ'‹Xl9°A„á´©H¥ms¶»í°Ý±28XœˆÑÃ*iðÁ¶L¦ìãóÄÂ6݇2@÷ðÅbȦᬥ)$<zlʶÝa<Åü+¨l¨X•Xy íŒaEé -¡vÐõ-cÛí½}8fb‡ï™U¯¬ús^Íñ"îxí23GCRoºìÅÍ‹ê•}aöÂì…Ù ³fŸ fŸòô@ö…h¶ŒŒÁÔm ³æaLÁP¥Ýƪ#à;ÍÊÌxÑϪ·ÇO;IlÙe °-K½ÊÀ:•f‰§{¹#OÖLâMqÅÛTÀûýÏ“rñ—дñ”äÒYŒ’XÙëÐYVÒ*„I N «ÑqúK&Îèë’4²ÕȼäïÇÂúª6/šReà]úóÕr Z,¦ÔéM4lÇ£èT´(gJñþ£ìÊZHr!0Z¸Èµ\Zý“xÁƒ.§‹ÂµR)Ï6סÀ¦‘ ê.8Œ>·”ÚU±ê‡›}Š*‚³gÍ ¦WNü1Ñ5hHf¸4ïf<¥‰‰aÒ{ØHé]™÷+3KÝ¡TìºÊƃ}ö,oË ¸mEâš½¶Ñ×jéma#ÏÆa“;7fay[É0=´‹ íÓ´'?HÐ])µwïBç«Â5O†Ã±J^d[ðØaètEè±$YŠî…Æddžèê RN–D™Ž$8s#¸0{aöÂì…Ù ³Ï³ONÈÐê£É’J§Ñà&AÕ¤%`êt?Î,óÜ>Ä ¢dÙªñ öÆ– j—6™n=9a•tóùîxÒÏ÷ã`O±( ËfŽçÁê5¤›Œ£4:ltÆmVÀ!AÖJ<uͶ²ÌH=åZ¢gNÈ1Юtj|N÷ª£m[1׋äÞÒFÅè¥Ó!1d¾ð¤­Œ½*/CS—‡Ø)n{$ˆé0.z¶ “Úâtùèt{e i®![žbm—³œâ‰vfl–sÇ-Cé’Nm2;d7e¹Ð ›ãš½:P‰™:9þK/|u÷Yei²ó_2$˜„@ÎŒgçyrÞgfÇF_nNk‘#þ” Æa3{´\™Ä)­Ä?«L^÷ÞÖ;,Ì^˜½0{aöÂì³ÀìS!RÀÛJŸM"Æ·””‡jà‡‘&'$C7N ÛK‹ËR:Û½ìSÁÃI‹FɪŒ&6´4EFé§À3€¿úˆ¤ÊVR0mó«QzH±Srkf?ÛR´¤–#oz.`VÒKÝ Ô/ÃCY¢²Ò`•®g¢røÝ:K¥ÒûÚ<ÕæbYrKŠ6d´Rÿ4uÀXÖ»zŸÛ§wV”D¥³-³“ýYI¼˜=…ʶUу>e–ë2«%ƒ0ÑÎ]s¡Ô#ǧmœÑÚR°kÃ2,¿¦éE‚*U*£8HPaÏòwudGÖኅs-C–Â:1O{Yå=«…>Êå2ņٛ)QðsyWØå`]³š ús‘ÐJoõ"ÈÉû–¼ 4©M˜Ü¡>¸êÑ[ØnbÙ6€¡ ‹‘ÉÙƒldŽdx¬+665$/k"P²às¡« hÉVÕ¢ÍãÖEp(7çœÜ{›¸îé‹§­H|icºÀ±˜ï‰sb%q·0{aöÂì…Ù ³Ï³OÍ^1œ–p¤¾j3½Á%O¯ÒeŸ:EŸYµå*Àf‰V@zŠmé@”\à´%d!®¡šòLK2?£XcU¬_Ù”Ÿáÿ¬lÚ(Sè`¤¦¬Ž0ØÝq_tc¨£ÜÇvÚ³´%S"©™Å2ØúUºd:éèm‹¬B’\dH(U©¡—©C’ÉÊIGÉf…Ce/„Ü3³E;P_òi•iBÙk-ìÊñÒO”;,ú–0ì‡YGI¹ù ªÚZ¼eÚÀbG7›>H 9‡N§Hf{qv²t–Atc壙êíjBþ º”—OÂ×?-`Ìׇ±úDK“ ¤=5ÈE<ꤻÇ&E‡¡ˆI+¢ÃþÙ•#¸ DO}ö»í0º!‚:zÌ^EMâ›N9¹Vækк#SË´ì•¥ÞÃ`eo}Ï"¹*d+¼¶S]gÕhÝWÛªR‘Í“~þ5õÊ~œÝ6@)­à]šÈ#Pïk®,$CÂN`bCžŽa€€á.èÏEcÃ[Îfƒi?Ë•‡ÌY,V¦Œ¾e)Õ€…Ù ³f/Ì^˜}˜}‚$0[ `íæðA²1i&õga˜(S/R«pi[L`“oM]P–ÌJËêgIЪq>'Rè ¹â%hêåŒê—‰ÉÑ«˜Î`{_ÚñÎAVišêC’êC2Ù›IdS¤´þ>u'ËÞ>¡Ð"ûÈ{ `³pç (NÓæƒ"AÕüÒ,!Ze4~ÐjÑi ×ÊY. Öç­ÔZeŸÒ8Ê~dk›’ÇVÂÓ±ŒÓn-Ë,‚äR§?F6ËMӺʤX%µ$¬çÄ3[•§c\iÊ=Yif:i*Æ œY_Ù0X¼†µ†hš{ÃÒ¨C1 rÏ( Z¢ s…\tË9jØËfŸÙ¦mÊ1ûÕP&>­Nùû²CHœ¬±ê¶ÓÙ:Ðk'ÁÍÉ7º lßqI‹S¾Ösˬ`ª6´BDg %63‡’)§Ý÷žT¸Cv2Ü[½*ØÝ’­SjË@³±1ôM™ ­YIMåén¤½TtpÙ-kkîÒhÙY„[ÍA`kOÐ"Û¢>'Ô’Ü'Ž\Z©J´\oÔR··[5&˜§8^öZ¶î¾0{aöÂì…Ù ³Ï³O2¼"8¸Wa*1 ëYŸtÚÒ8‰ "£Efœ²²)|è¹ð jÞ²)%8õ¤\j2þgX(EO“ {rŠ•Àh ÿ&µŒ³4ýðÑ»4®™©%je×;ÏÇé$d¡*åÊ4&¬þú{­»m¾Œ8d¦ÈyG»W Õšq[þ‘ ÉÞ¿A@¨þMi‚Pò€A¢ 2­2:Ætp*óßʈ$ÀǞ6éÉíÏ!2ÔØ½DÊжõûgÇÒvL› EôsI”¯¼ì'¡ÚÒYù¹’Øc9дG†¬QYFC«¦–}¥Ù¯™ÏaÔ¤v/Þ$’äóÉB1å"µ˜›#b/hÒvËŠ¹¶UZ^éåèEœìöîC$›þ"£üot@7gºÛ^e;{ÏÜ 5œk’Û˜›,´ä×”s+ÒXÊ<ô Wö1ó ²c§E–IZ;—Ç`l¢B¥ad«ô²õì-œY¶ØX¹n.z›ÂTA°p’k‚Vi+EH33 šz胖bøsuú–ÙÁô¯»f/Ì^˜½0{aö¹`ö)?•QÚb7&¶åi¥òr`—êŸâ$L`’éØã¡«K3q¯A`Q3t§Õ©iV¾ÀvÑâKkM„ Â¤OQu^Dg‰ñ¦ù96î 儳c¿ý £¬‚2 4·*ŒÞ£v  ÌBëÑÂæUòžñÐ{/£,c¸Äf£ 柡Îvä6È ƒtuù£’vÊ2YVÌyjãP$h °Ÿ²AÔh£1”ã[²Â³œcPnP»î©¢ÚBüìÍEgÜ|Q¤*GÃ.Ì/Œù99£f™–z;,9ZeÁ”L¢´›’¦¼¥‹T‘‘RÈå›RQÀÆØÉL† #S×(ÕÕ6¬cÅ¥Àˆ‘íš<þñ Å‚PÕà)œ‹°KË)‰lØ÷0só SŒ ®xÌoÐj±:fä€ µX 77NBQqºè=a‘Åê“°ÖXrRkhZwœ8ˆAf#»&Ñ/—Ÿ¥Ùù.ú0GŸ²LÐÞè`YZ¥Ô˜ò^ÍÙ?Ø}VK†]ˆ åo¸”îÛrR…°×é\Ë«AÀ½ËÈ©ê°I‚‚Ï93õnWóÒW‘Í„¡i \jf´L2j!ˆ’jåа—þ)5ÈKæl2!tóÿßé ¥VÎCø°GY`Ûji ,uér*C?¶²=Œ‚`¥´³˜ý«]b´!{ÆôC•í·Ò¦ ­[bh1wo2¸k˜8Kï£ÜhåHŒ[éçZhÎ*´0Á’8WïrEˆ‰OUå{éžÃc>]´‡YCæöÒ>-Ì^˜½0{aöÂìóÁì´·Ì^´<‰T2Ú“`QÌt)uK—I€cOYe/¤´Š„ÛÖ1~r|î¥[iŰMëÝL h”ЬNÞ(v?y±ú³RvÉâÔöí,E „à2Ùß24GV}pPPö*ŠYœŠY'A w©¬‘ÁlÔ›ñs‘ȳšÅÃÞr°VÏ`Z£(y˜>8òVã°J•¡ ™½]ܱÅ98Ëʬ¿uO–M›æü¡ý¤ÑWƒ>S¹`¯‰ªeûj nG[ÔHP=둎Q]]ŽìS’PâYú‰ ˜…SšÕ8Ì’µ‰Á=aÖYáe|þÌ™gò†¬Od¶äYåi’Ì‘ ”ÖBXbU¤Ùƒ`æå/[W9ØöúÇ0JÔƒ³”ÞJ»YKDEÏ-(‘¡,¿Ö`Ä46, âÏ%oo…ƒ"劌\”ÎuJ€!²n%_åeh+Y¸Ìž…cZ¦Ð*‚z½Ë´nrPb™ ƒ„®}|¯t—;ó—%ù=›-‹7½ÍªÁŸµ;È &[¡ÛV¬z9jÀ‘m ^&lE tÖ# —no2²§:æmÛ¤ ³f/Ì^˜½0û|0û”&ð“Í`{—ðz¦ô'(•(S"FÚ2öJSJÖøÄ÷›!ÆfqZOd‰þ¥Ëým¸íòíØívìvÌ‹­vNß°ÔieKúW§$^˜mtÝŒ_y íþ¬¯ƒ&)ÙSÁQ5>Dûk@¢D“æ+–Úüô×cÿáô½BŠIƒms¶`ìñ³L[ÌÕ3;C»tŠÙË(h±ÇWlç=8˜'\ñQšý“Ã/ »*ó³òvèF“FDiR‰ÖÂʃ4“XÈ]þ=dV†ä•Œ?5燡…U‹R`å¹ôÆ ó9LòØ¡ ßÍ«]ö-ýV) àcÇa÷$¶†0‚5 Åi{¼×“Mnég2éÝǼVmY°‘¡“ÈTÒö¢Ì!­± È5 PANVíÒ),ìµqÅäašŽdÖ´ÍM®xô¶þéĤ±ñÄAúª{$•Š“\‡M¯ÃuÛ 8éõ±aóLf %ˉ¹ù»Â¢÷¶Zž»SŠ µ`‹¤»ÝÑNYR bȘ-Ì^˜½0{aöÂìk³OÔ+‚îÃbSü…`›Sœ%XÎQ7àHÅûk•iia‚^¥“…®ÛíV¼óòð¹_üd|ü_ý0Üõ†‹;šC­X±bÅá €w¼ívüôÞŒïù¶çãúÓ½qÒëÛ"Cä¥ç ó~²JŒeáRvÇÖ¬a&’—«æ8Ê‘qt!R¹0{ÅŠ+γå“õî¥A˜ÌPF-Š) J»½'L§µ,KdžÔê’H§EŸA¸ƒ0ÜzùV¼íößÃüßÿ3®¿ábš+V\qëÛnÇSžüÜpqÜEï¨wÅŠl¡/ÙXmBŽè%öö ‰~ãÌ›–8ì°ñJ #áQÿV€‹mÇÂì+V¬8Ì–O~äsbû­„›Ù«QÖñR¢÷ÝìÁlß"²'ÕCwp0Cl–YBPÞh!;u‰ÛíxË;߈zá³°é$+V¬¸¶b7à¿yÂ×àÆ»<§ízœpò܆Ä%L6öVlÐî)- ºèëÔìÓ•)«vȪ¢p–x³«óT½ ³W¬X±âZÇlùÔ‡?'eÌËÖ³È,\š—Õ{õvQ([4%í8Újj:2Å[¥Öçžr<Üãp‰—øãÛÞˆïý‰€ëï¶²"+V¬¸F³$o¿Äç|Âó¸qýµNÄ¡l.=U®…ý}¡˜‘®gl¦8¥šÌ{§³§4³Ñp»`ïË݃¯P. Qf¯X±bŵŽÙš-~Õzæj.IdÃJÌOiQiáÞ¤ ÔÚÎ’¡]äBñ©¯©N³T ·ïoÃçñ'.À^±bÅ5×ßí„§~É_Ámû[q;oƒñvÏðJ“Þ<ó±!eÊDÝíÎÊîÇüs”(ËbÕ‚øbªg”&¬`aöŠ+Vœf«A`¢-¥‚–Ê@Òµ%¬MSƇê%HŠ 6í`£¶V舰=$‡vì n»|;>þ¯~Ø+V¬¸æãÉŸòÜvùV—p=+Ëbïk¾¢ÆÀa»=´¥-•4J/úæ,¢bdW²Ÿš¡e¼0{ÅŠ+γOÙŽR%,í̶¥œnQëÌþ”Ð=ÔpJÁ| iã0UH1w(3Ãmv+îzÃ2/+V¬Xq Æ]o¸Àn·¶ƒêrNšvÕe×­eßz¶Z¢\RšÑ2$ëÚ:™Ûo@`¥Gra ³W¬X±â<0û$a;©åú}{% î»r-­A–Eª8…» ”'Û‰ŠsÇÏÌÀ¸”Ð`vÛÜ+V¬¸VƒØíöƒ„Ó.5…h:îe¶Ã5pEYD®hé¦A‹”†l¾×­– —…Ù+V¬XqícöI²eôãÕ›ÂõÈmDÃiÒwøùÆi MäÝóGˆ6ÐÀn>îäìuífÅŠ+®ý°Ð˜6ÊHºœºYSI³iàµx2²Ò2\Ѥ˔éD˜¦ …“Tf¯X±bŹ`ö‰ÜÂ×­ (Z&O +fñ}©¿òUëÑöŒw+W/C†ï—h û¥+V¬¸Öó#Ž\ˆì²F_´¥Tž û`ñÒ!˜™¬é`®á$C‘Àb üÍw”AJ”…Ù+V¬Xq&˜}Â(j¾`©ÿáhÛÙ÷Cé° KËÖ/ÜEÀÓ–ÕàèN¬ñ»ù×î+Vœãè´ð IDAT h3\ÄÚr:…Ò-ŒÑ -i‹`Ì0…‘Ê}„¬ÔŽ*¨–lñà`¿×,Ì^±bÅŠ3ÀìÅÒ”>„ºS’d‚z$ÛE FìÕë"åõž:îûî¿itÇ1ˆ¼„˜¸„ay £¹>ëÂì+VœI˜í í †‹\Bå1s=j.Õ¢¯ïhÕ›ÛâRàËýo¼¡ôžé=²Ï ç¢â&ŽÂ…Ù+V¬Xq&˜}JI'Ícôý ÝÕÝ 4ÞÜÚG4Þño{”/Y)ô¼( Öæž6–ô /9•×\üý¯x&^ýš×T÷¹×½ð˜ý`|ög~îuÏ÷}¯þ¼"‚{ßë^xðˆOø¸Å“žðÑk@¬èìˆ0ö¥¬I–ÙMÐŽÉd‡†=z+…¤Æª›ÍT©¢¦€´¦ä„ˆdædaöŠ…Ù ³WœfŸ$¼Ù][ÐÓÝu#%ߘ#·ëš4K îèoA˜H¥Ð#á,›divÞe%G®åøÈ,à•¯zžÿ~¿ù[¯Â·|óqÝÅ{§YÅÇ|ôMPÜò¦7á×^ñ ¼ìå/ÇÏýâ/á+þ§¿·à ‚`8Š™¼Oƒ³!J®”›Y–cš¸ÑLì¶Q‡Kò™´onv%dúf¯X˜½0{ŵÙ'ßá‡_»‚=p™Ñ:n舌†VùQAßåSýwG3ùe@òF7O0æ##/²`û<¾ä‹¾÷¸ñF¼ýíoÇ?xæ³ñú[nÁ/ýÊ‹ñÄÇßô^ùy¿ø ?w»ÛÝ¿õªWáë¿ùÛð‹¿ü+øé¾OþØ'­aqFñiŸõT|ð=_ù?~ îq{þä­oÅ7þ/ÿ+^þŠßÄ¿ÿþïùs½®áEØýÐ&žùp#˜­6§&ÃH†N^¤0,Ò7ÏköPk|nÕB(ÇFä{aöŠ…Ù ³f_ó˜}SŠ$ Ô\â)“ÞÀœ2(Âüžÿ©¬²}Æb{’Á’?Bsõ¼,À>›¸ÛÝü¤'à{ÿõáõ·¼Ñ‡Šþíü^øóÿ¿÷æ7ã!~0>ëÓÿ:÷ØÇÔïý­Ïû;øÄ¿òñxË[Þ‚_yñKqÃ7àÓ>ù¿Æ'>ùãêgÞÕë|éÓŸ…WýöïàëŸõt|È=ðOÿù¿ÀÿäOã«¿òËñAz¾÷~¿ô+/ÁÛn};>äQÂ|îgãþ÷½o]ÃnúHÜ÷Þ÷ÆO½à…¸ÿýï‹ç<ëéïò3?âaÃSŸò™øÖïø'ø©çÿLö;ÞùÎwù~ÿ¨À]ïrWüâ/¿ªŠOú¯žŒúˆÇÿñ=ß‹W¾êոϽûùŸƒý GÝé{¹âÝ‹‡>äÁøß|%žùuÏųŸþ4ˆžõu߈W¿æµxȃôŸõ½ žID›²ª­•Æ´9÷ì1ü…#÷ÿ›öêss±0{ÅÂì…Ù ³Ï³s_Ú€Nžñ•L“´’Õ¡§ ÙlÎØñ“ê–¿~Šh`G]Žæúºæ¾fÒ ¾./wð~?ÿô»¿ÿêÿ-¶mÃcóhüö«ÏþÆçá¿ñÊÃëüÈý~ëU¯Æ£ÿâ‡àÍoþüãöÝxÑ/¿¤~æ]½ÎÇ>Þûí^zóËëw^òÒ_Ã=îq<æC?ßô­ÿ~ü'ŸG=òáø¨,^ò²›ñõßô­°Ýê~ægÿæßÿ(n¸ánxÿ‡>ôN}^¸éq^†}Ý-·Ô¿Ý™÷{Á ¿zóËñ?øG„ùÿÿiÏÀm·ßŽ{ßó}ñÚ×½ßü¾·Ývû¿—ëëÝúúê¯ø2<ð÷Ãk^ûz<ókŸ‹g~ísñê×¼÷»Ï}ðU_ñ¥ïùÜH÷ÅÂ2ÿï/•ìÞ «_ςԆ¥ƒ]¯%NFd|!z…£Œ¹0{}-Ì^˜½0û,0ûÔ$éÓÎ2˜L¸Ue4­Ä¸¦#è·lJ¶~§u¥çÓ%ÚÅ÷djÆìÈ~À×v˜^ýš×á§^ð38Nxô0~ÿÍ€Ÿüéà¡y0ž÷uÿÛ¶á§^ððíßù]øw?öã•Å€{¾ïûà[ŸóllÛ†ŸûÅ᛿í;ð?õ|Üô~§^牿 ßý}ÿ¿zóËñ”Ïø¸åMo›~÷wñIŸðd¼æõ¯Ç‹_z3÷Ø×þ_xçm·á^ô˸åMoªS°ªâë¿êéxäÃ?ðÝúì×_=®¿þzÜzë;°ï;^û†7Ü©÷»á†»á;ž÷ PU|ßý0~ð‡OþØ'á¿ÿÂÏóòî—%^÷†[ð†[Þˆ»ßxã¾—+î|Üû^÷Â×>ã+ñŒ¯}^óº×î{Ÿ{ãkžñ4Üï>÷ùó¬£"³ÀÂâ¼ó"– £:ˆËç%8Kõ ÌÃ.}—½,}5_6°taöŠ…Ù ³fŸfŸ b£ñÛ$¥M\þID Ö”ÚÕÇõf®Ä?ˆw ;y)ò P‘(]Zyñtj~ŵŸów¾¸+˪øüÏy ð€ûáÅ/½f†Ç>æÑÐÍm-žøø›ðíßù]xÝÞpx¦§‹ú™zÜc!"xÃß‚ø×½î]¾Î½îuO|È£‰ßxåoáOÞöV¼ø¥7žô17áõo¸ðâ_}>í)O=\û[ÞúÖºŽë¯¿xø¼Ë±FÇãm·Ý†w¼ãxÀýï ÝôN¿ŸêQÿ|˜/²I}ÿ{^÷†[ð'o} Þü‡x§ïåŠw/¶í„ë.®;ŒÅ‹‹‹÷üž;”é~½}ÀîŸ•Ö j´m0M…tœ!ÂJ I?TL^˜½baöÂì…Ù×>fŸ|Ÿ¢ÝÝœ"åæ?Û^ðè%Â<…âo5úáFÖÅ(Yo¿Æ®ý¸é#‡îv7<à÷ÃGäGà¡~ àïx'`·½~öï¼ "‚»Þå.ÿÉ×{Ç;ý÷r"ÝÙ×yÒ>¿þ›ÿ~íå¿—¼ìfÜ÷>÷Æ£ñ¼ã¯<ÏûoÿÖá½Þ“pÆÍ¿þ Äû?ôý7Þxã»ý~ªú§€IÿÛŸ÷^®ø³ãÿèñU_÷\¼þ ·TÖêõ·Ü‚g}Ý7âkžñ4Üó}ßçÏŸ1‰¢#¡ ¼ÌžèÀJ±c(Ù¤I‚"%6Êe÷2b- ü+ä\˜½baöÂì…ÙçÙ*Wûñ(Ñß.9R¿•òOgÈL•£zûàVgCKJåñ¼Â]_½I×l¿ßáçáKþî߯güµOÁCôÀú~‚÷¯¼äeÕ³ö’—¾ $ñÞ׹õÖ[ñö·½ ð²›=@ðÁïÖë<ᦄªâ—~ùÅøõWü&žøÑ7A x¿?ªŠW¾òÿÅ=n¼;ü€Ö×ÅéâÏìå{Wý~o|ãïâ»þÅ÷CUñ7ÿÆ_ˆ?ßûáÏø·wç^®¯wëëÙßø-Ø_óŒ§ákžñ4<äAÂëo¹Ï~îóރ׎ìñÔ—%DÁÔdÕèÑ“‰™’H9äúÒŒù6Ñ3-¡›ƒFfƒÈÂìõµ0{aöÂìk³O>p¬Rå’»råȸKi¦þªSÙãM%3'ž^wcËàÀçÒŽs‚‹»~Îñ~yû˜GãWoþ5|ÙÓ¿ øþ/zñKpqqÏøëŸz,ϽímøÒg|5õ°‡á—~õ¥|Ú'Ò»õ:w¿ñFü¥GÿEüì/¾fV†÷ºç=ñ‰ÿqø‰çÿ4¾âY_‹¿üÄ'à÷ßüxÛ­·â˾ä‹ÞíÏõO¾û_bÛ6üîïý>~ëU¿ËËK<õ)Ÿ‰x¿‡þy¿w÷^®¸óñêßy >àýßÏ|Ú—âžï㙯yÆÓðìç>¯~Ík߃ ¤4™FÏ)­jn„X€¶l°Póðý톶É 3ʳ•0ºż_0k²0{ÅÂì…Ù ³Ï³OÈO» £É[+%î~ñ™éHÎ7m½U¡§Ë æo+~"èï‡'ò± ŸþiŸ€Ý¿ûž½ßŸž.¹³÷`Å÷¯þùîû=ßçø–¯ÿ‡ï!î¤Pž•a3£± ߻ↂÿ8Ãxƽ֮¢Øk3¬7A¯åbaöŠ…Ù ³fŸf˧<⇻{ Áns ¶æa&C]°GµÇOyGhŸ2øå»Ä.a¸—¼—¼ —v‰?~ÇkñþÜ7¬ö^OùÛÿîqãÝñ¿ÿ£oZ7cÅ{E|ê㟆÷¹ëC±m×a“»@qÂ&'/°éÉ „ÊË“ìPˆ27G=ˆ L Õ™Qm ÙWÝ–3—êdÅ“úb±0{ÅÂì+γ§¥¯=}Þ­ûôÂE 4h:ë(aô¢£«¢ÝÇ@¨é  ÜTFeüV¬Xq^‘ÚÓWæØd‹?g;‡op­²ÂÖõÅT ‘(3R +‰ÈnB#L•¨`¼>/Ì^±bÅŠóÀìS›êòèúÅãÛ¨ ³!)/%Õ¼WZ«ùoð“Ç—¶–JI„/ÜþÿA¬g¼â½ ¶ P!cp“öQŽª !Çhx îFs„ÖÔÕb† V‚Q ³W,Ì^±â|0ûDtïÞ–n7%Õ.9…ã:t·ã% ­Žéñ–ñÁ†eeåÚ)5£j¯XqΠ]Xérx"R„™¹ÏuÜÓ"¦–”ÿ·²æjQfp㦔+KEdaöŠ…Ù+VœfŸœa®Ñ[ûoS„t³¾] *ê v@ †=œvÂÕ]$ô ­¬v%.³-ǜ̊÷Îø¾ö×MXñÞµý(ÐudÓ$ÖÊ®70¶ÜÆ4œLqˆ¸H¨|H˜ÇÀZÛ5Ò²?Pƒˆ³0{ÅÂì+γOþ³„b MÀîÕÃìÈ‹bØMJ4˼à>„'¼êïŽeª—dÔŠ+Î, ôýjj¯ e$ì{ÑVþðˆ÷K›0@Û^á‘)û_S_ ŒEc\˜½bÅŠg‚Ù§Üŧú“AâB˜/cƒ¯‘í´ØïK8‘Qý"£Ï%0„›,C [É|_¨½bÅŠóÉ8*«ZCE-poë~À@;u€ôÍ+Ûöyë m§2¤ªt©A²Y˜½bÅŠ×>fŸ¢Ú¡ ¨ …Õ¶¨d¤Û£w…âFþž[¼õî’S€ v‡q¯÷¬t&ÆòZgÅŠ+β{£«áf Ê@oR¡Ùà>E>”ØÝ¦ýoÂ!‹P“Ùçt$CüÞÂì+V¬8ÌV&¹&Ú¼5„¹ýýX™ŒìZÑðz/K_qf¦†Dw6–“yñÝ€쩱0½¤¢V¬Xqny ˆÉÁ aª}ˆXgO'ì«FsC, ¸)R¦:® ³W¬X±â|0ûdÒ=yf޼ݩsÆ^ÝŽê“BP¼)tVÁ@äé½-åùžWdˆþU©ª+V¬8Ènþ'1v¨l±á¬³2¤ô¬~K³ÇOf"ĵY-² eç+€’¡ÂçRQJ²Ád_˜½bÅŠg‚Ù'°œD;SáÕD ºyê§æÿ†Bþ'âV¦¹»—=‰w7Æ(IJÐyb§?„UV¬X±âÚ,1V–£á\"KÌЦ>ôì1©òQhÊÞÀ2¡|li£ YD›…Ù+V¬Xq6˜}Š<º$è}&Št!CÙK’mV°Ù(N†ç;ýÁ€wùê+$Ì™›´þˆD»ï¬X±bÅ™àvõ.œ:C=7d÷¤,ÎS*ûýÂìÀŠÑðrG¯ÅÁK’æ ÓÑó·0{ÅŠ+γOiNls) ÞÈ`H |ûÏ8Ànl«0²›¿…(g1IÇÿÛ‘’bd®~¿+VœdwBDaTQT¶#ÑÍ'ñÓ0&»¡ÇÀ«z2r) ³W¬X±â|0û”e@BBWQ›ÈdT¹²²%yJ¨ì†+3¾Ñä™ ßˆ‚z…™žâ ¯}õ+V¬8 ÜCV¯ …‰©NE´øW¥Tk†b´l KŒ Egij”EÈ\ ³W¬X±â|0ûD¨gBðD¢9<¯D`‰H£‡A‚¹p”30]Œ04Zc÷_J!f‰=ÁS–*~â¦'=y „+VœInä;ƒÓù Õ`¨32¿a€¬v -V–éAf’­^µeùbC= ˆÑïçö ³W¬X±âl0[ÜôÝ!Ø’1é={Œ¯ôl‰¦|‰¤¡Œž=ÿyEá¾7›‹ r†\Ôb°¯X±â|Â@ìô/¼§,2 P›ôÖÕû­I‡…‰·”¹(0ÈŠ¹i±½†Î…Ù+V¬Xq&˜}"¨BhØ¢3Ï#ÓÂä@AlaI9õT Š) I\œ2'L»š÷ š€tç¶ÚýV¬XqN±mÀ¶½¹O‰ 3±AË¡ÑÛ1Q`qBM §Æؘ¤6«„aB‡Tß Å{-Ì^±bÅŠsÁì0É¢bºß”¡¤Ÿ‚<#%qÂäF²ÑÛê Øìµ„ø Ѻ…X´š+VœWˆt;¹.«h½°[,Hl™Í:˽œA:D8ŒuF…Õ¶FçQED™faöŠ+VœfŸŠNìt•l÷4;@P5˜í)ÜMì€4@=˜ÉËIùUKÂzÚZÊ1ý¾bÅŠ×zTîBªD6Ø.Poé`Ž©*0 ÷ÄTc<<)‹ßlÑcФH; f¯X±bÅ™`öI!€14-”¡bG¯©ŸêûuO³k¥5$¾ãâ¬Ê“%˜â¤ø9S`O»ß5V¬XqFQmA’QÝ Û 4 “b2¤ºHè¬Rb“–çÉ|·î èTñ?‹° ›,Ì^±bÅŠsÁìS«`…Ñ¢œˆ"È4Xí„¥Meôº$3³*™!C_{gKêC$ì)WrdÅŠgbÞ¬'l÷0Ù [lU xçNœÂÆ=VµÉ¶øTC'8*aië‹”ÄŽÌ ¬2* ³W¬X±â<0û”ÂNY'Ü$à˜žc}zÙwIxJ„ÏÎðw9“È’DjéxïËRaÅŠ+Î&LëRÂI…îFl Ýî†K»JÅ…Ø%YÇïGfy$¦]ÛZƒÅ^ýÔ[lŠ·…Ù+V¬Xq&˜}ªŒ…D_{Ïî‘à£G ³Á; ,X’rˆ°±Dé¹r0i’Ýi‘{Y±bÅŠ³IŽ@@S`ó¦ p"AÙ!r Tf^v s„$ØŒ€µëXè4ŠdÁ§ë£aaöŠ+Vœfk´‹— é’Ö`—HŽ{üÐßùâÞ¿’N½<°ÕA 2N³4W¬X±â¬@Û:CO«¹bÅŠsÊŽ Ý ‚£Ø‚<#" ›ºÑ¥#ÂÚW= ”'€öýv`¿Ä&[à"1dš¤³.(3B¼ÌYßY±bÅŠó §DOWg_mA»-k– ˆhÿ]* \Âv‹ÖÆN-Ët×Ì.êÍÂì+V¬8Ì>1dJ(l†e]û<À£‚`ÙW¦< L 1éã蜅ÀApÅŠ+Î(=2ÿbÞ-.‘—8§a,ø<~W]—:Ë“§ P fÛ­6À"±c;GÚ§/Ì^±bÅŠóÀìÌ›¶÷ÕÍM|™®`ÉÇN¿ÁÛ´`¦;k3{^}*ÈÌJxÆëp$³å3¶bÅŠsÃl!,,{! H80ŠÁ Þç'CVO|ƒkæb­J£Kð 'ˆºíà~‰Ýv6lþ]{ °`aöŠ+Vœfk&5¶Ò`=šðÆh½néR)–ÒP^¼¤H ʲS*91ŒTý‚ì+Vœa¤§y˜Ä\ýÊ’äÐÉ+»tÉls€>iäÙ6œNØN'ì.A\ÂÚ6ˆ^˜½bÅŠ×>fŸ’0S¹3ß}ëñ 2Ó!ÔàÐ$§¦+`)ÖßQJáôÝ„R ¾ŒV¬Xq~!™áÐhÌ(Ü“ ¢$£,ˆ…\‚ØEJ·ÚàÀ½K³úÿcïË㬨®­×>U=Ó# “¢Ì*QóŒC&ãlœÄшúéËËh0‘ÄLÆç3ú¢‰‡(*1‰C4j≳qÈ‹‚‚Ìc3v7tß:ûûãìsª.4Ð@÷6{ùkµo×­ª[÷öê]ëì½–‰PRX¶HˆšìhY9[¡P(Ї³cߺíRÅ2xÙàÙÊœ¶ÿy„ØgYy.!kwâHÚ†>Af#1 I¾h¢P(Å&· éÍï(éBäü:˜3-~8™©t‚<û"vñéD°–A–ÁÖB9[¡P(Ї³c×»Â0l§šeÆÏÝô%Iÿ^Jº’ˆN–Ãì&g,½ƒ]J‡g¤]„ …BQ,\mÝD¹›ž娑sf]Ôø’ZW³LàH Yü;¡T!!ã67 ›k“Þjål…B¡(ÎŽ QH ËRhZÙûÑL×'îÔ–åH7ËîÎ2‚Yg7Åp±ÀòrÜ]„%‚e“É‹W(Šâ1Üdºq6P.ú€AœOjC°ÆYñQê↠á[Ÿ˜.ƒ†ð|ëüúB<0³LÕ”‚ÚÖ(g+ E‘pvˆ`'Øàûçµ/°ÛÐÒÍ® QP9¼‡ ë`±`CnºÓÅ!‘çmÄñY ®¿\Õ…BQdÄ y Þ”¤¡pÎ iá~ä]V¥5ƒácoÏGVbÖÙ•„}‚£ñÏUÎV(Šbàìògé$ábƒ"v‚°”9(G²ÌhexFdyOÀÖ –iK˧Áç¹xJ?P(ōޏÞhb†‘åGFÀ¸vóXåtÐ;Yù¬E)f kae9Ódi_ï’_ú$L£œ­P(EÃÙ&$ÛøÞ;ršY—'Ã)¹ú ÞøŽ>JýW-9É=!FB~`Ç»ªPÕ]De8m…B¡(¤±/néH@dƒ’A~Ü\z©Ý¿-ë aß/â{MÚHbÙ'IŒ$Ñê>EšQÎV(Šâà옼–&hR%„}ÿ·œƒŸf÷'ÆXb±;q'ÉÿK q¶& ßÖ—º½†ï´ßO¡PŸF’–œ,­œµÔóžÔœ®#§®ÀGœ‹P"Ų… SpO´²-¹V0À£œ­P(ÅÀÙqX d#AÄ–\<¥Ÿªôá™…D˜Œ¹IÐM$–aÈŠj"}€H_Xú‚4eL¡P¡BB KÆq¹¥Æ„œžñk-Œ¡àêá d¶^öðM| "¯ª€`É"!7€“øMYTeNK_ål…B¡(|ÎŽƒZARƧZ°Ü}¡/ÞOÖë"¥“qº Ù: b+„mÃͧRJž£P(E#Œ„–@6QìɈ¯ªUre+˜óÊßT9qpˆ> {J§Ý¥?[9[¡P(Ї³cßyç¤m—þåƬoúKÆ8ÄT:Õ„B‚ŽËÒ$‡P¤ùñL²oƒ[0»Ä2G E1Á—¢Æ-Š×*KÿRj"9^ „,¡nÐЈr"ó윺TG2´ã†ÃE“VÎV(ŠbáìØ÷™x’¦Ðgb2}(ÙåF!bJd9ѽ ÎTø”<83´Ã™€Ã¬Ñ …¢Øz—·¹?+“ê²äHž­pœYk`‘`3b‹+pÄ6oØÑH¤#³MÔ•³ …¢(8ÛŒ•hB:Yn),K/‘{ùœ,€D:ÿ´DéNXíYž—Ù9nW(Š"§SGØéW òL\/`3K’,Sî®ÑÚ™¡™4ôW¤•0ðè¶Ë¸ˆ(g+ EÑpvÌd$)‡ƒ×`8-C)‡²aÑR|Å_ÐÙIqª€XÀG'OÑ‘¾¿ÎãÕH¼£ŠB¡P i“óm"i¯pí4`À‚Œ§à4`&u²öL™†ÉD^|‚YaÇ¥Ö©'îXÊÙ …BQ,œííR¥ßÄ„–oohüt»/ÚA.A,4Œ§);)©éEqR )ÉÁ”× ®P(Åö­”6Xd-,¬Mûû ƒ‰ð!°Áb®º IDAT¥•Ä•ƒŠbƒNâ#}ß q³W¨•³ …¢8;v:…Û±%Î8³²DR’ìPBB¯ Ë“°¢-ƒ+“ Ù¸Yã^,§ñ¿ÜY …¢HÔ–èKžé[¶’ÙëlÜ ¢+XSK=6±”F #á1,“ëLˆYÞ µ­ïTÎV(Šbàlãë}Ÿ&æ+sdT‘Ú±Cñ íúá§1ƒ”_Æ‚fig‚‘awÒ¬Ù …¢’,YSÆ™Z"|ÉÍ·‹óŒ$‡ÑZ¡ ÈtL‡F°ð£ãPÃ;Ùþhål…B¡(ÎŽÃ ¦O½aΘt{íðY•.®€`ˆ×í"Íår"’-Zƒ·›ø$¶¡ËE¡P(ŠD ý{žiIø‘D-ÉÆº8â%‹l¹z…¤ ¤Ÿà\A8ãòA¾ÇP9[¡P(Š…³cOÊ Y9¿Iâärakâ´—Ïç8ÉÜŠdÎÄ.úWvÎ,LÒßb‡kh|‘­í~ …¢¨”qì IYaAÁ7Yéi-{H¤_Ú+(²ŽÉ2ˆÃ. 8xaûqõƒ!Xc¡œ­P(ÅÃÙ±ïÑc_Ú³7ó6aŸ~·©ûÙ„àÈÝ¿"±—2îg–ÓÕI—f&Õ>Qžý‰B¡PL(n½ÖáÚ5¬¸T¶b •uý ¤|®Ã:e…}j‚(#n¤D,žÙ¢°døX9[¡P( Ÿ³cÙÌõ£@zóä@¡}% ž“àÛj`DNÞÏ•RÂû) –7Ýý‚…͇3â` ®P(ÅÊKH”åE6båda$Ä€ˆ` °œ‡ƒÈŠ–"$Oi_t¤Ë&7ˆcYÔg›z¿*g+ Eás¶ÉŠäN­ˆÀd‚´nÜY(7 cÂðLúBR»ÎÄþ’”Nûú|SºÖQÒV(EÅÚf@ k¤0õ_F"x‘g¯çÿm߉ê‘zN “ :%ÙÇÊ0„ü)MsTÎV(ŠÂçì8µ {'¤‰cFlKŒ(%žl!Á!æÁâ[ÌÀÅx0%ki'¶nÈFk E·3òˆÜ·™]'™²‘ÁB¿âhSWÏx&S´¦´.>­{>°ôÊ_ål…B¡(ÎŽCL/û IO¼^,7L°“nâtÙ2t|S4ð•|, :ÞÅ•£Ih‚·B¡P Ø/`JœŠ!¼èÈܦj‡ŸK-ÖiÎR° 6ðùd¾¹:ÏTŠœ§kìš? œ­P(ÅÃÙ1à– );¿.R$ Þ¹°ŠH!MÇ“/X댺}™od:ÝOµ‡€`?L#?û+ P(Å"Œ¢ó\ ?¿.!未zc¿L ¿ôhL[Ù'5Ú*Ã,‘èÕÙ³©r¶B¡PgÇ$3¥NFüU}Ï^zl‹Èûv‹*â/Óž=Ù _"ŒÄz&$Ë»NÒ~?…BQDêYXceŽÝˆ:"|˜iÊ ¬ÆaœS«W¢Y–*å2"_ó’4‚p†ä¥u#!W0+g+ Eñpvœž‰käÎô} aûÀIN“uÂä¦?i×hEq=*&ü€Hõé0Næ‹•´ E1©#<¢ˆ8¨‘ôO{Õ˜ó2Åä»àÂAYñF\¤d‰FˆHç0 ©œ­Ø@Q¡+Û‡ôT9{=œ‡ì^öà´ïDž‘åòt¢Æ“®Œïwñ½*A>‘ýÉ2§?Ff"^?œ…ŠË–¢qÉB´45éÅØ†¨¨ªBC÷PSW¯£0å¤þ ñĔË@‘žæ°¤ÇòÌèÅ7/ãÕ*(m á”Ja…ÔFålE{öŠ¥K±´qZ𕳷)gWV¡¾¡'jêëµàVÎ^‡³cï½jdƵžx£mëd",­”ñngÜmC닟³1ØXi$·`NÒ4c›¯²( çÍÁ²ÆÅ(-+Gum^mˆ\[æÏ™‰Õ-ÍØ©O?½ …ÇÙ¡ev©aF¦Ø3ªGFOñűAÚŽA X²nòK„FxÔõöùb˜Ø€H|±•³íÙ‹ÎCÓÊ•èÕwÔ(go[Qjù2,˜; ­m«Ñc§>Zl+gçqvÌ~úÜ/+†IK±Šòžé·œFv²<3_VïCh‰ÀÖ ò¶)*Ž i,[Še‹QÙ­Z/Æv@\R‚¸¤Ë£¼¢R•íIØsâpË…D©!žDºØÔ6Ê rÆPÏ=f ­Mm¢àz° LèLdõ’aePQ9[‘_d/_Úˆ¦•+1d½ô‚lÔÔÖ¡¦¶S'ýJJÊP[ߠŶrvàl:ÉYþ$±"çèà $š×Ã’³xrU<…'{õ„‰Ã>ØF€5`+ý+Ö„¨`Jo$„Æ% QZV®b;£´¬Kê…(¸Ê&ÛÓ—†Ç09ž¶ °$‘&&Dˆ¬¬´c`ÙÂrâ8Õ8å8f Kb8ãma8oWålEÖZ,m\Œ^}wÑ‹±Ñ«ï.XÚ¸ÖZ½ÊÙ³cb B&™èIâT¾Xw¥JXsd¤yïžúi­¡ ?%/›²³pE¡¡¥©IÛE qI V._¦¢`¹ÛóûÙô4m,¨%Ö¥2’÷Àö4^eaXJ‡oœ¨’z\ÃÇøú-Œ+–•³€S³™«››P]S«ƒÛÕ5µ˜1mrx_TÕVÎfÃÎuÄ0Iâ—ó C왡O°Ö7Ã{ 2òC]$0‘€]¼¯ öĬ­Ä( E±6¥ýd²ã†b‘‡ =s(‚YZ3|¡d¤ÇÚµs0¬!˜DþP:ÈÈ Pø*g+²Å¶BßEárv°÷ËÎ¥‡ÆqI ŽO’Æl3ë‡zÁ 6Î;Єáx µD2å‰a)å$UL …¢àGÕ”!ˆî†(¾XÆMµgøà8WdBf8í·6 C2ï¸×Šï«S®ål…B¡(Î6ˆ^ NwÈ^J—ÆqòU:¥U>§KîÁ–HB 2²ºD_’?Q2éR¥¶B¡(JÒ¦ì7€u¡1†ƒ‚ˆŒø\§zž°³ê³M¹Uöáé3ƒMjµ§œ­P(EÃÙqx yyî$‚9§ ~«áÀ®^wÆÜF–3áNàJ}fI3Û(wáÈ\? …¢˜À):†µ02CØ ¦l/zÞ Ý‚D ë,ùÒ®§L[á[CîBÄ™%iål…B¡( ÎŽÝ2¡Mcu9?hŒÒCà ‡‡¡˜L@àuLÈO_¥Wî Qš2¦P(гý¢#Ã0ƒÈJŸ†süpœf¤:à†i,ÚEQ JWïÓ*ìèaÙy½E9[±ÞjB¡PgÇ~yØe´Ûll¯ëÒK#%á{õRv;²Ë)Ià! TLnšÝˆ8¦ÉþQP(Šb«i(ÔNe–áA±ÒsŠ2U÷D×÷ìíöÂŽü®¥GÐxOJùׯÊÙŠu>’Zg+ÉÙâ¯jÂSL¨ÚudKÖy Z¯€X÷[Í 7(³¶¬"æ`Ú-v(dá¬S– Yï»^}óŸøÅu7àÂo~ç\øŸøÞ~Šg^ø;`ì•?ÇsŸ¶ýÖ÷„G²Cû]û¹ëÃÿÞ|+¾}Å•ëúžþÉL|eÔxò}³›…l´y"E(“ë—&6Nå0Z2˜%øÅ$2‹O«¬d†þëÔéƒ=OÀÆ÷R(g+:Ͻð"¾yÙ÷pìˆSpÈQG㜯]€‡û3àÜ .ÄcOü%lûÕsÎÅÝ÷NèÐ~×~îúpÅ‚3ν^Ξòá‡Øÿ‹_Â?ß}Wß,EQrvÌ :°%“(é>à ëÍÊ?)ƒ6âI̡ƭ3ºo,’°Òh-‡;ˆ´ÚWtÜtû]ø÷¤É8ýÔ“1ꌑÈ%9|<ýTUV´»ýþû~wÛµÓÏcæ¬9xû½á3ŸÞgŸu´°W(6¦Œ8 Ëô>Ks†sëH$ =}43ZƒÌ˜¢L¦;uÅÊ£Vœg+2K—䕳€Ÿ^u5Þzç\<æ|ãÒKÑ–kÃä)¢º[U»Û|бû°a~Ó>ú/¿ú*¾øùϯó³ñîÓ7JQÔœ3"Yô¶$ÖUãâè–(SÂŽät­<‡Â Ža¯“8Y$"B‚LÀ%XJi‰It­«Ë௾OšŒë¯ú1**ÒÂz·]ÖŸVvæi§l•s©«©Á#?µN¡=oÁB|0ùCTUVê¦ØryÄO Â9sØÀ~,®Î:* ¦ –]Š£ È~8Þq®[†ÌFÚB”³[Ž¿>ó,Þ|çmñŽ>ò0üõÙò¶Ïår¸ÿàÕ7Þš¶V°ï`ô™_EyyÙF_ÃCü=òç½Þ‘#NÄÈ'ꇥØ9;ÛqÁ™oDå é¿`¤~Ö6Õ¢%ÄH£×ÛTYòfJyÒ)ÏÊÙŠ ÊvÄmwÞ…‹¾v>ªª*7ðÜl¬‘k9åä“pÒñÇ…-xèxäÏFcc#>õ©Oaì·¿‰>½{ç=wÕªU8ÿâKqÔá‡á‚óÎ]çÇóe<þ—§ðÎ{ïá?öÙ;üäî ÷aä©§à?’wmmm¸ù¶Ûñìó/bÍš58ä ƒðͯ_ŠÊÊŠ½îÛïß¡ktáùçaÌù£õ£¥œ½EœíºH(uR%â¼fqÊd‡y²µ¡„OÅtK@"2º÷yeš@þ.!;oôÝï"XÓÚŠù bèà[´ŸGÿò4^|ée|ý¢ pý/~‚/}©î–·µ×Ýô[ì¶ëÎíÙPVV†ã¿|$δ‰4.]†×ßzGqØ:ÛÿîÞ0wþ|ü÷OÆáÚŸþ .„ßÿ±S‹g-²»p]#Å/2QæÙ™ó”tÓÉwÀŸëü}€MPOÖËq3îÊÙŠ-ÁêÕ«1kölì5|Ï-ÚÏ=÷=€'ž| ?7Ü3Çy$êjkó¶I’—ÿèÇ:dP;E¶CEyÎyÆß›¶‰,Z¼/¾ôN;eÝ•Ï_þêF|2s6î¹ã6L¸ëÌž;¿¹åÖN-žµÈVÎî,Î6΃5Á"%0(4|3KS7`|_ gb+¥ÜXX±K MåÁOʺpòdm•¶»,XfFMÍæ/ïYkñðãÁ…çƒAvEC}¾ø¹PVV–÷Kò»{ïGKK .¹à¼ îïè#Å”iÓ0cÖ,ÀãOý‡üEt«ÊoiiiÁsŸˆÓN>µ5ÕèÞPÓ¿r2^ûŸûÆŠh-²»W‹®,ƒ…–eá­$4úW3{W7ÈèqØ´BÖ¡°%’¡áaXXk…‡•³í|.¹ã_³fÏ3£¶®~ƒÛ!|žÖý>—Kp×½pùw¿ƒÝ‡ Eî=pÔ‡£¼¼"lË–qí¯nDSSÆ]~ùzÁ¾2âdüëßÿÆ”©ÓÀ L¸ÿA챨öb‹l¿jU}ü \pÞhÔÕÕ¡gž¸xÌ×ðÂĉ~ýcÎ;cÎ[=æüópÁy£7隆ףPÎ^‹³ãÔWÕ‰­““;ˆÜ¥•ú<ã…¬Õ³I[˜÷`XæÌd[ÂÀr.£’°.BvÔ×9cÁÂ…è6`Àæë‹cõê5mf¡íIÒZ cÚ×Í>µçî˜3o>ž|æYœ5òÔîóø/‰K¿{9"ãÀý÷E}}í:ÛTÊ`äÕ?¾u55[tF „b[‹ì.,{;£±Ú“aDŠÒeDfç¬j2²5ØÆf&fÍðM[8üÿg‹dålÅ–¢¶¶ õõxõõ7°çfÚ+W­ œEQ»Ûìÿ™}ñÉÌ™øýÿˆK/¾h£û½{µûó(ŠpÒqGcÂþ„½ÿ¬e,nlÄG(ø7-²wÂN³ä …?Ig×Ëç9°¾øõÃêÆ1$Y °†¤À·žAÉ{f O+g+:gŽ< Æ Ũ¯]ˆ?<ü(>úx:fΚ…§Ÿy_~ʼnuµ˜;o~»œ][SƒC:×^>™9MÍ͘øò+hnÎo»ûìûcÌù£ñÓ_\Y³çlô¼.}.n¾ázô_5lÇ8ûÌÓñ›[oÃo½k-,\ˆ¦l~Ù˜óGëà£röVãì˜Â¼ºM£{áš¼™Ò_®ÐóGn щ">ôÀJ¥‹&ŸF–Ù#‰ï‰Ÿƒ÷¾…zØ5E®û<õì xùõ7pÿ†!ƒûõÁQ‡ 8þè#qëø{1kÎ\|ï—®³K.»&<€qW]ƒ\.‡ýûc×]v^ÇfïÔô§ãÚoÂÕW^±ÁÞ¿ênÝ0|÷ ,œzâq(+)Á÷>€EKQW[ƒ“;ƒì¦o¬b]çµaøE@<«C¶¹S9\YkE1q.ñ#„ ȵ]FT͚ȑ~(–•³[†8Žqó¯®ÇCzÏ<ÿÆÀ-Sú­˜Bt°% ålE»ŸK½ÿQ( ’³cOº>ß&‘èIG¼Ń„`]sxÄ©b}On~B“™ƒ´îÑC™ï½Éà( EѰ¶—.$€‘ùT1#1bi äÿ8³P¢¢÷oÎvËœHû ™³SíÊÙŠu>˜z Šäl³V,*f$u1wò‘•†È7~ûD2“Fó29›“ÜMÐ?Rék)*ŠÂBEUrmmz!¶3rmm¨¨ªÒ Q` Œ[jÊ`”a6±}ò•nˆjä ¦P†¸)³_Ãþ€<‘üT|úÇA9[±6Ê+«°jÅr½Û«V,Gy¥r¶rv>g&†5NÝp¬@dID +}{”ª$Ö5…³Lcf“vR3WÞEs'ÿ\ãÝÜ Ea¡¡ûNh]³Z/ÄvFëšÕh输^ˆ‚cmNAöê0\"£÷fåYîú7˜\ß³%F›Úˆ‘ñneg,•Hj™eY±¡bYª´ålEÞÇ‘µµõX´`ž^ŒíŒE æ¡¶¶^ƒj”³ó8;Èr¯ ã– ÉÇp0ßö1–ÖçR2»©w&¹Þ– ƒHJð_%ÿGÂ/oÚ é+ 5uõXÝÒŒe‹QZVޏ¤D/Ê6D®­ ­kV£®¡jêêõ‚dqã ÎxY{EÃ)#†ó•/’0ÒåIƒ´ru„.Š ³»î™d ò¸Àål…/²‰U5µh˵búÔÉèÙ«ºÕÔêÅÙ†Xµb9-˜‡ÊnÝPUSÞ…r6Á 挩vøXøIu¤Ó–~‘eªÒ-5&ˆ|/[2ai‘ƒç`äT$`c]û9±L|êXM¡b§>ýP^Q‰Æ% ±rù2½ ÛUUèݯ¿Ù Oº J{˜Å"*-\=]K‹‡Ÿ[dsW³ß§ËþùÞ胈`™¡œ­Èƒ(ŠPS×qTŠE çaÖŒôÂlC”WV¢¦¶•ÕÕˆ¢Æ½(ÊÙ³coÂÍìM¸½ˆnB ïäŒ4ÁÀyS8˜a#Ë•¾¾·AAq­rᜲ.ŠBDM]}Ñ{ .r7 ;õÔ7RÑɬÍECœ<ȸpW²Â0`Ä^Ï-G:Î3Ò~a…iM¶ö|¾}#tR;µ€r¶"_©#DQèV[‹ŠnÝ`-‡!.ÅV¾þ ãÞÿ¥j¶rv–³c° yíÖKèBäÁwUªÿ •„ä0ã̤ȿJ ™^@¿É X–géìºbë`É’F,ilDq„î zQ÷‡Õ Âì}Y³–Qò8ù"ØÇŸ[Ä0¡':û³´g¡¥CLú൷Dé[G6ÄÙ²0J fëË@î9Xrá6Lf¢œ°”ÀrX ¶If”ÈG.—ÓÂǾëŒ6_lûÿ²zým—÷Ó£E¶rö:œ‹9‰4€‹z4° ¤Žef-CŸ ÌL`aK‡‹?°¨"ƺ&r‰Ô ¹ñ¤| èD,_±ó,ÀðáÃADø÷¿ÿ(ŠPW«=‹ŠNû«š™&ÄóŽ…f]LBÔÆÈѹn6Ý»°¦>ž‡å{áFÇÐÞ[°>Îvó Ú’f´r rI+˜“¼âš„§Ý¹ºèu?-ïÕç kÁœ G°9X¶`›CÂmXݺo¾ù–~¶¥¥%¨¬ªB}]ºwïÞ)íZdoÿb[¡œÝgÇ,‚ ÌÒ`p(ñ~—øÃû>&×—B‰+°ÓfsÕÄ©Ú&*ð:/@¡G26š IDATØR¬Zµ ³fÍÆž{î‰ŠŠ Àž{î‰÷ß‘‰P]ÝM/’¢sÀVâÐeQ“ýckL!NÃd ,L°ç3AK&oÅùÆS^Ý òqèks6À–‘KZ°&·†ï„#N>Ÿ=t8vÚ[ß«DKK3—4bþ‚ùX¸p!úõë‡ÚÚÚNi;ЂO¡(,ÎŽ½ßj"!i›H*™§=)k0&uW%'S˜p—šSYÞúƒ‹<ɉg–¥O…b ÑÜÜ‚ŸÌİaÃP•ñž®¬¬Äî»ïŽÉ“'cÀ€ÝPUY©K±¥âˆLž;‘ÁPê.Í̸yí #ÜgœÞaÆš[Ÿ*&n|Ä„Hx3´ä1˱³œí:×$«Ðܶ—^1_½ø0}“ •è·s%úí¼3æÌž)S¦`×]û£gÏžˆãX‹e…¢ qvì…jÊXzSªq%rOð©…”³OBo| &Õ)q@ä,]}ÝOªgüM`,C¶¶¶âãéÓ1pà@ÔÔÔ¬óóêêj <S§NÅÁƒPVVVÄ ¿û;!}ÑîÿT`‚D¨`¤Ü I=®ü¨Yúþ¤xÎôBv\Wt&fŒ³ûuµq3šÛ–áªÛ.ÄAÇì­oP‘¡ßÎ;£¢¢ï¾û.JJJP__8Ž»4gwÍbN9[9»}ÎŽÝ÷¤oöfƒbqÂä¤röb9ùKOŸŸF'¶IÞd»•“q/òý¥O[Q¸öŠ¥K±´qZš› ˜Ý ZÙ`àÀAèÞ½ûz7«¯¯Ç€ðá‡SQBÉ:Ãa¥vUV¡¾¡'jê5ø €?x´ä:Ø·aZå¼_ˆC^º¤)dî[ìdéœ&>‚Yyd0´äVà’+NÑ"»ˆÑн;† †™3?AUUŒ1›Ü³]4œÝ¡œ­œ½!ÎŽïôk'o÷ä$t“ÆVŠ”N°¥Œ ”¤¾sêy’žƒ˜3wØi 0 }û ±È^¼pšV®D¯¾» ¦¶® ϳ­­ “&OFÿÞ½±ÓNOPìÙ³'’$ÁÜ9s°Çž{¢d T£­‰Ë—aÁÜYhm[;õQâ.8ºvJ†›sñöw⮄ ©QÚçç šc°‚GÌn œüÏl™„·ÒÊÇ@Â9¬±«0p>8]ÛEŠývÞóÌÇ’%KлwïM*´‹…³»*”³•³7ÈÙa°Ñ·€x5š„Ÿ Ø;ɇ'"7aÉDapÝÎÕµk[÷d¤›2^¬ñ««\Wd/_Úˆ¦•+1d½ –°“$Á‡S§¢GèÛ·o‡Ÿ×»woôèÙS¦L)X‹²šÚ: Ùc/4­\‰åKu)¸GR72cüÂdO $º<3hîÝ™˜‰‰`ý`ŽXG%Xo Å ÃÖ‘;»x`ô–m¹Õ8òäýõMé"èÝ«7–-[†¶¶¶ÿÞ gwe(g+goˆ³ d€Ñ„"Ù+Í,K” C.¼=! K¹0miÉ5…»ä0·±“à¿E@æ„áNʧŒi~RaÁZ‹¥‹Ñ«ï.ýK3í£P]]þýûoòóû÷ïÚÚZLûè#X[¸-$½úî‚¥‹ úwHuÄÊ€Àle@Æ-#1¬±HHÜ– ƒ83 šÐMç»ÙJ…òRf|š ‘9<ç2Ãr>{èžú¦t4toÀêÕ«‘Ëå:\¬gï(PÎVÎn³cßúZxËF2•é&,ŸB7‹ C¾ç™”&_A_¼»þî |€&ZËÌXÝÜ„êšÚ‚¼+gf|üñLj¢ Øìý¸~íñÑGaРA¹ÔW]S‹Ó&‡÷E—# nUÏx2fÃY&ÑÓÑ’˜¬ÓRÆ)0kf²Ý‡$p–%9|Y¶° µðëB¨¨¨D.—tXÑ.ÎÞ‘ œ­œÝgïâ d„JßOµ»B›¥Z7lÂI‘ÉÉÊËa Á ·aºÓ»—„—£(´Bv{ÛZ k-’$A.—[çkÆ'Ÿ ±C‡Ýb2d@„§Oo÷XI’„óÙÞ×EQP¿%^NÈüceu‘ $IÌÉ6v’!òl¦€yqÃèNb Ìé¦Û5f»+¢²ªj“8GùAÿŽ* ›³cç—í}E¼!·´u°×»É—bÙÚPt³ÿ5~{éq!‰ÿe©Þ²KౡåÄê „âzñ’%X¶t)šššÐÚÚš·MiYªªª0|øð-NQs¿„aÆáƒ>À{g5kÖ䯴UUU¨«¯GNJoS?ˆ2.sÀGŸ»V8Ÿvk›€Ëö{À&“ĘV™ ËÒšçZòœÂÁáÉqvÚù] UUUX¾b%êê´×Z¡è œ‡»/ \‹ˆ•ªÜ²•¾‰üåΰϤ²8¥á3Î22ÿpöOzÊÓéμÿ*vØ;ÿ$I°lÙ2Ì™3qc§^½0dèÐî¸5aŒÁ§>õ©vÖÒÒ‚¥K—bá‚X¸`úõ뇺ººNIoS7i§vLF’qÓ€.f GHÕ…[~$ö9NQ1ð\>§­y)¡3@†L¨«ýÒ´QÛ¦.‡áÇcòäɘ5k6vÛmW½¹W(Šœ³cÿÏ( Õ;§þ×¾(! &,†ÞÞ­$µðƒ”ãìÓ%}¢™(ÞÖFê߈¾ÈÎårX´hf̘!C‡n’ƒÈÖFEE***зo_Ì;~ø!vÛm7MoÛá?·”†nYt|gÀ ²!ÜÀ'áJ¿ ïõíwäT‘àyê7óª 9¦@ ŽÀL JR2'ÀU´»Œ1Øc=0uêT|<}ØM‹m…¢ˆ9;všL¿ŸL—‚›œÇ¶ŠŒ‚© …®—p×ܱ‘ZŠÊmà|}aæ<…ùÑÜêGH’–.[Š3f`ï½÷F}CCÁ^¾}û¢¢¼ÿú׿—ÄhØÂô6E1ÿfpª’„4]OÛ~2<„ñúÄ€”ˆ³ƒ2”Û¤v§¢Œð¾äÓÈ~aT£­w]D„¡C‡búôé˜6í# 8 |£Ÿ…¢9;æL‘콪´ÈÎ+¥x/×Ì€£;†!rá7Y;œ ‡¸ËÔK[Q˜w€[wÿÖZ¬YÓŠÙ³fcÈ!]d{Ô74`È!˜5kª*«@dTiÚQ !OnÆ‘µ„„h_'2Pp`ƧæR&Ä‹²DÉÔãFàI–5ýA9 #h‹vWÇ€0gÎLö ˆÒÒ’íÆÙ …röæq¶qS’IK#î!R•ûIJvÐaV“}v¼ŸÝ„Ä´»#F^L7ÖÙ§ U¡˜O-QôÐÕñÜ /â›—}ÇŽ8‡u4ÎùÚøÓ£aÉ’%ï}èÛ¯_Ѽ–¾ýú¡´¬ K–, ®$<ôœ;æ"|Ô—qÊégàÁ?üQßô.ÎØD6%k‘ ,œÊaYXQ–#­8,ƒÇ–6„x‘uDoI›`ŠdhHà†Ç²H9[È}ðÚo`ŸýÄ÷~0®Ó/ËšÖV¬^½:ï±3GÆ#ýy«¾c¯‡}ö?ûì >ó¹/`ÄÈÓq߃¿/(/ãÿüæ·pËm·oÖsûõë‡>}úàéS×¹¾Û’³–÷ñÜ .ÄcOü%lûÕsÎÅÝ÷NèÐ~×~îúpÅ‚3ν^÷Ž)~ˆý¿ø%üóÝw7KäQÎVÎÞ–œƒS{?0ÁŠ‚í¿, 1ËN‚{ ¯îIº\Ä´Ûú;BB>™†dÊSœH¤HÏ“ã]?½êj¼õÎ;¸xÌøÆ¥—¢-׆I“§ ¬´K—.Åa‡Rt¯©×N;aîܹèÞ½;ž{áE¼ùÏ·ñ_ÿïbôíÛ¯¾þ®¹îzôèÞ€#ÓX쮈lËù8OV&×vçe8\†É)³‚çËË⻊4oÀý°aŠ]&ÕƒØ èxÎÞ<õ׿ás€‰/ÿkZ[QVZÚi×åŽ;ïÂÌY³pÍU?ßæïÉȯœŠo\z ZZVã•×_Ã5×^‡ææfŒ9ÿ¼‚øÌÄqŒ(Š6ûù}úôAǘ6í# 8U••Û”³'OùÕݪÚÝþàƒ¾ˆÝ‡ ëôó˜öÑÇxùÕWñÅÏ~ŸŸpßfï÷™çžWÎVÎÞ¦œûÚÞˆŒn]í솥ºO§*³w—&ï¤-‘DèX{ €k3!æ$ ·ñn%ZiwYüõ™gñæ;oãÁ»Ç£ª*%éÁbåÊ•˜òá‡8`ÿâ‹®ohÀÇÓ§£­­ Gv(Ž>êÈð³SN:o¿û.^úÇ+JÚ]Wqþ¨ ™\wB„eC>´+ë®äØØúÈ_Ÿ æ3»BB.#ñj ¹Ä²ˆÝð Á…_X¤†Äؤ%Á¶¶6<÷‹¸ýæ›pÁÿ»¯¼ú=øK]â=)-)A·nÝЭ[7œtüñX±b%î¸k|AÚ[:Óᇰ§M›†]û÷Guu·mÆÙC^ïs.¹pÌV¹f õõÏ„u íY³gãíwÞEuuõfí÷ÈÃ×W@ cÇ @ õÁ&–t’/æçY‘Ë$ÈJ„MúŒ¼üêkèÖ­ {ì> Ÿ;ð<ûüóy??sÔhünüÝ8kôùøì—ÁÈ3ÏÆ;ï¾~n­ÅïÆßO= _<ìüç·¾¹óæîºç^Ü~ç]øë3ÏbßÏ~¿¸æÚð¼7ßúçz÷ÙÖÖ†ëo¸GŸp9êhüôª«ÑÜÜ’wNO<ù.¼ä?ñùƒÅ«¯¿Ñ¡×ºï|Ë–- ûÚйûãÜÿàïqîׯàóгFŸ÷?ø üüð£Åëo¾¾ÿ`Òdð…ƒ:üü8Žo¢nòëë1lØ0|2s&–-_¾Í8{C_ç^0=ñDÞc<ôŒ<ûqìqøæ÷ÆbÞüyëè _À‹/MD[[[Þ6¯¼úÆ]>O>úöÚëSøîåßÛÜrûxæ¹çpÝ5ÿï½¥%¥¸àâKÐÖÖ†óFƒ1矇/yÞ~íü`ìeaŸ³çÌÁÆ^Öî>ÿû—×aÆ'3qÿÝãñû ÷`öœ9øÕ¯“wN×\wŽ;öhŒ¿ãvüÇ>{wèµ.^¼=zô@eeÅFÏÝãÑÇŸÀ·¾ñu<úLJ°Ï^ŸÂ…—~+W®ìðõÝÐó;CÑö¨©©ÁðáÃ1wî<466nÎÞÜsßxâɧð“qãðÀ=ãqÌ‘G¢®¶6o›$Ipù~Œ¡Cá‚óÎm_Ð(¯À#OÃø{Ó6‘E‹ãÅ—^Âi§œ²Îö¿üÕødælÜsÇm˜pט=w.~sË­:gålåì­ÉÙ&‚7í¶ÁKЋèáD²÷”ªÖ‰ßof ‚£t㑆C7 `B½ŽtŒRQ¨w€[ò5kö\03jëêÛý¹µ\Ü7ÿòÖ~]/¾ô|2k6N<þ¸-¾†ê"P œ-£',C‰Ö7BÂn0Æq$K‚®§Ðh²+‚l‚ÌAÞ˜IV%Ì r2YÎîhëHKK þ>ñ8äKN…ýÂç?‡¦¦¦<•Ž?öì±û044Ôãk£ÏÅâ%K0sÖ,´¶¶âž ÷á‡ß¿CÂÎýú᪟\‰¦¦&¼øÒÄ {ÄI'bø{¬³Ï¦¦&<üèc¸xÌhh¨G¯vÂ¥ÿï"<ÿ÷¿ç=ÿ’‹.ÂIÇ¡C£¼¼|ƒÇJ’“§LÁ7Ý‚ÑgŸ>÷3Fž†Oï½7vêÙßýÖ7ÑP_‡§ÿöL‡?z~gÚPYY‰áÇcá¢ÅX¼dÉ6áìÀIòÕÞ÷¹\‚»î€Ë¿ûì>l(zt8ååa[¶Œku#ššš0îòË×{ ð•'ã_ÿþ7¦Lf`ÂýâøcMÛfdûU«šðèãOà‚óF£®®={ôÄÅc¾†&NÜèëVÎVÎÞÚœ[ ¦!ŠÀlåI.TÆí&èׯ#z]H2àÉ¤ÞØd"n}v(Á XHXÌ´I‹í.‰ž=ºæÌ™ƒÚD)X¼x þû—×á;ÿõutëÖM?]ö.~ÎÕº8tö2…Äñ²/‹ÓV´ ©ÿªáðÿ¾`ÂZ-" ˼‹›y!i¿ëØ)¿øÒD{î¾ZZZPUY‰!ƒáÙç_hwØ úöéƒŠŠ 47·`öœ¹ÈårØ#ó»\QQ½öú¦Ï˜ÑáK—Ý猙3a­Å·ÇŽ ×%—äÐÔ´*ï9åeeÝï„Ä„¡_ß¾8ûÌ3ðÕ¯œ*Šú¦Ÿ»1ûì½7>™9s³>"k??ŽcDqTÐëÎàì¹ó桹¹{ì¾þáÈÇŸ| “¦LÁcý~£Ã¸ÕÕÕøÊÉ'áž ÷á²o yêiu01pÆ)nO†]‘ #Oñ€Ú9Ò%Q[[‹†úz¼úúØs(´×´¶â²+®Àþûí‡ã=F?]Yñ¤mÝзaˆb¥[ÄQɈ(!:1ˆ8ß[âz)¾¤“…°°48²±Dþ¦©³÷{úoCss :üˆ¼Ç.\„~ÿòõ:bøðÓÖÖ5°Ö"I’<ïøÒ’R”u noŸÕÝÜ0Û}ãïB÷-ôÑ÷®#¥¥¥(]«xÛÜsŒÉSÐyåÊìóûö郆úÎË hnnƤI“Ðk§ž¨©©Á²…s ‚³W®r7IÖÚõ~¦öÿ̾ødæLüþÄ¥_´Ñ}ž1r$Fœ~:Ì 19ä`ô‚¼‚¼ÊÉão» õõÊÙŠ‚âlã«h±íQ¤up˜Ö Õ{P¢wPXüv¾<'€¤÷…DvOãnHŠàpó¿Î<}$&ÜÿæÌƒ-{Å8\{ýÿæä¶ò“íÈõI’~ð£+QQQqc¿‹Î¨ÑÁšBÿÕpK‘Æ Ö€\0A(„XãˆØ†Ì”ý™l…{îdJ§Ü] ž³L2Ò ‡çm¤øY¹/¿ún½é×xïÍ×Ãד=‚eË—ã­·ßÞè>vÙeÀÛßbk->˜4 C år¹_ƾ}z£ª²ßHëIGà]GJÛQH;zòÕÏ0 ƒàðéÓglð6ôüóÏÕi/+V¬Àû￾}û !ïe[rvûß÷ëÛÖZLš2y½ÏíÓ»~ö£âÞÄ‹'nôõõµ8á¸cñ·gŸÅ9g|µÝmúôÞ U••˜ø—;ô:•³•³·%g_±“ÏÄ<CÖ¤«$ïãê”lgÏgÂë@H‹4ðA“.ºÝG»»?®V·ÇEWÄ™#OðaC1êkâ?Š>žŽ™³fá¯Ï>‡×Þxs³÷{ÇwáÊŸý¼ ^£µWþì*Ì7?ûáH’---hiiÙdLQ$œmÒÙT pä’Å2«ƒVlR€9~÷|éb MÊM7ô(Dj×¾îž}þÔÖÖâ€ýöË{¼_ß¾¾çžxöù6ºªÊJŒ8ñDüüêkðþ`Ic#þçºëÑP_Ï}ö@@¯^½ðÏwÞżyóÑÒÒ²Ñ}ÆqŒÑ£ÎÁ 7ÝŒ×ÞxÖZÌ_°ïOšÔ©ïWGÎ~{ûxñ¥‰Xºt)~{ûhjn‡ øô>{ã‘ÇþŒyóæcÞüùøÓ#¬sœ =ÿòq?ÜìÀš,–.]Š)S¦`×þý×0Üšœýô3Ïbâ˯8å»®sçÍo—ßjkjpÈAáÚëoÀ'3g¢©¹_~%ÏI>{àþsþhüôWcÖì9=¯ FŸ‹›o¸ý妩½ÏÒÙgžŽßÜzÞxë-Xk±`áB|0eŠr¶b»svLÙ wN¤';}¡oETm#'Ä6ÛÑäÀˆ‡ ¹Ærz´Ä¡Üß^XÖþ쮌8Žqó¯®ÇCzÏ<ÿÇœÊËÊpÍ/¯Ã¼ù н¡ç:Ã÷Ø£Sß±;|ö€ýñ¿7þ‹/Æ>{ï…;oý-JJ\äù·þëë¸ò§?ȯžŽž=z`ĉ' d-õ|CÏŸ3wî&·Ø¬E‹aÆôé[5°f}œ½Û€ÝpêI'„büê_^§OÇÿüb]ÁcÜ÷ÇâºnĘKÿ ¹\†‚!ƒóGƒ&MÆØqãpçooÙà kmM öýô§7xîç:åee¸î†_cþ‚…h¨¯Ç¨3ÏÀžk…éL|ùUålåìmËÙ#†]Ç +ÄíªtoÅ fùǼçµEr>ÛávÁËéB ³(‘†ð,Ú`ÙÂ&90'Èq+Úì,[= oL@?…p×ÇŒ\.‡i“þ{î³ßV;N.—Ccc#>úè#Ú€€±WŒCîÝqÙ·¿…»î¹7üæ&nàè+#Fàc/C[[~}ó-øÛ³Ïaõš58ìàƒñÝo}3û™£Fヿ„ÿþ¦2ƒÄcÇâŸï¼ƒ?=ò(,X€ößW^ñÔw Çï…çŸÇ AƒÐÐÐЩnkãƒ÷ÞÂà=öBÇyEbûaßÁg¡®²?bS†ˆJQ) ň(†¡ÈÅðBz‘&8ÚÐŽGÒzgƒ&ÂáF@ "À¥`3• mŒ¨ °œCkÒ„¦ÖEøûÌ›õMÙR%wÔhœvê)qÒ‰Ûåùüyó0{öl 4p¾ñmÁÙ ålåìÍçlc%tÝËß!7RúYlfšÒ[I¹–ãzP¼w7 @ÆMÃû¨uö-'®wÅ$Þy„ÄÈÛd${…bãXŸ_oGüx_óM\9îx⑇±s¿~8cÔ¹˜?>~ó«ëñÀ½wcÖì9¸ñæ[ô"+:¤X8;(›±,õj Æ-M§ H^o:ÕâD,„M°Ž°ƒx‘øÅL:\Ôo>g+º2æÌ™ƒyóæaè!µ7T(…ÇÙ&›ïsÛSoVÈ„ž•ЉMþ°’âY¦1ƒ!J˜Ì4îE‡q4Ñ:»@ÁÛèkËÑQ?Þã9ÆE÷†œ{öÙ`fœ{öÙè×·/víß'Ÿp|^j]W¹>ŠÎ…ñ³+œý,¼Y)ËŠ_6ÖË Æ„yròÃân¹ÒȽRBɧ馇å<[)EWÅôéÓ±xÑ" <¥¥%ÂIú¥œ­œ½)œ»áG_Tsøû_ÛŒ½IjÉÇaèI ÃUî’$iÅsÛÙJÁŽb¶í”oý`*¶õãÍbàÀ€ÕkVç=æ"{Ši#é° 1ƒ‰…7ÚèÂ<¹‹ƒ·J¥l/Y ,³N›&BâGk2«}$ˆ%a 6OQt)™ƒS§NÅš5k0xð vûë EqpvLbø—¿C6óɆM(éYîÂü$sHÎqʶ ðñNÄÆr0PåÌEG쩊 asüx©ÝÇô³¨Ø8‚îá—“ YQN ŒEêwælŒØšú™rëúMÃn™‘Ù7ƒ°kÿcá_08Êd.!ñ-‚Š-Æý÷Œß®ÏÏû|Y‹É“'ƒ­ÅÀ»i‘­P9g÷œ€Ü¤e6¡YšùeÊÝR±îODŠgcÙ›÷A§æ¼ÒÅÿpEïWEF±éÈúõv¦¯BÑÑ›4¯t˜0aŽ=`d\ÆÛš‚]H‚ó5BÜ ›d— ¬³@ŽdX7`.Û8Îö34Š®„÷ßI’`—]vÖ"[¡èœûí¢ÖÈi¡L€åÄ€Ýá‚Íé€$e½3}Û®ÇÅ"Æ‚Î{Ñ M†,TlÍûæôksЫW/üááG0oÞ|ÔÕÕ¢¢¢"øñöíÛì·.Z„%nÖÞkÐ{Å´‰!ƒß>kÀÀúþ=ö#ߩ˪%#É"pÊI”qL%ß¹3Œ ”ì=Ÿ’]àvùœE—ÂÊ•+ѯoŸMv¬PR( “³c9¸xþ+ò9EÚ·‡„+í— IDATÞ/;5vwýÖí¹‡lÆ*›a¥ýÄ¥Jj{vA—Ú[yß›¿ÿöüz·•oû¯C?È;Úo–¡pøxÝ@ØÈ€ˆÓü7@ãrÝD¸Ô…Ь¥Wøcd{g¾jIÖµÎîrXݰŸmÏÙ …röærvlà¹ý®|•oÁˆ‚g •ÜfŠïtŒ‘Èd|Ý4%‡m9f°„ÝXIdh_l!¢¼² «V,G·šÚ‚8Ÿk®ÊE(++ï~yí:7u£Î> £Î>«Ý}¬ÝCYZZŠ÷Þ|=ï±Ïî³øÛ_/˜÷aÕŠå(¯¬Òd’¶……¡|×$·)ƒLÙ¸¹pB¾ÜàžGLaÎEd“ KZ3Rû>Gôn¬\¤Øžñá|ì6´·¾1]--͈"³Éjv¡qöŽ ålåìv9;—‘ȺƒZ–twã{®SÏA#'I7‹/º9a¹+“dçT‚Ì`%H¬TdšÓ÷zërWaˆP[[E æéÅØÎX´`jkë5ô Ð~G@~vÝ 2Niã 1|OŸ÷nr ¹¥ê‰K÷¥àÎD°Ìa½Ó­n"bÀ‰ì3²„¯½ð¾¾)]KÇ1Œéx±­œ­œ­(lÎ6NYö¦{. ’¼Á¶˜¡'Ë~¬M¤È& ®‰2ö'’÷_ðË “0n‚‡©«¶¢PŠl"BUM-*»uÃô©“±jÅr½0ÛA™>u2*»uCUMmx_…BÚ™/F&z×-FpýÓQØÞe rK’œF¤óäÄ¡uBÚ˜8f3K&° ÖSn…1Q žyôm}Sºæ/˜òòr”””tèw^9[9[QøœÃ;²Ã=#–|ì=¶mèÔC,9D€%ú¯!MãÎç$‘¹IrźMœjδ¿µÐ`ŒAE¨©ëŽ8*Å¢…ó0kÆGzŒ$I°|ù Ìš=8üð¢¼NŸ|4vMjkkEQ§î»¼²5µ ¨¬®FEê=¦4º—9mÖ#·‚È’YÀle(ǵ ÔXëí·’‰›rLû`6¼õyœ~ÑaúÞ1æÌžU+W¢wïޛ߽-8[¡œ­œ½ùœûIKf©Î‰Rã?ßsâ§5avá¿DÞ%Í)ËönSf~3±L½³}4»¢ÀîüˆBáØ­¶ݺÁÚü¼¤-E.—CåÒ¥Xm‹÷ýïÙwôÙuêëëÇq'ÞyŒqïÿRe¤à~I‚@`˜d¹Ñ§ÝJ«SÛ;œJÔüd~º€Û[äZí(åL7 )ìlPB%H¨7ÿüôÛµ:zo}ŠK–`Ê”)¨©©FUUU‡ímÅÙ ålåìÍçì˜à’Æ|Ê£eãmr¹î!˜¡Ä¶rÂþÞDJûx°8 Öƒ!NÒdÔÞ¯€‹mÿ_îäFú\¡¼¬ åhnnFeeeQ]ŸææfT”W ¼¬ åeeZhûëOD›Ô§©ØvpÇnÉQlŒL3 Íu0yžÌkö‚±u¾0A€)ß.Õ%8ÎdJa¹–s¸â¢ÛpÉFàô‹×7©ˆ0gölL™2ååe¨­uv¥›ºJ¶µ9[¡œ­œ½ùœûÖòr¹ÔÑÄÆ5s7év)¡¼¶™Óy !4>%GúVÄÀ†ÄIíF\M…[lo Â&"”––¢¬¬EWh766¢¬¬¥¥¥())éôÖ…KÛnÚDVõ,\/Ÿ |bÄ…}ª®ÿ}b'^°±Â¿FúʼnI¬¨)ÆIÌH9›@6FIT†EkÒ‚›ñžyô-uò~8ðÐáêFR hiiFã’FÌ_0+W¬@yyPS[‹ÒÒÒÍj=Ð"{ûÿÍT(g·ÇÙ1Kh qjôüDEHMúØõf?o’ì[F|âŽ[§Ô/›¤èNSz|¹bG"c JKKQQQ æcçw.ªk²`Á|TTT„?ˆJ°;ÚïDGɬÈÑZ7^å`@†É5«Éx°’ãWNdÝÂR%غ0"01ȺáDŽ[g›"Ä(*AI ¦}0½ÿ(n¹êÑ4­—©Í“Ÿ¼—sNÜ:%“ïOdi%L`9¥6Ø$E‚Ķaåš…¸íWê¡x5Ž#TWW£¦¦5µµ¨(/ßâwå#…¢°8;öDv RúTœQ·nvŠ4Ù8Ü”3¶ä¦5-œ¡‹ò ø¾–ÔÔÛ”¬uwÚG¶Cþ‘‰ãݺuÃüùó1gölô+’b{s–]èó „¨^àÄG† zIê¨ä "Gˆ6ðªôÐ2\[»g%ÂÅn²]h_ –TÊãlw̘Ë`¢‘)AήFζ‚‘ƒåØš´…/gwƒ#*9ù[€, GRÐ3È0(± Ä%%±~¶@hˆã¥ee¨¬¨@UUU¸q×þ^…¢ëqvl²*3‰-IƸ‘ÀœÀ‡Â[Ø \§Mæ”yEò§ ÔÐY”`F Én¤Ø í’’TUU¡ªª S¦LAEEºw/èóÞ’%E£má±4è‹Ó –(_òI&· ɶÐ*§Dn$ö×w", ŠçH;œM00(A â(FÎ0˜[ásÐ8p6DP‘p² †H_"K¡ÌlsHl+Ó†\ÒŠÒ¨ýû÷×ÁðŸ1%%%ˆã8´Ÿ©S…BÑ59;6ŒÐGÍÌ¢nˆG¶õ¸õÉ퀱°la(‚eß’õqG0€„Óø—`þš¾t£“Ñ;*¢(BEEjkkÑÚÚŠwß}Æ +Xe»3–]ŽgÄøf¦Ö}ÍaOÿ#!j tì–AÙ´1öšŠÁþÿ‚Ñ6ÄÙÆJŒØq¯aXN`…UH–%ÆÀÙ²Œê8;s¦ 3,å`LÃŒ!˜\ ôƒ°…Ŷÿ̨ç²Bѵ9;NˆÝúª?ï ØLðŒeéLaélñ€†C϶óC1r0ß0[×Èé]©íÈ ß§]S[‹$IÐØØˆ©S?ÄüóÑ»Wo4to@EÅö’ÜKŠ®AÛ¨Ôõá9µ’~K)φ„]aPJÙaqÖ^Vz9Œ(.99à ít”³™ ,,"ˆ£ìUðÐÈpm($'N’…À‰k±^Æ ›NwÚQ(Š®ÊÙ1û¬vr¿W¡}•oa@Ö:„ÄE¾ÉÏ&­Ó”w‘Ò½5 Ü”&ÛL¼N¦ãD±ã!Š"T”— ˆ¢+V¬@sS>üðC÷ÚÎÓó[s`IQ¼ !Ö d–}Ÿ!×k› tg¬qÄîC¿dœ&Ìßkݰ’Sà×A~‰°ì!•³ …¢88;vá3¾«ƒÂ #|Žyô ãò³”{ Æf–½­ £àH’²5òTmÅŽúáwC‘•ˆ¥•¤©© Í--h]³¹\ÖÚírn:°¤Ø€8Ï›Æk¾?€È`+³-ŠWÆÛ dÙy´Ê `°k%BÂ&ØJ)”=ÃZJ­œ­P(…ÏÙ±‘¿ ¢Õ3S”¾Ë Ki4¥¯Üáý¶­vû–’àøêÎ6µMX¢°’¶Ûq†ƒ***ËåÐÖÖkívSµu`I±aÞvìf ˆÙ9s¸– ³–"œ–¦V²Ž3­I·'oûáK—8ýÌ 3`È%›)g+ EqpvLÈÖÀ62À‰x3ØúAH‚µ#FÝð'BŒHì]RŽØþ…“—þíÌÒ#³³@ÑaH€àGí[2Ø÷Pmç›XR´+È¿­Ÿ@gRÄDña]ð>®üóˆ—©½–l2©`Ü^-”³ŠÿßÞ·$K’ëÊÁyeöFÚ€&Z†£ýïAª€k8fµæfd›ÝÛ]uN~"NðÏwüfÂÜ,ÊïÏEgîòW¤,K3¾f@Їâö±ç #ÂèìªëïÓ/ûɤ掆T°ßÍËÿ°±½ãŽí<­ÜT >UYN`õjÎ>ö0Ì<[“ÝÊ´ÑàpA~&@úQa5ðböwÜqÇï`öG†$ÙŒz1ýäc/åCÔ‹ƒ­¼|8»~3¯¤ÈlW£ù~õ§Yméô±È÷¼ãŽ;îø)ä®àƒJXLn´ 7ŒöšÁ³}hcÿdQõ` uÀäP6h0ø³RwÙ\BkŸë‹ÙwÜqÇ¿€ÙÓ/)¬ ê 2€¼‰¢öeL/W>‘\ZÔGе( Zo•ßËW[©ÀwÜqÇ¿38‚šbþ±,óGW1”ÄèÅ» æw•žKCá¤õÆ79Ó®´aWÏŸ\̾ãŽ;îø Ìâ^m¶mýpy®–« ½8,¢´Ô¥_Ô|§|^?X_¯“'/^ßqǿٓ½%·Õô[MOj¦Jl‹÷¬`f“åimˆ…“k)à û²d‰x—¯/fßqÇwüfô©bG*ÔkÏ)e´'ktÍŽ³¸§«L5ç»"=_¥¬™åŽ;î¸ãW€Å+˜t‡O/7©¾ª%…y>IºIÏxV¥ø‹škÀ÷†ô‹ÙwÜqÇ¿€ÙŸ(«(5=¦Â‘af„·ÚŠýe¹¶¾ÒdÞÉ[™Ü>í‰LŒÌÈËÝ ½ãŽ;îøÉxYÓèi®G¹u<æ{ÈÅN,Œæ&À3X ÷jOš,úÒQDïá%Rÿ\̾ãŽ;îøÌö¬NT 1Ø;xTø*$Š0i^ÿXuÆ­·ÕjͳâÍŒ)Þ žòbnæwÜqÇï LÇÐ?ƒ´×¦=¹j(6îÔ^ÝÈ·í+©@¦…‰N‚ËFÅñ“ÁëÅì;î¸ãŽ_ÁìˆâŸ¨4FU™weÂØEtÒàj[ç^±”ói<Â^ÓIÁÍÂoqäŽ;îøÁâHñG¢C¸™=éIM$÷¯ª"½™¥¼6)Ý®|ýŽ;îøÕI¡ÕN4_ój**] a2‚ÒÏ’"~ iPíÊyDÒ¦VR"ž‹ÙwÜqÇ?Ù…Dñ½K?cû%ûCéd€|ƒNïÜw´§+Û›0æ÷8¯F‹ïyÇwÜñ ˜mâû¡l¢Âõó)áÍp¡³æù |ÃÌóô´vá-ÍðH«>9täÅì;î¸ãŽŸÁl—‹‰ƒˆVª›Ñ‚¯}BuUF‚´—,_A·“H®˜à4/ F¥ñ0³âÝ|ÇwÜñ[#³ °ÒÁÆ ¤-¡Ìa1µ 2•ïoã©•ÂÝ«8:u¯ ÅŒìö¼~/fßqÇwüfê•Ìhö$Ù¤wâiÒîJ´n¨3ž„FZÈÅ›N§*É $ðí ×ï¸ãŽncÛ¹z ö¢¬\•æ(^`UMÊnïU˜BqifNo·iTú¤2^̾ãŽ;îø Ìþ¸^ÐaÑYî;5,ËáYj‡9¼8.ìR¼3J™É³‡< ݆ËÓ§ V”ÙIJ¿ãŽ;îø™ÊHaæþ÷&–_‡*Äðƒç—åèì#L$ÂÔ{lzˆ¬ü¼ÒÅÊ˵ÞéböwÜqÇ`ö'u˜(‹’"‚Ór4ëâhÏ@Z”ÚRg¯üø‰¸TåÄ1-K*žŒ·LrÇwüÞÀ ¶y”[˜]‹ ÞÍî$RÄ(T¶òk]WÕR^äfÙ"ãÖűN¾˜}ÇwÜñ+˜ýG%íH¼¹*iÒo²Ý‹µ‚áô©N2žQJÌ*žƒ†2-MçÜâÈwÜñ‹ m¬ ‰¡\X½©-%¤ÚŒÑø‡sýä$:vÂü© /fßqÇwüf ^=N«Dä/­7 •͉zãÚëóIe&a^o•‚LT²˜'ˆë ÷Û§;î¸ãŽß²‚zjSk,<ƒÒÁ“©c,OêÖÆF“þ­!j`ULj\\?UEÚYïböwÜqÇÏ`öeÞM²~¹hà°,˜¯ªZ‰ž•”æó•/á[ u•[¾Þý¡’ô÷îßqÇ?YÑH®´!Åê«iÛkU›Üí­-r&1&í㬔”iÆ×HñMD!ñÅì;î¸ãŽŸÀìf1ðøÉØI¾ âæùÅãS]dˆå,oÂi=ÂvRez7,)gôzNˆBú¿ÂÀ?³ï¸ãŽ;~³?X sé;•é0ði€Ö_íʕݛÆÞ¬O!&ŒxƒìߨÖ#{÷/«•;î¸ãŽ_!QŒÚŒ½ U„ FVä¹Ôí\T‹’SLi>u¾®Û’çô?³ï¸ãŽ;~³?bxGW6º9»öâµ›¯ì”,&<Íéõ9£wÿGR¢lTvrðí;î¸ã‹$¨t”pfÚŽ’Rl 3¦&­ƒµ'Y¶}ŠTïWJ¢áÅì;î¸ãŽŸÁlÇÔ?êÿQÖ%^oþš“µaÏ41S´$Òw5X¹ðX1ÀζšJ5|Šu´Ë'Ü^à&ÝqÇ¿†Ö†@Çž§G ‰Œ)ð&Ú=æñ1·§ñÎËaíÛª* Y®!¾*ÊA{H»˜}ÇwÜñ;˜í-¤±ôgþÕvôÚÞwZN6+¥ «"‹ÏE;ýLÔ±jƒHó(‘ÜqÇwüÄðŠ?G&("¦|0ÁÔn,˜ r6®ú?OðÄjc3¾ᆰn]š°øböwÜqÇÏ`ö'l“»9©¤`¨z8=Áõ¿ª¯ËÅÌf'_¼¿ B°²RAWPò‹s•çï¸ãŽ;~§<šÁa0Oè,¡¢A¬íž3ztµx¸Ò–Xɬ”Pø[êÞ—¨Èu\̾ãŽ;îøÌþˆå·¡3Ëé{ ¯ªˆYÀW‚h+X…íòuz@0Tš뤰O wÜqÇ?ÛU1¶ö›ËZñcï¹1¹ª+ë…m7•õ‡’.fNcÞ&th¿|1ûŽ;î¸ã'0ûýAqÿX5tZšD9Ì‚a^"UH‰zq7Fý;ÌÙ£*_’αmX 诂ýŽ;îø¥•6‰ò\Mk½¶nÑ3,ÔE¤Âm“¹„5Tµ [WÕ:¬”³ï¸ãŽ;~³?J°ñ°å,(;¨0Œˆâÿ¡Òsœ´×Tü€§ñàó˜šIÑÍêËÝäwÜñkcÙB…ž |!’–Qöyn°—•.沉ê—(7šó©* òg) )´ã‡UÛSâ‹ÙwÜqÇ¿ÙΪT4ïÄÐ.RYÁ`ïÏó-ßtnm®V®{•â¥\¯˜Ë]zßňŒ~ÇwÜñ3˜M³åe­ŠÆ ûP‰…‹a î»%éÌj Šºam3eÕ’tIwB!³ï¸ãŽ;~³?¬œ°ŒÂ™x¡k%†•=ÌK SÊwíÞÑer%|ö*mÇËÛ•~ûŽ;îøÁQÕ‹RÔ˜Œi E·h‡R¸SDqýÒÛÚ1›_mx»± š›gWèÔÆ‹ÙwÜqÇ¿ƒÙŸl+²Ûƒkßoff/ôâULÒXmñY惪~°¿ .u;,ý…IÎßqÇwüÈpÙ?©â¹±uª¢±œ@ÌM!è;-,š_me™—-LŠ+ˆ©N‹’Ì a€Oü¤™YxGY>föØÕ]¹e‹Ûú|R»_¾ßwÜñK˜íK™ÎòZìµâLÃÍÌSéÞÕa/;ŒŽ1ºÔïfäcÁ§DˆYQÞ2‹â2m½˜}ÇwÜñ˜ýÑqN#ò¡´šèÆcè¿Á΋WY„œ$L_–) ƒÃ9cNô; î¸ã޳átº¹=æö1]ñm'¥3ãM«€™´úéefp¯:ZÁ¾<@.fßqÇwüË1ûã(ysU`áf/õâ®Ð°çRŸ›…K­nY’¯9:IMqƒ…¹Y¼öDÖR¤Î¼ãŽ;îø…áðÜ€fxLâÃnÑ¡¹Æ-VlÕVLn_x…ÅD¹‡˜Ð=Ñ68#Žÿ{1ûŽ;î¸ãG0û“-È4Ú†|RiÍ3QO Ø¥²´JÁ©¨÷²8Q;³Jç™Eª8É:9xÕO öØÿúŸÿÛÂþXðµà›œ@FyÁZ[QA‹ÀQÑÑ+[‘/Û«©ýpkº€3DG,Ö!ñWÀð¸ÑžÒ#òÁ²¯ù²Å²¿þ¸«ec”¼ê+ûm¾qö1ꊕ“Í‘jûúØú®/¢{<2«ä{~ý9øõþá[r­ÜýÙ÷²Ïõ~fCÅ_'Åï‹ùÿ¹´Ç¯ãøÖû÷úŽ?µãOþé5×veýÆú>âo­?'æýŒvxCïÞsvDnýKœy+”ëÄömIÇm¬oT£ü÷ç}×ctÜ>³¿þn~ç¼<ßb~¶^¬§íŸçus‡ÏçèÛ¶z®s·þÉÛç3‰ïu¿­>´*e×ÿÀÍñ˜ãSÿþs>EÉnÞŽ'W΋º‘l¬iþ…3õÚà—Gv}Ƌٳ/f_̾˜ý;˜ýQV˜J Ì«ô[øÂån Àì¸ñ­Ò„[à=TÐB áÊþûý þ ûcäk4ã›ÿnoq˜-y€ €ä$Öwsz.H+ˆ–ùôè$ ôŒåâܽLʹ°9ÔZ|T×ó ¬\¢[ºšHñ¸€¨vEs´#=ûž¾x‘ì˪†ißXš„ÝÎЄ\˜ÊSÑp<‹yŸV „²›&‹ÏÕŸï‚ JüZ61“YWj ±Ò§ »¥•µÔpÕv¨¸@X×q¬Î¸–z¯“õ0kÁWµ÷9ßÿ°ˆ8ŸA׉<øµðxtæ›zñd£íØÀâÙŸ"ÃGð×2àǵßï;›²xÃZ‡¿>a º=æ_«AÏLü÷€{½Àòo>œ®¾–ÑÏ” 9Î7"ÖåGµùÖÆÿ^íkƒ³ÿ\Œ ÔïÃÜ0·'«ø˜ûcþ[VH ÙèM0zÞW7ýî 0ÿ¸Èç'5{×Ü_éböÅì‹Ù³/fÿf$„‰¨ Q&XÞ*wÔ .ÈU§€E”ˆÝh¯EÜi•B¯Ø_ÀžíG2¦ŒÑàVÒ!=Xùþõf}2››O7{ŒÇII 6§ñ»Ñ ö¬Är°2, '6$íÓ¨M6§ã¿®Ô>ó Zaæì‡ìÙg\LÍA§^Ç×:Z` ËkÙ3»A›s½jö“ôUÛ@^àGïimÇx‹ ,ò~)^ºæDp›¼U0ýyáƒÀ*´¿©9·––^Èê÷]@Û '¶À ˨+[4{‚ˆsîyϺ?ç‘ÿÉ0é}™y]}®{æÄ_¥½´¨k©? üg=O}-æ`Rl9dôµjdLœñNGÐÖón›þ@y–Î<â PÕäïÍ5/¿+k£²ßå‚Ç^Œgׯ{š2ñÜ Ð=ÅéVóÍÝÂ^3 ¡dm@ªÒëØ•À¸E´^«CiêÏdCFû\̾˜}1ûböÅìÂlꜚg²pödK°‘Š áQhn“ìQt#& ÞW;ðÏœ©Q¥ý*D«>ÿXT pè Ñ'[¬$¶™€Š¨1eûþßèÓ»Z1Tê§9&’ÓA ²Ö‘±}ÉpMFÀo|ê¶¢õih7Âæ÷9ÿ½ZpÇ¡Î倞q4ÙlNY è¼nrìÉ­( ¹ [ÐS-ÐeÍ6±Q-[¯±[ŸS]Ø\A×ÊÂUbÀw;õ:·ðU­ÙÍ¿žGåo©ÓçZè©ïWÛŠÉg5CÇ­¡5bvV,xTrQáãºë †˜M@c…Ïñ_MpØß-¼U<ÍØØªému}ß·þÃWÁuZ7–¹Drïqvk0„O5«Uê@µÒ±šºôic»µG©ZoV!'úªîõì¿5'@{äkª¹Ñ¡v£ •àÞt-=·oérÕ@͘×sañò¬SŒ¹ždµÿhì땟û1ÂíÁS–yùÿ¹©,¥:’¹œ—ÂÛNo·óu¿ŸY¯ïŒ³­…Žë÷j’rU:/f_̾˜}1ûbö¿³?(nKp˜FoÝLµ£gEž4U>÷Í«3 ”ÐÞÈ‹ëºÉõ{(ó“°×s{Í-ðX˜›ûkް`4¨42×ÍR …G`´Q\Ãu*Ú“i@‡ÓFrë6lÚ½D=ª©¼wV…F Ä}Š/á»ÃW­/=öÞÕ¦ášý­TJd¨ø2Â¥šðêœ9¿8g`/V”Ue<¨/ݨÍç[‰ÐÂ]Œé&×÷r|¦ÎpVË¢*6j·¤Í—oø^ôÕê}Öº+^Ú¤,墚íÆõóô—ÑNŸ.£[Å… ´ÝÞÌçÿÉ­ IDAT¨¦ØjßY{U]1ËVÓóÂHá¨6@ª*WMiÕVoŸË)Â̬{»Úx<—>÷¹¶8 ^—(p,‡¹¹YÕ(&׬±çCúâ¾h™¾£K’w;«OúÌ­ö®.Ìz ­G~jîswÝk“·7Y5S Qâ”Í÷­¢©×³ãUÕ¢­Ífã÷’º™ç¦| þä»/à ó™¶*0‹d¤‡õ–T^z†Ã4}#ŽJ§Öxù[4„ÛÅì‹Ù³/f_ÌþÌþ «]°ŽˆýHx·ˆX ×§{…`Uö|D}iÅ…¹=íãJŽÂ=§Õcí9bØ-",eg7C‰E¤‡áY•„E…Z>1`àÙ–Ìââ¨ÖGÕBiqKó¶Ö#©ÏFž„.ÔS‚åU»Nâ RQ=(œÄzU|ó9“#¸ù7«‹^”TE ,Õ€>qv†Nb\5±ê$¨“&aéY|·{ø¹TÙâTþ¥Í)XϾ9oÝ'ŸÏ¹„Iïz€giÁÊÂã!Šù.MxÍé‡Ù4¬¦P¾šwkÎ-’geD•…U%‹©#v‹ø=à×TÃéJ×nnª­Jè™Y·ÙOõ¦f!U\`_õ›ž£i©öéÖ|Í|èv·Ïs=/µ9ž¤Þ÷Ùg¡ò3‚=ÜvŒó/Ð$X\V›g´·ž!ß‚'ç?+r`])ÉMg‚1ŽÅt/ˆyÏÝÜÜUÓfT íMugQâÁ™=¶hFh.¬Ê µÀG?tYÙ,­gU~ã÷böÅì‹Ù³/fÿf¢90Õ>ê4M½YvQRvGO¿èJB Fg)Œ 4×G­¹ ú ë ÀøDÙFå âe>¤^ß2¤„ïSPNy+.a¶¤Ä)¤Y<ýù½ 6æø Ú{A)€)ŒˆFÜÝhÚ»ˆ;:E¿6ÊŠ5o„-íµ¸hOÜúé™0ÍaÂQÀŒïÙo›cº·Q¨cq ‰¬Z~û„›§e]ӃݢÍt¸jiêN D~¯¶Ë^_–úÕ¶ÑÔêì]}ÁŠ‹6VËgÞt9*p]G/»ùU G·Üœ+µï`³ðj9GU¢8|ò‘ tØØ2Lé@×O-;²õ)zÙUS¸[¥ÚT¨ç#D£Õ<®,FšDÛ \ÇS•JšÙSÇþ§Ú O]S&Øz‰¼>‘¯í{£%)ðŒUECKXH|¢¶æŠ_7lXÎfÊž™UmÄëµÔ<éŠO‘Ì&ÔâÖ`Y+A¬*CV¹¼ªfvˆîpHõÖ¼¬káxz{/.©©:¢0ƒ]¡â8dhã´Y»A½Dü5Áwнì^̾˜}1ûböÅìßÁìK`GóŒúQe^_d÷h¥6»%&¹4yR÷áÁE¶ŸDµ¨œVÞ†nư? ¹#ËùõyòDìÛÞ©ÚX§øÁû,O=uÓ’_ô´½•Ú¢ù/Ñ(îuoÐV$1}zŒPï‡nä§TµS…`ML¸Ôß…àô檺°T)õ¯¿×IÙ}Ô¯\xuÙfµhE:¶Ê^‚†üïð˜vÓâ?=æ"U‹1T¨'%ªòó¬qEŽ2Û}X×§'oÛ›)\ ÐækO5‹9ü£Ç¹Úë£G7¤I¼ÐœúÔZËbܤšO¥pă¶ÆBɱPJswK%‰{ø,ðîs,Î=Ÿ‡}òÿT>V€[‹”ZËνnwæLÍôT…rá¢çæÊ1­KHx†È¿óU¡,1Ô>Ç;|]ìf,gcôû=UOSmB§Ý[”³ÃccnöØcf«9²Ep%¬#Åós|úûaªÌ–ólzl½o-ÄËgBB¹¤ D‹‡TÊZؽڋO9_dUD …7^4‹ü  Í\Á1KH‹ŒP§·p©…IûûV%íböÅì‹Ù³/fÿf|Y¯Ð17Z--ÔÝ-±zß(®`7±ìN$S˜¥1YÊw¾ùhøSØö0OKæ^Êe¶|*1hq•EZÕŒåI)¥4pú„ÎÉ)úhâæøc¾¤ÙÄß““·Å£”O«¨štU5éß·b˜ÑØŒ:õGª ¯Z2U¡‚QʆÈb«,üT|sq™¸,—tb ؈uŠÅVF+ðB´Xþ“ÕšÕ£|¨RÞ6ƒo†YÍú¸$÷j·‰¼+Z†·Ÿ8/jà–2é ÿôýY^¹¾dî03.Ï`µ}ÛIDζA+°rz'JE‰±ˆñïT… ”9ïØZˆTed?äÐÆ…l@ˆZ@ú›¯Å[$SmÛ°.‚²0jðŒ(Êsc¶¡‚!°Lji†OÞ×]ájŸiUê'šj©•ß²cµÙíâÜìëŒL2t½j£Ç P[šŽ¡Âç"ù '.øÛÀ5;3¢_¡ªø›ìøˆ–Ð=ÑâÐ.K7ȃ•˺j6m2‹ 59¬Ó=ÁˆZ8ÊbaÿÑfôböÅì‹Ù³/fÿë1ûã‡@!º5jèX-¡¼À:/¢58O¶Ô:}öfÞÜè5IlNêPy_þ„.Eýâ,ÁЏž3$[D>|@z´—"¿˜_С^ŠZ«æ?ùgG_jË;•aže%•GVr´ÞaM¥ZV-›R£2«6¿YGV þt%‡“!€lëÄ|£ÃbG\³O=Q €<#UÐï?ô>¥<Å«’Ò m÷²¼ÉIërõg±ÞW¼9Ôýxºý;Šz4¡©5ïe~ôäIµyƒÜ,Ò:½æÃj5÷ø°UËS©ÓS}þ>ÝW´´¼CŸj#éìì˜jZ|QhŸÇ(Á•õ }B%Š¥õ¸ ƒN›o 5XV ­ZèyüÆ ÁaÙf_~¡Ál/Š/‹®” ÌUÅ£ç|€Ø»lUF¿Ô¬ÅŬËè]‡T»¼ñH¹œ¡ìâÜÛ¸Œ«5kÝG÷ÅE)õú™á(’Ây‰Ûª"ÖÏoØ'I„ÍÓ{Íð…Ä=ôÙxb|¤Yé`¬ÊF},¤PÜV_6mâ­úT­X $ù}³à¦ˆ/Ÿÿ-ÈèÍO;¸™ÅÛï‡z?_›À‹Ù³/f_̾˜ýïÇìO«k·y}X :·Un1B95­Î´‚±iÝÀNOØŠ fÞtÖ)I<¨ç›ö.ŸÒÅ)’ F÷桸i¨öºˆ€ÃKÊàu³çßV6‰…!œ´ùáHÕÿЇmï‡=ŠwÄ•äîe¾Ž•|¤±®Óî3zñèÿódoXmNUÁ†±Yž¯T3œÄÀNwJ­½Ý/} ‹X–_;…-—x„/G4yn·-YœJoŽÜ$U­jCY éÁVÅÇe€"l2•¸[†0¯VݳAˆ8c±PÁ*thÁ6È/qš* ÖËW"Á®`=ÅÝQ^ V¬56>¹,²qù{õºž“º±X2 •ËjV0¶ýR‘ ñtb¸~õp©èôn‡–&0Ib,¤¦dö°ótÔÃÛ*EOŠÎ†Ñ<ÇÀĈ¦® 4ÿråäŠO¶^ë–ÍM7JºYæò8Å9yr²~ ÄÆÒ'o·!ŒB_ÖAj}Ž fZŸ.Õ8|£& w»Ù»÷ÔB6÷±ÔÄjXëºd•!_/ýqß®f ÚÎÍó[éU:íêLŒÓQ\ÇØùÓÖK%›w‘Èl7vQ‡õ“·oî“Í$<Æ‚9ýØbt]Ž"ïÊã«Ê’Uë°xgQ-Z‰Jä?m74JøP%hY]=bëÊ‹v¨ùQ‹Ûõ¸Ä>†Ð3‰W«…²€ª.b‰_lªKiïÅÿ{±'J좸‹9³žn3æìjÝW3[—¶|J¶C¶¸ßrÈpËÖ±©UßY ǰk¹->s{WAæw^¡/‘…¾[<8ÏT{÷“…SxQÏ*V(HóK°…Ú¨ œU°1]̾˜}1ûböÅìßÁìùYmŽBȉ"€àRübN¿4®ØØu¢õT¬§q¨—Ø´\”¸‡€Ÿf©…ž ßÉY‚àýåÒŠÍÃr©åa3Á˺& m¬É‹•B†i—´è¤8 a•¤Kº½*ÕºÁ2™Ǿ¾šý¸æ?^ŠlU—”è6ÖV8ÒÈÔBc·{Ñv¦ö%›jW/nØÛ­FÖ‚ œWjõ‰aîS%j¡Êá㹌{ªŠ¤vuÀìó EB”Ô½ÛžåíêcjŸà€þ­ö7ƒü¼ONl` ,Ár [«e!õxŠwˆU-ô==Öâ¨ËˆraÏóóÛ±®^o¯c¯ö{«²(i3¤ð\ Ÿ‹Yñ‹±jk+3Y&æ1 ¨UûL‹ò¶ ³áÔ5,¾!±—,T‡›,žòâ-‡‹Õʯ’Wqðäú€["î5ÿ™I ˜ J/öŵs©ÓQU5L¦ÞÉ1(;x¢“tøQyVDkÁVÜKU,Õæíe9T}Ï÷Ò¿½èg¨ycÌþôænhâ ¶÷´,¼0–f³/f_̾˜}1ûw0;©#Á&Ûï3|8Íø|zHÊò†KIº9rmü®Àƒ²šñÀLN«a÷½ÀQˆ>ûg4º“€ëä‰:©9llnB™ßÉOO½¾u›)ô»mJjóÖVÜûzÄ#2q¼š¿ç+öõµ§¬‹¤jU˳ãm÷d[‚áXçvÔ5G2X'¥å£þ¶Å—*$K}Üñ ì(Q=<Ô‚FÎ÷%ð>) tt?ÉÓ…6 v' ®‡~µ~­øOâÆ-®žm«¬=WòÌí£³oU¯25œ”0pì´$ÈɃ>Y›qÕ×ɵ8\Tõž~0'ˆ¡–1—¾/f±•²š‹ñhk1UbZèM]–A´ðLc¸ª)(Aº6W.N]ýN0&"y%ÈM[{&HÅm×<‰ß$mÑ-ˆ¯J_OëÊŠ€[‹Õƒf#­{ͯl«ÇÄI7pç<}:ûÍfÎa?]^‚š©Fqí¸²Õþ¶7´b´WæXœ hIˆdRU/æÆµyŸÙžvLÍ_¶Äzžf-ò™!£?çÅì‹Ù³/f_Ìþ Ìþ<ÌнÚw:‰Yµ ž²vzõöå_ªò}vWL¥sûæÙsnØl¬ñ~íQÞ¯˜X^´²´º‹föV’)â};ø ­¹‰+Êöû¤Èa9=ž{$Y ªZRV3œ˜%rÅå¶R½^«ŽTŸY¾´Ám' ÄPG–O¦YÀÛ~è_«¶á«_Šg Ë+÷‡´·î©?É]{eª^\²?Èü·§šAýBXΕHiâf5Ò<ÿ1øR†/áPZ„ñhuæ> „'X²âá,ëÞÕt”ìzjT÷åÞZ¥/c7/‚w«ü-m~ ÈÞ^Lѯë»VCvTôÛ‡äl?Rí$µw9¢ç²ß_-ÛO—cØU¬·’Ìp$¬Ml°·È¦Þ¨Xë £pFÍ 7e©)9Ð[Æ”L®°“µq[› sëWÃv®Ø¿ rh“ t3ʵ@s7v8bmz&¦wRíV5JB2gW£îyonš§Œ ÓÀÚ$É2¡^\Øï°‹mY°ã,ˬ°“î›×UœÌ ”ìláŽø×“”8 FníÅì‹Ù³/f_Ìþ÷cöGàâô‘Ë–‘6L;JâJ=m&#LKÊiŽAe»À‡±#S7ø°œk(±Mäõy‡W3'DB¸”²;ùë¯x)½Òþ´ÁÿJìâªvLºÚn_XÿÖB¤“‡ ùìä¢ÓXùHÖQ¼«‘³ª"ØrÕ·i Ù²ôâ²rç°:ðÃÇäˆ!ÝþZRªù€Ûj}*ò䊢SÚl§·¥,Jp`Gž¾=Ý&å\}[ùa/ÙßAa;ú–ØÖ[ÿœ7Ư:ÚTZ¬ìï4ây²«?ZJ0ÓÜQ¦ý4¯ª^´ø"êBW*wpóù–m›ÍËæR­fÚ°I\Qì×·î·PΖ(¹ª%6:6ÅW]™ 6¸°KÌB ^ú`UôöžÚ“-~¯­?q|»Â…GË·ãqw f˜k„!%èŒ8.1žØ¢Ó(Îë:±\®X~ȶ®­6«,á–8Ô²½“/ü]̾˜}1ûböÅìßÁìOk—ø©š„¡“¨—xE'é´ym56ï«ø~uç6H5ËJÜ$–ò×’ÖÖ*³ °[;:u O^Æø1qºjñ5WqÌ{lµk¸*)PÒÖ^8¾TäFY+a‚€ÕZ+µpÝrYIn J ë3ÉV»•‰™ðŒQį3r¬vYú9F‹H<ê¤ìÑíçLÙcrlWr˜/7U6Øêãë‰[&Ì5iß]¬Ö[%,J”9½"¢»y·ì¥: Îcî³ÁX–GØ ë,ÚèA°¥Rn¸oD V€”jÎùâ…±[Úã?<–X™Fö%ŸZâ«S+²Ëù>X‹wó 1I}nhA ‰i7ú<Ý$•šx{mÝ´„m´Ãíaݯx¶^݆f`g8ÃÞÜÙZ0ÚW®+ ¹2FXY–M+Ô(7²H  tùXönµ±òq=eŒIœÖUÕ$¢kÌA!àl^³^š‚¡†[óL£ F˜´8‹eÆ}ÏouZ¬\.Çâr¢ñ¾){Ý¿˜}1ûböÅì‹Ù¿€ÙŸð!ª;%þ°ö—tœ§ÈV™êB TW%"¨X$–%S èìÓ‚D\ï„¶ÿÏ6”·PB‰;:•ÇN–æ§_Kˆ{·¦š¾6Ç1c­& ȦM8B\)`«`àRSOk–؃Œ1M.ÝÓ~“úýG‘­ÝlÞ[?<1é_[U¿ZÉûÆÇB—²Lk)¯ãµwNs! ”ƒkq{ncMÅm25¯Õ lʪî/bÁØq¶¯@+j~¬+ Q–I¾NàÁÉ‘Úó£MjKAnË+tûLH6mͱmÚ‹Àâ«•-VB™c‚BÄ…³Nëª &+þfÎêÕ"¾ÚƒÝzTzžªžâÖ-ˆ(•:&ñwüCk1WU«ŠÁí`aKœ! J-{zƒ“¼zŽºŸ;Kt†ñ†Í=”/áõœwøÃ;‘Ò²ïÂrCî¨\)õY 0&:<–š\k`d;ñcÖWµ¹Uºòzöˆwb¹Ã×2–<‡Ú+u"£3uöÎä7²ÒAöu ©è/f_̾˜}1ûbö¿³?Ífápîš[_m¿>µWRÏ[\(õ [-ì\ W‰HÛG•}z_ Ä©«øÏ5 u*¦'…'ƒ¼ÿl´ý¹N¹J¼¢:Õè†oÊi¹°?ãˆG\‹ÈA |qã½µ?Õ«øT_B _|Aöµ·eócX§â²|Š>t¢*(+è+WKòõ$;ñ¬=xW»§}rmBèè¶Ïôc†ßÔ';cµ×jÒ“]t Íï†äêLí èë$[ʤi)šÐxx~²žzUÂQ;Ôì°Ú£"_æu6ððÓÝznçt²OÜ™¾5ÐaslWU.z1žSðÎÓÂ[­ø¿èdµ€.õ÷ïjã+?Qâ™¶<ç¬TбõÖÅUeûŽbyðZ{Œj¾—™Ñ¤bUœê{Eý2ö†H\â'c­”kC]©x´"«=·¯¦T¬p0vJ®!há˲-–—sWrØ­ÓbûÖwy[UŽöŸV¬t4ýÂù˜ñ]<Þ Cl—¡ Še·õ¸÷ýèJ-ÏX•ѧ4÷½Y»˜}1ûböÅì‹ÙÿzÌþôÉœÊ}_IsX 3-'*Q‰Ë žo·kÔct®–Y—ÿcðƒwU¦JÁ> ?CÊ“ÞâŒqµ4óÌ/7y÷‹Ëœ$ùV}O 5X)ašÄ-Ä¡½€°¢9YG%·I¦â0qú_ ‡aeµZËò'8ü ubNžß, ý:5õÂû¶("Žû¸ÁTú›[WÀ-bÂ8Ís¼^­°â»¯6an‹“æ è0-¦2Òe‰´úžÅ2ôç®D,±ÌF‹žU4p­n ªôýŸrˆ¿Z˜â ¥+(vc]ı‡êx¿ÊöHÖw[SM”¥¼L¹ûóèÊ—gh&ÕE‡hÊd˜_µú%ó":~ eË$ÏNJîMÊŽ<®Í@œ×úhé9âT1|Q–/ÿø ~]Óñ†µÅ»;õÛL•IB°gebW¬ÛˆS5oR-sØá¹œÏDVŸŽ+ûú‹OêmåôxÚré»G;I”…Wm§m½pr-dX­c³è:9vR±‰´rÆ@cÜÐ Ëg{.f_̾˜}1ûböÏ`öçã˜öÀŠ¿ð™BF ÐË|Ô­ù›™E|åÛ³«›Ó>-gf”àR[}I‘ÖÉÅ5³iËé¡§Å/`ÚCŒCØ¢£‘/a ®Ö’à ú”¦CgŸÌ1qe²€ò¶`»Çn'Ñ9Ûu[îµËWÒF4ÁnB-ýòR©Ôo½Ëþl§ ˨>ÛìxØÀ(ŒG°Ã3{ª*Š7ž[¹c_7ç+¿ó»D¹ØƒÌžU²§C6ß«…Ó-œ÷“fW΢S®†‡5±Ò [ë’÷)Ú&°jÔÙ‡Ê|k¿TÕ¹ÀF‰Ò4¥- ¦àr|°Q–cE#â°m!ÆQT/dÈwêTànyÍ>ß¼2IG {Z){´^¼{“Ó‚ÌU9k½¨o%;×üIš÷óJ¨lE8˜g<¢ gSÁXîçKZº æ‡ö¨ŠÚB>¬gKØ6+”¯ªÕ™|u%êi¾.oyÑ)VÉqïöë¡3¾Üšã@4t ]̾˜}1ûböÅìÂìç©ÊFÐÞxÓX?Æïq”<Ä7¡Ç¸y|ÌŽ2–ûÁ<寪X¼2[¤\¢83h%é<Áv¤›m¾›c3qØç0$ÖÉ*Áœ¤ £ûìÔ(Ê[g¥€QÑ´cá²'’¬'L¥,åpE<`r§œCú·±Ñ-°}6É];X€‚ -1òJÙš3®Ùâ-µýTÖâÁoßœå(ÀQSGMÚWµyâ÷¥ŽyùŒÌXÊÔGDµ« ™uÊTVž/cdë”Ú5',«ðµ8Ø_B"¬¨áá—Yù¬rt.áÔkýë>¦ØÈüwÅ8út+½oÑ ƒFW}póU§tÐ`Ó»°nƺ-höø§$ÒÕM_Êk+å{Vì©Ís¯j*zó×-ÛIÙ=g,O»¨í61µ±JÉ—à«„91 ]'â© ¬6ö¡ Ÿï¥¢ :Õ/+p/³jÓ9qÅ=°†ÙëJ<·½V»ÚöX;…hã9€]|Ñ…KcfaÏã³/f_̾˜}1ûG0û/ÃðŽuT>ø>ü, †Ú…ÕºlïÊR’JMõª‚ñxqØ8§Y_d~ÖéÈímÕ|? \“['º ™?é­™W¶'Þƒ³=z°êä-"»¬‰b-Lu-¢¢Zu &ì³*KšÜ±¼Ll›)E„ª•ª6Äáëk°Ú7[ÎÜí7éb½Â ¢ Ý—ŽM‚÷a¾…9oûîÒíðTuš…§o«/‘OÚoaø ÑwG1ePÝ¢ÿ 3©½æN Ò»tµ§Q eS*•/¿PzWºµ{¨ÅwµçJµüYó_¾ªJÔc{›òàî‰oÕNgd"kÞçç«d¦ù¹ ³Zd`u©›ó1Wlv,ÛÓèR”>µÀ¯Ý±!Þæ²­´ÆnÍpíÊ…â¢Û‰c>›¢SÍcÂ¥Å_sÝ|Eÿ²ÅYŠ€˜xknTQB%Ï»ûìj£ëû©R¸,Ù|*-ï"».¯ÅCÑÊÄl¶$šÚmsx1ŽÊ:5`Ãã,€G°žÂ@›îuÎw¸•eu§–n‹­dËWŸãböÅì‹Ù³/fÿfô!OÆ6Íì ãkõe¦MÑâ„NÈAë"йö(E&¢"<}Û†65ÝXYQgL¦Õ­Y>‡U»÷>ÆJ— •@[èåͪɷb6›;µj,VÛ´ÅošÏ(sürúÔdQp³+D«¨–+Æ.Ê öªJ²8s£·ÃK²»ž!v0µ úê§q*<¸d°ªüÄÄ'gëi€i‘! «í•@˼jª' z?I° JPЋgøšq|Fç:Éø·¿'u.ˆ)^é\5_9"•ÝFËJW˜—ò½ÝÚMa^A rqX@¹À¸OϰT<¥1eݵ¢} :6¿qùk°¼[Ê4¶­u/—‡ü~ÏxûB~Z.ÉL×büØþ 8Úö:¿/ï0Òèo7¢ðUÁÒl!Íì™ Í#ÿWDý™üËÇ¢.0Ö3õÄÖ¤·‡²Oë«&'ñu9މÎm†j‘ZÙTµËÂNšc|MaGhN_(¾wåæy]£Ñ ÕuwyïŠcºc®/f_̾˜}1ûbö¯`ö놥`}2EŠoŠ ‚Ãòò4Dd€IDATj ¸MKñ¥U›kì”Þò%E²ßÍñZ•–×£ò¥sÈ À³Òˆ˜>Þy´eO«´m'rmÿâ³:´8`‹½4m´j×ô-E´Çf·ô*| À¨S›¯ÛÉãÏÚí\ÿ:óJc‰|LÕWî|M¸NJjŸÙ<GyÝ¿Ô8„ÖvU]Õé6¸÷IQœ7_XIŒãwj6U9ñ1G¹ýåOœñ{{Çæè$eaÅ ½è»ÙªÖœM¯ª—=*fj4Dj£W0QÓ$Z¼Á®@ØÙ6Õ`•FÏVYU0Ý¢[}^UO"êÏsB íšÚª«SþÇÏØ¼á䮉ë‡Ã9 ª•g Î-޳©Ò8£>ú–11×@x„<õ¹Þ£ø!Þg^@´0¶µ“îZT•B ÞÅÖ·™ýaWÅÅ—m–Þ?²Ú«mh=½Œ ÈØˆ‰W8)‹±læ.f_̾˜}1ûböï`öçxÐ{®gíóäd{965ü N°åÔìÛÕÂóV£º­ GþuÓÇ×òß]>‘XÒ†7jÓšÃ(è[BÃ!¬c é‰ÉóT– ° ýi§½6¬1Ù[v[R´û×:q sÓ&uÊÓ,cñóýLÚ}»*m!}G7·ÅyXïXÝ—EU(F„@Œñ<¶"«ÅLQ€Å'ÛgïèJÄö}gêïôN|GgõÆÂ¶ûgÏCrÕÞV¬jÎJãÊzóšvðæ°cù±®÷y¬ŠÏNãÒÂ釰U¤¯z¡ýšµIåt|ñä8FrEd¨*±SÙVXA®¹ƒe·µù¡<ž ØØOlñýàó£ß¤ÇâlN€—×m7ÝÚ½¢ zÛ‚k[/ñ†›ù³øv™¬$²ý,qÍ" PžÆã)=çRÅÏ&ç°*a…©ØQQÁV÷ËO™[Pv1ûböÅì‹Ù³ÿí˜ý1ÊÜp¹ÉÀ³7þ¨áƒâ¾ûG\j·ÄÔDTË$lÙ¼W¼§-#v§ÖíÚ%{›¤¤¥t¥Æ‡Ã‡‰ýeæûħ ±m•4Ú”1¥—-d³„¥/÷R…ïØ6Öõ\"ö\l»";Ò¦8‹‚==y¥òÝ>ž#ıVùOœ.§½ÅTÀ²Z8£:_m&Dß{ùJª£¶µ+=­yZ~ÈúDª +=ë;|b=*Ó„Uhvç¡> M«êN¬ï±»Xgßoþ<΢ïò Æ‘pþC2ôZ’§#Y~¾ª(©å5AÃéì˜èv‰(>î±s89¡´äiŠ4ÚFV…ì'û«â¶#gÇ%€‡Oêö0°Å£KMœ ]ZCb³Õêe·Ë+w%| ÄÀ8äí´åza\ fÔ¢Ç3.Ü,¹¬O½q˜ªžqF™Ër¬žWÇꤻåòµUÉ,÷÷^",‰™$6ÓN[aÔ,Ö.ÿ\̾˜}1ûböÅì_Áìˆé`€òLþ¼* ŸäÍ9iñ¾¥JEÞÇ"Ç:!Ûšlå°÷Iv; kȹÈIg T¸Î« “aÏPòT]X7‹x3ŠØÆÑìÍÖŽ™™?ù`2ŠÓSp[\½(¾ úâ/5p+ Íb Ì[pèðÅÍ“xƒF0gè^Óòd}Hu˜ԋ”ošhL¶ýœùªjHˆ„1ª .å¼þÛ¶æéu\9§JÅhId3q©vÌ™<¦G]jµ‘ìðôt { ðÿ,Ü~hcì´Ê˜Ç"o«Uµ¬m¤l§íÙ!ni.eÅO{5k·ßhs W›Ýj¦}Š£¹OÐøv*õjï/ßáô¼-[%øùÜ+”MÖaA´8ž4T•n¢l'¬âà4Ech£e¹Äêïy‚Rt‹»`6¢"Xäsè Ë 6¡t/P®¨ÜÚ$:RäÖVQÉMU¢Ú6_ê ÉJ0vT‹:\ÿPMÇgVÁH{3®zK Ú!CÏ‹6>å,¡Šœ0ÎËFO1y(±Ë'×hîQüÆD÷‹Ù³/f_̾˜ý;˜ý±æIò {ä;*f‹"yÇðF‰Qæ» ƒ^œ¶}Œ/…iT:—s9~Ö©HÂFŒKa°­ŽXG¾®ˆT_L‹ó§’Ä8êpÝWÎýÑÁã- óö<]ÖYzÐJ«ëâ%8ꊛ÷NÃL0Gö9¾k‚ ÏN^ž{ÊúVí¶¿+毡½tÙ bXt‚Tã²Ã,ž#D­.ö^\-ÐU }êÕZ-¸ØUº爥õ‘fã4µ ìH„§ç«NÎOGýr-ŽXv¶R(s>‹„@HîPÛ¦ˆÛ¼«|^1ÞÃÆ‰¥Åj7m¯_T²ž:`RåGè”Ìeîo;†a¥Ce‡vhË€þ|ѪûÃKU´ƒVíûÚE›Ú|RͧõV¬ä¼yŽÆ»ÊSÕö Ó–16r¬v[òi½TߺVá«9Î%TREŽÛ[%Þñ™«ªZqxÈ­šä¡Ê‚m<~·FjUlq¥O‹ÞúùÏØ¥…B\Š JróXËÓvx°nª„ÞHaÇÅì‹Ù³/f_ÌþÌþä):“Kq¬ˆL•ú£O‡§zš4ó×ÚV%êƒÄ2ÄWË*¾(aHùÁv©¾XLƒR-°ÿxƒíF§è…"óÇkF³8e6• y}FË_¸’À&ýª½'1Œ¥¦~Ú&É÷a;=(Eª'§íS'²ÝòSŠ’xnò£äæk9š;Õ`Ë:€ÉDYv©-ç8ÁTjíƒ'Ö‰Vó~Ðv¯…þÔgðõZ1]3µn148`Ÿ+7£I°Ëã‹H!8ž¡­ˆ÷´Ÿr,L #ˆÆ:Ý}øbËç’«ÅÖ•µ¢c÷sÑŠõ\ _ŽE–mÑ gc¶™ò´,Q‘!gOÐW[t%Óa”öÉyle{taöú\æâm.dL«‹ËÙZü3â…Ðs ñ(ÑÌŸn©ÛòY%½EKÚ,Œ"$p¨Ê¡ëÞ•ˆUQa¬…žôܵ#rY}ë@ªó½måìLÐÛª-N+-ĉÕàß¾Èó¹­a -ŒÍ Ž“OÉUµ*§xjÓ:–xcõv,QUq­…âböÅì‹Ù³/fÿ f:-ǾÉóXÐFåf­îÕCħN—R©L¯É¦ 9 ‹¿µ}H}•ZþS,•pûrÚ'ûruXD lÀã…ÂVµÀƨ?Ô6•Z7lU3¼“»ü¸™8T´ÝöRrÑšÀÜFK t”1–Lü ¦Õê}¼'ÍšÆò‰ìÚFÑÎ\äœÛÞº[²#ÂÂz¸Ó°àGa… °ÓØ^iuX à:õGgxo&8U³¸p¢oÏe€cÛŸƒG¢ÜJ40ûŠ•5ìN¦5ÉáÂEîÓwʦEnLàZ­¬-¨Éj›—×+»%§yöå {Pãà£ö„^´Lö5ßb²*9²L"—°f‹Þ¸Oê(5Ó1ÙFp¶Ï§q7ü:6HY+×½\ ÁG˜åXi_æ½™ãR¥—êÚˆaWɰÚЫR1Á#j¦mG¶ø˜ÓâçwÚTi};Tê]™b þκÛ–J;:®ÊàÅì‹Ù³/f_ÌþÌþöûíàX¶ÝOÈ·µNïí)0ó–?0¾j§°=ßõI£~Ç,½¢|ç ‡MC{>V{ƒOD4øÛR‰ÅTáXy¶‚% ‘è£ðÞUƒò*® ,sž"î/â;W¾ÀÒã4ÔÈ fO¿i=øTÊpv%¡L†â°€²%ÌÐûNxCWf–žW¾“ª_©QG‹Çgÿ"%î0·­CvW#†"7¯hÛ¿ú6a·ºxsTÕ£-Æ´VròŽiµ^õÝÁU Qº !£ýu×=èÖ|‡9œ"ÙþAB[he?3ºîÂiæ‚§òyÍùæEÿ³¯6&„ͶµP‰S^zEÓ<,½~w°Á>©ûj‹*Ä„#ÈÙìC½ŠïÅù¨¨U%ÃÎÖ#jáB‰ð°Ljìð Ñ=—UÓ´Â_ßáÅTð´,[Ù8c¹U=‹Õ²Ÿ„ÄÕþÿ LšN9U²ÕÆïÐ]ÊvnhrzˆúâO ­¸V w&ÂyxÊ«&ÁØv“¸˜}1ûböÅì‹ÙÿzÌþtôjŸlž¥(Ž:N\m®|{ˆÒíóLEÌt§€fÛæôÏ(¡xi;QÞ‹7ør}rìÈW|Oâ0èð0D%ÿ m[Ô> ¬’Ã(™Yd8€npHU¯Ô3[-›‡Ø1j{.³ô¨ÎË’§Y{jµmU‘ú9'µ(Û¤jÕ5ò¢ õiÙÀ¯XcSÝæä¸gj/¦ïˆ1z’.+¨Ó§À<ª…ó”ýÓRã¾ûð)!JôëÙjl«™Ô“y‹2êôëm V Lò™o‰£Å9WÞ%f(ŽÐ'UF´3“a{~‹SÊÂ)6gs/²Û¤›oÎVd¸…ìÁ<¤¾“Ä´!pv{°yh´£:¥V)»Q³k!WâYÕÓ01Æù÷QIj^#‹'ìÅb@3ºò“T·(ÿàªÂ4gÍ×Ò5³Ó‹ßÖq\ Ü »8’âVëS›§ÐÍÈ´­µÁ[œÚPi»VðômνDaXÔÂbÓ† ’‘Uµ{Y­Ù§6!vZϦº¾‘7@ác÷®$9=´KØõ˜’ôÒ?—ý.f_̾˜}1ûbö¿³?m×Z”1;º-ùXÆpY)%çû$˜à¡“ iÆ7&éŠå)ñA?à‡ÍÔ€^Të£' wL«u[ªsëÉIâ2ͤÂËÿ2Dó3ª\?„4Zç)—£)Zú{Ýüxʧ2úS‡¥˜Ë;‰,TOŠ©v°}2wsÆ»êð¦ÛüªÎŒ·äAîZÕ³i×}î,9‘¶D'ÓP¬èVŸÇR·O«ubV¥…»L³xq­w°±hÚí2pl¢öB•¬µÜ–xŒÛL˜z“˜~üÁƒÜÖGdû2Ç +þš+“*¦êB™ à0îô½!¡*“uòæ’Ш۸ô807ªÎÀû™cúïwULëî™™IÒÚB¬¹ÇÖÕƒèÏÔ¾ÉUARõF÷6ù|ÑU:¡^ifnbD}X\UÆX:1žËfVÉ)g ±¦ËΘžóÕ–fØpdcÝ{ Ôè”V^•R¯èß|°*,¦ŽªÞKD}’Ê—났³òÏÃ.f_̾˜}1ûböï`ög äÒ#:应§ú{¬Øn!ÊF¥€ÍáöÆ€Oð¬&%®1; òÛú(+()iÌàÄðn>[·¾OžHQÉAĈRÜ“/Ôâ†nAz‰ƒêµ"õsŸòˆT‹àm‹¢¬@„™¹‡j>i%™…_¬Œéþ… nˆV ?ÓF¡/ïÛX9뻃5I½'†±”Ìu“úšÔ.á"“®u´ƒ¼¯ÖÜ)è/Žè€`N•8Z„õé+±é] `³\,+CvfãÉ-ËÑä/ã…G­¹®4yW›¶[w0–A½sGlL]‚%rx–»½UcanM؇KpF[-ç§Öø eðîË-Ûªj‹µ f¾*Fh¡œ“Æð ûqðó£±aeqç­pŸ…QÖ—Ìéúù®†òß ¯Ê“\Ê!Ûp¯Á£•ÜØ×]$ ­Öœ¡¿%°òéÿëÓˆáyftõid›T¢ö†‰v$¹Ì½WêXï÷µ³nó³( ¹yû ¿8º›ÿ E–X¶l;ÙïböÅì‹Ù³/fÿfÿ?Pü«˜¿eÌIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/popover_menu.png0000664000000000000000000001156215074673150022673 0ustar00rootroot‰PNG  IHDRHå1án·sBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timedom 25 dic 2022 13:28:20¯1›.ÒIDATxœíÝ{xTåÇñß9'. w!$€ÐÂ}m­uÕ¶îÓÝ>¸­»KñA¡ên­îjÕ…¬o…»ÏÓú¬m­«ÛumuQ¨—ºÞo­­%@ !᪂( `“™³ÌLræ0oîÌŒé÷ãsžI&'çrùúžËœHH:ë,.¯¯— &®áí^éMÄ,ߣÿc@²¸JF×÷Ø-=‰˜?~Þ÷½oÛ=Ù èpôÑJ4M5êN ý#FÛó˜(ŒNw6z!}ô‡2œàyïc‡2º¸òD£DÛ÷¶í{ž$€dqÔÄØcX‘™¢Øi$»2‚ôýtÔHo(]X6ô… âÛBЦwTÙé.wg#H½“£ö8fH.i”¤!’²»°lè+­’š%—tDÒGÑçE"R¤eÞ]îXÛŒ‘ìjÄüq̈®8CR®¤‰/¿ôÂÕ…“'_*K9r9ƒ É,¹rÕT[W÷Â%_¼ô!I ’Õ>Ðkõ}FXè(d–â1zG‹±i´¤i{÷Ô>¤H( 4N˜Txµ¤*I‡‰clòïzwµ; ¤÷,ulw:ÆLIC%•ìÝSû˜8Þ ý'L*\"i‡¤c’N«=’±ÝnÿYî8¦@úÏNÛŠD0#ú8@RIC]Íã’rúâ_gAÓÄÉS+ÉSŠœÌi>zOæ$EvåRï.vlô8êÅß>•ˆ#€ô–mÕ(EÚ;»Ú¦C¦@ú¯uô]Xø™/÷vËÄs]7%SmÕhµ÷+6àó_Ï}†ŽÎbûw³c HjÛÒÏ¿®@Ò¸®«Ó--jnùD¡`0©ëveg TfV–,«ÿ]€bÛ¢È9“€Ú=†é𫸋Éãtå:Hÿµ’ºa×R?übÉæº®B¡V…B­*˜0Y9¹C“ºþ¦ÆcúàÐ~…B­rœŒ~I7ìZ’*~÷:6ux©O¢@ú_sí?™,©ï*üYr]W§š›‡UXT’’mÈɪœÜ¡ª­Ü!Û¶5 ;»E2òOñ^žè?é}Œ‹Zg»Øþ Äc»Ú6mz/ «¥¥E'§zStN^ö7Ô)9@ŽÓïî5ÓÞ®3'ã(ÒÈD·3‹{‰!}zÇuÝÈË­A ÉÉMùÉ’!9¹ µ#¯ÁsÝþ5ŠŒit¢3 C&:‹èÕ3è”é™ôV:žéLÇmê=o»b=ó6.á™lnI½¸ãN¿ü¿ DݾÁu’¤ëv%_ÏÉ×ètíPºnW pÏF -P¤tÔã@òíìß>=-¾REÓ¦è»7Ý œœÈ›NœÐºýX»ª´ññGS¼…œÅîW2=ñÔ&ÍœÑȧ6=§œœ555Ežp¥¦¦&=¾a£¶íØ¡£Snî}vÁ-ù»¯)3¹9ü?,¿V@¦~ùÓŸ´½ÿÙ󕕥߿»Ya7¬K/þK-þúßž±ES¦(33Suõ ž*¨|G…,ËÒ_]r‘žyáE•—Wè¢/|^ï½X;¦ÏýÅBÙ–-¹=[wss³úåÿ¨lë6…]i|~^Û¿7ö³‡µá7ÏêÍß½£#G*?oœý2Í-)Iºõ¶5ª­«Ó½·¯RÑÔ) ƒúæ·oÔéÖ ~¼ö^5B'O~¢+®½N%Ó‹´fÕŠÞ}Ãâ7]ÿ…úÙÃÿ©Ÿ?üH—æ½vù2]³üª^l×ÙS?N•U5ºí®µºsÕ Y–¥ÛïY§ú½û”Ÿ——ád?rÑ…¨¢²J»ªj$IU5µÚYU­¿þÒ%qóefлe[tÎèÑ:oÁ|…Camzî·úßÏt¸üWß|[›·–«`\žŽ?¡_?µIeÛ¶Ÿ1_f  ES UWß I*¯Ø¥IçNÐ…Ÿ?_’´uûIReud÷º´dF¯Ö½þõÊëojØÐ¡š>uŠªkëÎXÆÏýo=öÄ9Ž£Ù3K´§¡Aw®[ßöõZ8ovd›<_¿¦'ÔÒrJ[+¢Û[S#×u5oÎì·÷lêjôzÇ$ºcå-;f´öî? Ûî^«Ûî^«ú½û4zäH}åÍ©ÞÿãéÅW^SAþ8­¿ûZqã úÖ7¯’$=ýìó’¤…sçH’vÕÖJŠD}ØÐ¡rGÛ¶WHRÛöΟ=«Ãíí.×íÞtͲeºfÙUÆå]³|™®^vU·—›L#†×]«¿ÛɆ}û5jä­Y½B£GŽLîÆôâ2Ÿ4ÿ"Ψ‘#tÁçÎÓko¾­_{]›·nÓÒoü½È·Ùþ'EFGÏýß˪ݽGǛ亮Ž78ãûê}ß¶9Ž\¹*œ¹ûLcÓñ„? ¥3‹ÛÖ3rÄp¹®«’âé’%Í™U¢WÞx[u{TQU­±cÎÑÈQÃ{¼î}J’fO—íØråjÈàAž¥¸jØ¿_ápX³g–´Ísþy õÀÏÖþƒåÊU~~žÆŽ­êêZ…ݰÊ+vjþÜR>|Då; ‡´³ªJycÆh̘ѽþð~?zâšåË”9`€xð§g<ßQ<Ïövu‡ãd(3Ð~k‡@F@@ mú²Ÿ¹ìo¾"˲ôà/Uvv¶¾|ÑΘçÐûïëö»×©aß~]írýÇþM@÷þ0e†ÓñNAþ8 6L•5»U^±S@@ES %Isg—J’^yý-}pø°JK:=v¶îP(r·ªì¬,ãç´´œŠÌµ=wêÔiY–¥¬Úž›?gŽŽŸ<©šÝuª«oМY35Þ<ù‰vìªÔî= š?7u»×~W.ù†¾ýOÿØö~oã˜LkÔê»îÕÞý”Ÿ—§ü¼¼¶ŸÍ5¦zó$È~§`ÜX-˜;GápX—~ñ"eggŸ1OuÍn5·t–Šg)gÈà³r«­Ò’b555éwK¢)…ÊÌÌŒ>?C¶më¥Wß$ÍêäøcgòÆž#I*Û¶]ÁèŸ+hnn‰›§`ÜXIÒæ-å:gKy¹\×ÕÄ mó-ˆ‡|rã3²,K3‹§kAôxã¯7lT8îóÝ눞_Ârå’źfÙUÑéÊ^-+™î\w¿<¤ü¼<­Y½BkV¯P~^ž:¤;×®O궘p»?‰þŒ_½t‰.ºà|M›ÿs}{ÌèHP^z-¨Ý{êÕÚÚÚ>™‰Þw;˜'ª´d†^}ó-5·´hVñô¶ù²³²U4uŠvVVɶm•MK¼Œ.®{bAЦª²ºV·¬ú&N(л›·ÄÍ3>?_³g–hëöºå{ßפ õDz- º|ÑWÛ–YTX¨!C†¨lk¹fMSö€,eÈÒ¹'¨²ºVÔ´)…}óó߇MêÓ“1Ije}Ã^;a¼n[q³†åæJ’Ö¬^¡;×®WýÞ}iÑFýÐÈõ`îl 4(áÇ‹¦êò˾*ÇqôêoiÔˆáZ8oNŸoǬâém7]Y?JœW…Nž¤öz]ÿú/7há¼9úð£TßРë¯]®áÑë,cnýçëô¥‹/TsË)••—kjág´öŽÕÊ3¦mÛ¶5?z`άö?°0º[=»¤¸?Þm;%ž~ìÝÏš¶8JÒ°Ü\ÝÏ=ýØ#©Ú¬8‰nìýÓ ±KfG§’KZXW½óþdm$ÐEþXWH'š5}Ö¼ToŽ$iWùf ÎÉ•ã8ýêŽâ“§ÎøŽ¤?J:!éIÍÑ)ZùÓ q~$p7 Eâõ¥ÏoTòOפ/F`ÀYl UÒu¨–®Û•üM eÒµDéº]ÉÇí΀4NwG; ¤ ™Ž8‹ ¤HlGÖvhjÔàœÜÎ>å¬:ÑÔ(ÛqØÁöà$ *®dÉR†БÞKy |ðž2œ€,Yü~Gq’H‘Ø Uì G@†êk«4ꜱI剦Fùà=2 [=ÛÆï8Ç ²mK’£S§‚rÃ!Üß p(Ôéçõé68Ž'CáSR Ý&HH)˲dÛ¶ …B–dÛ²ðY¹ýœiý–m˱m9Ž#Û¶ûÕk°{‹@)‹¤dÉqܤÅÑ»~É’m[Äч@iÀ²,9Ž•ô8z×3õü2®lú ~Ÿãf`@ À Ç»Ø÷Õ÷åv@Úéq ~þâ¾ÜH;ìb€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€  $H0 `@ À€@€ ] ¤ë{?Ü×g‘¿Yþ¦%ÔY ]ßÛn‚À§AXí‹é0”2Q½|ZtÔ0cϺ²‹«nØ3…z¼™|!Å7¬K{Ã2ìyŒ-0$v³|ºxÛåc‡-ËHðœê=ö’Ô*©uà Á7HÊŒNè²E¢kK²zþo€nñîåÆ:”t::µF'o$ý;cW;Q ý+õÆ1¶â2IYÑ)É µGÒ—HžXôÚqjcKtŠ2Q$2Ò[ÔDUŽåù¸#FRÃߪÚ›‚ŠEz#™0” MôÆÏû¼7–$€äI´·TünvGLÈt Òò¼[¡¥øðÅ>æU: 怳Í;Œ0¶«ôMþc‘ÞeÄéh;»c)>’±ÅžK´kM$[¢½^ï1ÉDqŒÍ›PGÇ ½»Ñ–ïcÞƒ¡ÞÝêØqINÐH6Óe‰ÞPzOÒxÃØíc±Ù  ¤wÔè=2Š,‰.KLô—n],ÞÑRjß½ö>[¸—š]kéÀÿ’Bý»ÖÆ5Í=ïîs¢(úI,$K¢{Gxßößl§Ó8J]‹˜?|v‚ç #€t謴7‚‰u5f¦ãŠo®\ßcgÏŸ¡§acÄàÓ Ë÷~€dûA[÷É &vIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/images/textview.png0000664000000000000000000004543115074673150022036 0ustar00rootroot‰PNG  IHDR­G¼M¿sBIT|dˆtEXtSoftwaregnome-screenshotï¿>&tEXtCreation Timesáb 24 dic 2022 22:00:08§¼Õ( IDATxœìÝwxSåßð;éžé„RfÙ{–‚"‚€lDpŠ 2‹ ¸Pe(2E øŠ ŠŠ?öž E)£”RÊ,¥{'ÏûGÛ¶YOšNî×¹J“sžó=ûî @DDDDDDDDDDDDDDDDDDDôRc{Ön›ˆˆˆä ÿ/’¢ä~|‚ˆˆ¨ô è¢ÀO)–ä †Ýßuÿ¯´¤ """²*MîOÝ Q0T Ɉ‚g”:?õ™Bˆˆˆ¨X¨s =¯ëþ4ÊÖÌ‘ë;Ë ,ðe×y‚ˆˆ¨ôÙàQ`Èû©AαÚPh0"Ì9QðìBÁ`ƒGB7HØ™Ñ6¯,äyùC…îY “—4L(t;< ¶¼øpàdFÛDDDTü²¤Hp@\îk6È jäëu/iäû †sòÃmîˆm¨ÔÚ½ëŸÑõêÔé Ü!øQ™¡€€@╈ˆº=Ûs €ëðèDAv!40ÁØ^ü÷8èžmÈë*huíÊä """*ÛjÖ®7@8€{È y]ÁK/e ºOYä]®È ö<4‹ºve#„àýDDDå…B‘U³v½—„ˆ‰G!"ï²FÁ§4ò7a¨iäºB‰œ›"ms:hqy³p·ÊÄQ‰@b@úÃ"2s³evîOÝ›-õž…0çQKÝKyg|wîø{$ÃQù¤Üwîø{$r€°Ç£ûóž¦4ÊP€(øYï¨T¯^E-žˆˆˆJOî±¼ßóNü¼§BŒ=…Qð2F^ãv<J…„Õ¾“ƒˆˆˆJ˜B©pCÎ=vxtïƒ9Ç}ü6•9ŸQð³l8 PðYM""¢òK¡àŒü—/ò:£rê ¿ó¢à=yõ¾”ˆˆˆJ‹î±½à=º?óöÝDYðìƒî¥ ~ÏQÅ {l×÷Õzº„¡ïëº |„5Ï?Uº_M¡ïÆI½÷Aº„QðÓ'ír;{mÇü@T®Ä>xðñö.åJˆ¨Œ±×ét?•Òú¿¹¿ðŠÈj^?ââ ¾?¨?¼:tp‘Æ‘‘‘ µ:ŽŽŽP*s®$N}ïCDDFaÒ¸7ÐõéŽùúŸùÉ\\ ¿Œ…Ÿ}‚wg} ¥B «–ÁÁÁ¾Hu˜2e懈ŒŠ( x{y¡j•*xö™§ÑñÉöÅ:n"*ž€ Ê/°Us$%§®FDâ^l,š6jww7@êU‹¼Ý,]½‡ŽÇâùsP£ C» DDFáÔé³è¢ ’’’péòUÔ¨^ 5k¢FõjP*°µ³-±í·CûvP*¸uçÂþûç.\Àáã'1sꤪ€ˆŠKÎ@0Bé7z”öÿ˾ý»öÀÐÁÑ´QC¾ŠºÝŸ9ÿ²}[løi BÏ_@vvlms6ë“gÏB£Ñà©öAP*ørîÇV¬Ã¼:Ç¿1ÎÎ΀+øì˯qüTö„R©ÄoׯreÔ®U×®Gá¿ðËhÞ´1àTÈY9†Ž;;{ü°ú“uLÿ`6®DD`ÞÇï£QÃúÈÊÊÂëoMAfv–.˜__o¤¤¤âå7ÞB³&0ûý&§»^:1üE,Y¾ »vï×cuäÕýDP qüÔi(•JôîÞA­ñÝúq9">Þ^ûÚ«hÒ°@£Ñà×ßÿÄÁ#ÇpÿÁT«Zà D›VÍ­¸$‰JVõjUq1ü2>üt>æ¼? …º‘Q7PÍß¿Äë±üqLÁŽ;£ô¿þÅ’oð÷ÎÝhP¿.‚Z·Â™sçñÙK Qk0fÄËpsqÁÏ¿þއðíÚ•‰cG£ã“O Fõj€žÝº`èó´mvh9s@ffBÏ_@ÍêÕP­Šÿ£z`^í[.†_~é ““‘žž³aa€.^º ![µÒ?íz¦¿]›œv£oÝ2«Ž¼¶ö<‚³ç/ ZU<ŒÇ?mÁ” 3+ Þž¸}_~µ ™™Y€V¯ûþ666hÕ¼®E^Çœ ñßÅË¥¿^°cga7kæ4Tñ«„¨7ñáÜùøpî|DFÝ@%|4ómËÛ¶?ϨEÞ¸Ó¡çѪE3¼=a&ƒv­}·îÜJåŽQ¯ GZz:fÍ[€Ó¡çÑ»{74oÒO¢fµª€ÝžÁçûkÛ}2('@œ: »ðÒ32С]Eu´kÓðß•+€sþƒ§‡lllzþàß‹—m[µ0{úœœàää„´´t¨Õj“uäqqqÆò…ŸcÎû3ð€~€®OwÄg½¥_ÌCõªþxŸ€˜[·û ;÷ìCõjU±ðÓO0cÊDŒ{}$`럛]+QYãíå…¹¼›"¢oâúhøúxcö3PÉǧÄë)ÂM”Eˆ-D ‘û/Ï͘[€ÓgÏaÀðùúMJN†€À3OwÀÁ£ÇzþªøUÆ+CkÛÚvóoƒ~~¾¨Y‘Q7sç6Nœ>x¢}`¡mU@˜¬£aýz¨âW —.]Fhpî¿hÛ¦%îÝ»sþ…Z£Æ¿ááð÷óƒŸ_%ƒûƒ‚ÓŸ™™‰ôôtøUö…ÒFiÖü¥Ò ¥õëÔ(lÚ÷ëÕ©ƒè˜[HLNƒ‡¡ÑhЪy3(m”xê‰vXöí÷ˆŽ‰á¾‹Ê5[ØÛ=zŠÊÎÖvvv¥²^ó¢äêê hÓªF½<4ß{ºAx{zäþO@¡4ï[gžl„Ȩ8uú,N ͹|aຨ9u´mÝüý._@Däu êß>DhØ¿ûï"®^»Ž~½ä¾”÷ü¿ÿAšÕk˜]GAy¯ê²±yôZzz@­Qk_ËÈÈ„B¡€£ƒƒT½DeÉÃø|ôé|ÜŒ¹¥Ý¶oÞº…?]€ÙÌ€§‡ªDëá=ìØG—§Àë5ªúC©Tâòå«pwuCU¿*ÚÎÎÖÀÙsaØsà0¼¼ÄøûHKM)ŽQääìO/_¸{zš\iY§iæÖy#ò*jÔ5ø~y˜€uš£¢ÕYÖÝŠ0 TþX=@!{ï6R’’PÙ¿:ÜUÖ…Q‰ ñ¸{+™Yéð©TÅà Ë:­[§1åeXçãY§1œ†¢³Æ4PÙdÕ!„@ÂÃ8¤$%¡^£fÖlÚlî*¸«={àÍѯÃÎή„«"z<ܹ{kÖ®Ãá£Çð .No?>>ÞèÓ«ƾ6ªÌl‹yáÁÑÑ#_Žž=º£’¯/îÞ»‡ÿíÜ…u7áç_ƒïL .ír©”•™aì/²vÐ3T«‡J…ñoŽÅ€~}K¸"ó=xð6n‚B©Ä„±cJ»œBJâ/Jk(u–‡ó”§ZMÙðfÏûIIIFû‹}€õ?ü€ñe`[ =¦ +¾þ M7Ò¾W­jU¼>j$‚‚‚ðÖä)ØòÛVôx¶Z4ãåŒÇY¹¸‰2ï ·êûµ¥]ŠQñ øtþ„_º\Ú¥àÔáƒz»/>› økÇŽR®¨âY¹æ;¼óþ&î?Ëȶ¸å·ß#_ž/<èjÖ¤1F¼4ðËÖm%V•Meæ&ÊS‡zmÿÁC˜þÞÚßÿÚ±ƾQ¤Êò³ì⦾Z`þÂÅøeë6œ; Ô+JaXï"lç§;Èùë§do3o\mŸêdV†–AÑÉ͓ҫ·bÕin}ßz Ë¼iønÝ|·n}¡×׬øvvö˜2ýÀW_|ŒÌ ¼ñÖ%µ-šnÿLh( ggößãÙnXõÝ÷8}æ¬YíRÅUf.aè“w°Ë“³¡•]Ñ7o¼½}JµŽŒÌL,_µ;÷ì-óóŒ¨"ع{/V®ùNï{övhÔ°>V|µP§vmü~©$Ë3KBB" ’¯¯Ñþ*WÊy?>!¡Øk¢²­ÔŸÂÈÈÌÄŠU«±s¯y;kÞ-ÛÖ­Û·±tù „œ>ƒ§(•J%Û´.Õ:—­X…Í[~±z»Eaî¸N2ï/Êâª]¶ÝÒª·¢Õin}–¶_æŒã«eË ¾7yút,_²uj×\¸¦=!3Ž¢0§}•ʱ±pçî=T«ZÕ`wîÞ×ö_žP!Ë•úˆå+Í;Ø•¶‡ã1vÂ$ܽwÏh4€Êݽ„ªÒoçž½€5Ë¿As=79u´ìt1éW¾ªu‹عg/þ·k7^9Â`ÿìÚhÕ¼EI•FeT©ß‘w°Ë³fùÒ|½ Ž-nÛ4óÛúeëVܽw­Z´Àg³?†·—W¾÷}½?mùíƒÚZ¹F¹:¹;³lu¶‰aËÞ=…—·yNÚoÑp…Uœ:-©Ñzõå)/óÓÓÓ0ñ­7ñÁ¬Ùzß[òÅÔ©€ˆk×uj`ñó1rôX©qéö‡ ˆ{öbýÆMh×6M›4.ÔOØ¿ÿæ<Å¥P`È fµKW©Ÿ@äž­V—R!Æ]¹Ø¿_¡ðÇO†@n€(]=Ÿí†?ýÞœ8¥´K!z,tïÚ7cb°òÛÂ÷Adfdà¿K—<}`ñ󑙞QÒ%šÔ¼Y3 4?ÿºoM™ŠW_†žÏvCåJ•pçî=ü³k6lÜŒŒŒ ¨T*T¯^­´K¦RVê"ï`—§¬ôêÕ­ƒý‡á£ÙsñÑì¹zûquuÑ›ÚKÚ¸7^ìܽ÷ccK¹9%óeÑ•‡:ËCyÊS­†¼öê+ÈÊÊÆ÷ë7äûÊê7ÆOÌ×_þ3€¯OéÞt­+xâ!°å·mXýÝZ¬þ.ÿ£ó …žžxø0ã&MÁН—ÀËÓ³”ª¥ÒVꢼì^ú"nDGãÀá#HOO×ÛO`«Öeâã]ííí1yü8L?®´K!z¬Œ}}Ô¯‡¹ó>GbR²YÃôíÕ³˜«2Ÿ ¦OAg»a˯[qöÜyÄ=|Z·h!ƒ¢zµêxkJ0"®E2D<æJý) ;;{Lzk&½eÞÁ®´žnprrÂì>´j›æ’i³ÝÓ¥Ú>qp¿Tÿ–2wÌ­¿¸ê–]~¥UoE«Sv½ÍSë¯ì¼îôÔShðýwøný1òQÖ¾>>èÓ«'^9¢L<…¡«Y“¦hÖ¤©Á÷—/YŒñS‚qõZ$ÆN˜ŒåKÃÇÇ»ˆURySêg ˆˆ*¿Ê•ñþ;ÓK»Œbãááo焈ˆÈHL9Ö|[ÚeQ +õ§0JWÅ«óÄÁ}ÅÖvј7óë/®ºåÚ-½z+Vòë­\ûES^öÆX<=UX¶d‚g¼‹Ê•*Ë8¨lã""²ˆ§§Ö­^QÚeP))_¦EDDDe I+¦§0Êǵ0ÖYrÊË4°Në*/uÃi Òg ˆˆˆHšÕ„£³ ’Kÿk^“àèìbð}Ö)ÇTÆ”—i`r*JÆp¬§(Ó@e“U„B¡€Jå‰ûwo[³Y‹Ü¿{*•§ÞoÉcòŒÕiLy™Ö)¯"Ôi §Áº,*»¬   \ÜUpvuEä•ðRI½É‰ ˆ¼gWW¸¸«´u±Îâ©Ó˜ò2 ¬óñ¬ÓNƒõe¨l³êM”J¥666p÷ð†­=îß»èëÖ…IŽÎÎpWyÁÙÍ 666P* g$ÖiÝ:)/ÓÀ:Ï:á4XGQ§Ê.}1P™ÛÙ°Ëíœr;g®Ú¥¦$/Ò× jµZÛi4¢„>¡L”Jlll´¡¤Ë:­[§1åeXçãY§1œ†¢±Ö4Pñrvq à€d©Òr»¬Ü.€&·Ó²úcœ …B»’ØØØ”øãCy§Ç”J¥Ñ•ušÇÜ:MµQ¦uš§¢Õiª NCÑXc¨l*–Ï(­UwüæöÇ:Í¿5Ú(ÓÀ:ÍSÑê4Õ§¡èã§Š§X¿ £¼¬4¬³ä”—i`ÖU^ê4†Ó@”ïf!"""i DDD$ÍâKNüD1""¢ÇÏ@‘4"""’ÆADDDÒ,õêÕÓ~@ˆ¾îÒ¥KhÛ¶-¾ûî;ƒm4mÚŸþ¹ô¸-®,KOOGjjj‰µgÍyhª­ŒŒ ( DDXÿ#tÕj5&Mš4lØÿþûo‘Ûܲe z÷îêÕ«ÃÕÕ7ÆÔ©S‘””@ÿ¼5µ®ç1g»)Š‚µõèÑÇ×Ûï‹/¾ˆéÓ§(½mêöíÛ;v,àää„Zµjá•W^A\\œYÛ;ßÍaj›)émÔÚ,Ý Îc™uŚ˧¤˜Ú§eû7GQÛÒW_q­kßDyæÌh49Ÿj¹xñbìÙ³þù§ö}777“môïß­[·–·¥Ã•eŸ~ú)®^½ŠÍ›7—H{Öœ‡¥¹<¾ÿþ{ìÛ·aaaP*•ðòò²¸-!†ŠsçÎaÖ¬YhÙ²%C‡ÁÅ%çÆá¢,+kl7ƬíÅ_Dpp0233aoo¯í/##;vìÀž={”Î2ÌÈÈ@÷îÝѦMüùçŸðññALL <­0½\Kz-«*âþW—©}JY_núê+®š-º;:'''ØÚÚB¥RIµñé§ŸZ4nK‡£G¬9Ksy\¾|¨R¥J‘ÛZ¹r% GGGíëèÖ­[‘Û¬³ÝÈ8p Þ|óMì߿ݻw×¾¾k×.x{{£mÛ¶Jg†„„àêÕ«8{ö,lmsvE•+W®Ð§Š ¢ï­¹Oyå}‘–#7^ª¨  9€' Ÿþ¹èܹ³((00P¼ôÒK"((H¸¸¸ˆ-ZˆC‡å{Íš5ÚßwìØ!…³³³¨S§Ž˜9sf¡6‹2œ±þÔjµøì³ÏDýúõ…‡‡‡èÓ§ˆŒŒÌ7Î9sæˆÀÀ@áêê*Úµk'NŸ>-/^,7n,ÜÜÜDÿþýŽ{÷´ÃdddˆiÓ¦‰5j___ñÆoˆ¤¤¤BuÍŸ?_( ¡P(„­­­xë­·L?kÖ,Ѽys‘••%„"))IT«VM¬]»Ö`{Ææa`` øì³Ï .+có®`[YYYâÝwß5kÖ^^^âå—_ÄÕ«W¥æ‹©å2f̘|ÓÙ¢E‹|Ãfddˆàà`Q·n]áää$êׯ/6lØ wÅÐöoìX'S_``  çϟ׮]ÇUªT)))BãÂP}ú^Óe6@è®h‘‘‘€¸páB¡÷ÄR©QQQzgª¡vÍÎXéééÂÙÙ9ßA199Yx{{kÿ"-8-§OŸDLLŒöµ… jwš B©TæÛI=zTøûûë­¯à6gøƒ wwwñçŸ Ÿ|µX -+SóXwØ´´4áèè(N:¥}?--M»ã’™/æ,S{AuêÔÑ{"w#ÊwiÖ¬Y€¶Ë ‡†v ß~û­7nœhß¾½HKK3Y‹¾í¦8–{||¼ppp'NœB±oß>Q»víBõç-CS5ÄÇÇ ;;;ñï¿ÿ !„xûí·Å¼yó„‹‹‹¸|ù²ö5Ý3†$&&Šùóç ???acc#†*BCCÍž2ugee •J%Ž;¦·ÙQÜÛhA×]cÛ¬©íP—©ùbl_aশ Kö¿ºÓZÒûc@µ>}m¥§§ ±nÝ:!„uDÁù`i€(Ö/Ó*¨V­ZpqqArrr¡÷5j„gžyMš4Aß¾}1zôhtíÚÕd›æg¬¿k×®!++ mÚ´Ñöïââ‚öíÛ#<<\ïx7n HKKË÷ZÞ´]¾|ƒ Ò~MqB« IDATMVVMN“¹ÃwìØC‡ÅsÏ=‡õë×Ãßß߬¶Í¡»¬Í^6×®]ƒZ­Îw[÷ |dæ‹%Ë¥ û÷ïcóæÍ8räbccq÷î]½w#®^½ ___ÀÌ™31eÊÀĉMŽkíÚµ Addd¾{(dÇrW©TèÑ£¶mÛ†   üöÛoxñÅ-®A¥R¡S§NØ·o7nŒþù¿ÿþ;NŸ>¿ÿþ“'OÆž={°páB“Óëææ†wÞyÁÁÁؾ};/^ŒvíÚáĉÈÊÊ’Ú†LÕ‰¤¤$š¬ËŽš»îæÑÝfMm‡ºŠ2_ÌÖÔvaÉv®;­%½O1‡¥õéãàà€§žz /^´Z}úæƒ%Jüs ­Ä666ؽ{7¶oß<ÿüó0`€ÉöÌÎXéééP«ÕÈÎÎÎ7ŒƒƒƒÁ¾éÐ}-ï.ò'N 22‘‘‘¸yó¦öQ@S̾N:Ðh4prr2«]yÓ#³l222 V«¡V«õ¾/3_,Y.º’““Ѿ}{ÄÄÄà£>¶mÛТE ½ýººº¢V­Zؾ}{¾ñ¨T*¨T*888˜_—.]àææ†¯¿þÚd¿†×r2d¶mÛضm† R¤ž{î9ìÛ·ÑÑÑÐh4¨S§ €¿ÿþ±±±ˆŒŒDÇŽÍžn;;;<ÿüóØ·ojÖ¬‰-[¶HoC¦úíS0EUœÛ¨Ìº«+o›5µê*Ê|1gXSÛ…¥ÛyÞ´–ä>E†%õâàào$Šøµì†æƒ¬2÷AR;wƺuëpäÈüþû‰±êpúú«[·. :¤íO­V#$$Íš5³h:jÖ¬ 77·|$S²²²¤†Çüùóñå—_b„ ÚY_{Ö`Î<Ö7/uÉÌ—¢.—Ý×dÖcÊL€ˆ‹‹ÃÚµkƒÔÔT8p...ðöö¶ÊpÆússsÃk¯½†qãÆáÔ©S¸{÷.¦L™‚J•*å{ôM†Þyç¼ûî»Ø½{7Ôj5¢££ nhÕ«WÇÁƒ…””“ëÕjŒ5 ï¼óÞ~ûm´mÛÓ¦M3Ø^QÈ,777Œ1o¾ù&Nž<‰{÷îaΜ9Í—¢.—*Uª !!+V¬Àýû÷±iÓ&œ;wÎ`ÿ¯¿þ:ž}öYá믿FXX¢¢¢°eËAŸ>}´ýšþãÇcòäÉØµk"##qåÊÌž=!!!}:Ôj5èС¾ûî;DEEáÆX½zµÉú ¾Vp>XS±ÝD)„®®®âøñã…Þˆˆ}úô•*UŽŽŽ¢E‹bÇŽ&o21w8Sý¥¥¥‰I“&‰ªU«ŠJ•*‰—^zIÄÆÆœ–ôôôB7$ýóÏ?¢ZµjÚß5øòË/E£F„‹‹‹¨]»¶X¹r¥ÞiJMMýû÷®®®¢oß¾&‡Ÿ?¾hÚ´©ÈÌÌB%\]]Åž={ ¶ghêû]ˆGËÊÔ¼+8lJJŠ3fŒðõõU«Vï¿ÿ¾¨[·®v^ÉÌSËÅÔ OóçϾ¾¾ÂÓÓS øàáéé)²³³µ¯­X±"ßÍÅjµÚàô_ºtILš4I;___Ñ«W¯|7¸™ªãÿûŸ 0«ÿ¸¸8ñÊ+¯___¡R©D§NÄõë×MÎ;Cïç6jjÝ5µ5µê26_ Îã‚ã56¬¡í"<²ûß‚ÓZ’ûSÛQë &LÕ«W¢_¿~ùžPºsçŽèÝ»·pqqõêÕóæÍ*•Êh}ú^Ó°ð&J}çÄ”:!Â.·sÊ휸h'„Xd´BDDD¥G¡PLp@2€Ti¹]Vn— @“Ûi•™KDDDT~0@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤ÙZ:`ZjŠ5ë ""¢r„g ˆˆˆHIc€ """i DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHI³ø£¬ >Ùz›=„F˜7ŒR {ÂôƒÂZ…P‘p9‘9¬ >Ùzÿü—fõ«B¡0ï0"„À?ÿ=p³úY«*.G""2‡Õ.al>öÕ*{š}Ð…Bj•=±ùØCk•AEÄåHDDæ°Z€ÐHtª¨làíj…BaðTù‡³ç }§.…º·&l733í;uÁ͘[€a#^Æ›´ïgdf"==Ýì:`Ô˜qøã¯¿-~¿<)Žå˜gïþƒ˜:ã]ô{aºöìƒoŒÅ¶?¶±ââ3yÚ;øhÎ\½ï½?k6–._  ð:fLÁ~§u‹ˆ*«]Â`ö5ó†~vø¨Ÿ'R5˜¶åÑ~ŸðÆy#ßkJ¥ù¹§ÓSР~}íïë؈蘛˜óчf·ñ¸)Žå8wÞœ Ř×Gaâ[ã…ðK—áæêj…Š‹G·.Ï`ÉÒeÈÊÊ‚öõÌÌL?~ß,Y ð:fŒL¿DDe™•„é#ÏÓõ1­‡ìmðpRbr7Ž…EìßÞÎ...×ôæ¯[<ìãÊÚËqçî½ =‹k¿ƒ‹³³öõzuêX­æâйcGÌ_¸gBÏ¡]Û@íë§NŸ†»J…F [Ǹ>QEaÕÇ85šœÎÝQ‰Eƒ½Ñ ²ö5èßÂïöò„½MÎ)ò„4 ~=R¤qªÕj¬X½^†î}ûã³ ó½¯{ ø‡Í?aí?b÷ÞýèÐåY|±ø+deeá«eË1ø¥—Ñ©{/ yùUìØ¹«ÐxŽ;a¯ŽDמ}01xnDß4XSVV–._‰C†¡gÿç1ï‹EHM•»lRš¬½׬[‡7FÌ ê3ðœ:sFû{ø¥ËèôlOíï£ÆŒÃŽ»01xºöìƒ!§ÇOžÄ¨1ãйGo¼0üe,_½Fg:4X¿q†¼ü*ºõySg¾‡Ûwî˜l3››+‚ÛàÀáÃù^ßð0º=Ó9_;º—ŒÕ¤ï’Äã´nQÅaÝ!7G% òFc{Ì{Þ ý컨0®³;ò.¯Ç<ÌÆ¤Ÿ ,&Óh›YYÙHKKËשÕjíûËW}‹c'Oá‹ÏæbýšUptr4ØÖ+ÆbÔ+/£[—Î8²w¦O†ªU­Šùsç`ÓºïЧWOÌ™7QÑùÿ𾋹³>Æk×ÀËËã&¼—bá×ß *ú&Ö®Z kVáÖ­[X¶j•s°l°ærLOOGôÍ4mÒ¸Èu-úz)zôè†UË–¢EÓ&HJJÆŒ÷?B¿Þ½°ý—Ÿ±àÓ9xæé§´ý¯Y·{÷À¼ÙŸ`ý·+aog‡ñSÞFVV–Á6 êÖå<|"÷¬ŒF£ÁÁ#GÑU'@è2U“>ÓºED‡U„Z¸;)ááœÓ¬³½Ÿò—ƒ½Ñ¯Å£¿>ÏÞÈÄ›?>ÀÙPkŒ·ùë¶ßñLÏ>ùº}ȹ!ò—­Ûðîô©¨W§ªøù!xâxéº èÚ¨êï/ ‡?üw1<_?úõAÚð¯RïϘ…B=ûj+%5üùF|žž¨äë‹1£GáÀá#Òu•k.ǘ[·!„€§‡G‘ëóÚkèÛ³'êÖ© GGGܽ¬ìl<ùD;¸¹¹¢v@€ö²Bff&6ýßϘùv0êÔÎY¶¿7)))8tä˜Á6 êôT$&&âbxÎúz> ®..hØ@ÿ} Æj2äqZ·ˆ¨â°ú=×îgaâæX,ê o8Û+Ð¼š½¶Ÿ.¤âË ÈR›w§ÞÐÁƒ0e‚þPpëöm¨54¨WOûš%d»÷âÜ… HHH@ÜÃ8dyRÃÞÞ-š5ETÔBïÝˆŽ†F£ÁÌ>†"·šlu6RS“-¨¬tXs9úx{bbbànâ@jŠƒƒ}¾ßkÕ¬‰6-[bøÈQèðÄx®o´mÝ:g|·ï ;;;ß ‹NNNhÒ¤1®ßˆ2ØfA...h×6AãF°ïàÁ|—/ 2V“9*úºED‡uDî_¡×c³1iÓ|5Ì>®6r>ápÝ‘$¬=œ3oò7)+3FêÉ ]©©éx}Ütéô4F|•*WFðô&‡³·³Ëwg~W7À÷+—ÃËÓÓ¢šJ›5—£J¥‚—§'ŽrTª¦²ÄÚËqØ‹ƒ±qÓOˆ¹uË`?NNŽˆº^ø¯ns´nÙ¾;ß._Šƒ‡à~lì£u#ìѺ¡Ñh~é2êHµß±Cܺ}ÿìÞ {{[Ô«[×¢š zŒÖ-"ª8¬{„ùºë²0~S,&ýô…¥z?¯3FßM”™97ì¹89¡OϘ¿pþ»xÆc톶W©’/Ξ Ã;w‘––oo/¤¤¤à·m >>ÿÛ½W¯Dnó–_~é2>ŒÇÒ« jtê˜ssœJ¥ÂíÛw „€­­-^>ËV¯ÁÉÓ§¡Ñhp÷Þ=\¼tɹZò¬½‡ ~ ÔLj7ÞÄ/[ǵÈH܈¾‰ÿíÞƒÃGs†Í›6Åý;wîâÎݻضýO“u&&%áÏÿà~l,ÒÓÓq&ô<œœœàîî''ôëÝ .ÆÅðpÄ=|ˆÅK¿§‡‚tÉ4‡‹“Ú·k‡%K—£Û3],®ÉÇiÝ"¢ŠÃj—0” @£(øçûõØl\Í60! 4rã¯Û~ǯÛ~Ï÷Zë–-°ü«Å€·'OÄ’o–cêÌ÷agg‹¾={¢z5ƒíõêþ,Ž?á£F¡UËVX8ïSŒs V¯]‡kÖ (° ‚‚ `[·ÄŒ>BJj*Z6oŽeKÃÖ6gö òæ/\ŒkׯcþÜÙõÊËptpÀ⯖âνûðòôÄ+Ã^D£ OhQËÑÖÖß,^ˆ-¿mÃî}{±âÛ5°Q*PŸë˜0n,æ~¾ÃF¾o/ôëÝ ¶zNãëJJJÂÞ±lÕj¤¦¤¢Fõê˜7ûc8ØçÜ×0uò,[µï|𲳳ѮM –|9_ê“6ó<Û¥3:dðé skÒçqY·ˆ¨bÑ·'Uæv¶ìr;§Ü΀+€v©)É‹túè×[øý|&Jý 888ð Rp9‘)V} ƒˆˆˆ DDD$‚ˆˆˆ¤1@‘4"""’ÆADDDÒ ˆˆˆHIc€ """iVý$J]g®§bëéD»šŒ¨ØœE®éc‡'êºb`w´®å\\£&+JNŒÇý»w˜‡ô´4€£“ÜU^ð­ìWwR®*2®DeW±ˆ–ÝDø­4x«\àîî–>9£IÏÌÆÁˆ4l=ƒ†þNøe|µâ=YIä•p$&Ä¡Š Ô¬].n¤DÄÞ½ˆËÿÁ]å…€z K¹Rªˆ¸þ•mVý2-è4/T÷ó4:âè;á TãÀ»E(ŸŠKxØY89;£a³Ö&ú;ƒ´ÔT4lÖª„*£Ç×?¢’cé—iYõˆ–Ý4+<@u?Odhlð²›ûùpötíÕ<(ôÞšuëñáì9Ò5¾óþ‡˜öî…^ÿjù ô0)¹§IóDߌÁ“ÏtCbR’ô¸¬e؈װaã¦_ä•p³vÞаYk89;#òJ¸É~÷î?ˆ©3ÞE¿† kÏ>ñÆXlûc;`Ô˜qøã¯¿‹\»5edf"==ݪmrý3Íšë_Y˜ß™™™hß© nÆÜ*sµÉ*éuÊ6«ˆ3×SqñVªVö„Fx»ÚàÝ^Ø2¶2¶Œ­Œ÷z{ÀßÃVû~ÕÊž¸x+ g®§lW­Ñ`ɲåÖ*íÛ¶EèùóÐhò)8xÉ))8y2$ßë§ÏžEà àîæfµduzªÔ¯_"ãJNŒGbBœY;ï< ›µFbB’ã ö3wÞ,]±Ïv킯~‰•Ë¾Æ Àãì^Ã^ÿÃF|ºà «¶ÉõÏ8k¯ey~—åÚ )ÉuÊ>«ˆ­§áåîÐoW%¾æuád¯€“½OÖqÄÂÁ^ðrQjûórwÁÖÓ‰ÛØ¿BΜʼnÓV©³]P ’““qíšöµ¨èh¤¥§¡W÷î8rôX¾þCΜEû ¶V·¥Þ|ãu´kX"ãº÷ªø×®Š Ü¿{Gï{;wïEHèYü¸v zu5k ^:è×»:?ݱ¨%—+\ÿŒ³öúW–çwY®Í’\¨ì³Z€8v5.ÎŽÐhÓÑnŽ…›wsTbLGwm.ÎŽ8v5Ù`»înn˜<~¾\¼™™™ûÓh4X¿q†¼ü*ºõySg¾‡Ûw ïPªúû£zµª8z^ûÚñ§ðd»vèÔ±?žï/‚3gCÑ.0gƒ5fvìÜ…‰ÁÓеgœ9¬¬,|µl9¿ô2:uï…!/¿Š;wåç¨1ãðó/¿aÌø‰èÚ³^{s<.†‡K½¯{zÔ˜qX¿q^{s<žéÙ¯¼öο }_­Vcùê50dzô€y_,Âà—^)t UŸÄ„8øT®b²¿‚|*WAbBœÞ÷Ö¬[‡7F„‹³ñ'oΜ Õ;MæÎcK– ü´åW {u$º÷í¯]o~ØüÖþð#vïÝ]žÅ‹¿ÒÖ²tùJ 2 =û?y_,BjjºÑ:tqý3ÎÚë_Qæ·©}Š¡e­V«±bõ xqº÷íÏ,Ô[3×*ï¬ ¢b³`g÷èòD›šû ¬å íÏÎÎVû˜§!=Ÿ}~•*cæÍûY³nöî?€y³?ÁúoWÂÞÎã§¼¬¬Âm·j‹3¡ç´¿=qO¶o‡6­[!##ÿ]ÌÙ`"¯_GFFš6i¤íwÑ×KÑ£G7¬Z¶-š6ªU­Šùsç`ÓºïЧWOÌ™7QÑÑùƹ}Ç?˜0n,~úq=š5i„ S§#99Ùì÷ :qòfL‚ß6oD“&ñÞdz´ÓºlÕ·8~ò¾˜7ë¾] …Rè›1Fçqžô´4íÝî2\ÜܵÙåk/=Ñ7cдIc“mÄܾéÁ“ M“¹óØ’eóÃæŸð׎ðñûïaãºïг[7x¨TxeØPŒzåetëÒGöîÂôàÉ€…_ƒ¨è›X»j6¬Y…[·naÙªUFë(ˆëŸaÖ^ÿËç·9û}Ëzùªoqìä)|ñÙ\¬_³ ŽNŽëæº@å™Uo¢TkuÆa~¿y¦O‚Í?ÿ¢wåËÌÌĦÿû3ßFÚ¨êïß›‰””:r¬PÿíƒÚ"ôÜ9!‘‘° ah×6öö Ä‘cÇ!§Ï"°MkØØØh‡óÚkèÛ³'êÖ© GÇœàýQ; g¼#^ÿ*~Ú ?Ïàç yÓ¦ðõñÁäñoÁËS…]{öšý~A=»?‹õëÁÓÓ#^†qq¸ƒŒŒ üºu?ª‘ aIDATÞ>õêÔA??OoÞL.1·nCO3îuè×§5hPhšóæ±ì²Q«ÕX÷ÃFÌx; Ô‡¯ºwë'''½õ¥¤¦â?ÿÂ葯ÂÓÓ•|}1fô(8|Ädº¸þ•,Kæ·¹û”‚Ë##3¿HL?×*Ϭö95¼íž™{»œ&OGe c=ýÉ;$*!™YÙ¨ámgºýêÕ0lÈ ørñ|µ0ÿm1·ï ;;;ßÍ=NNNhÒ¤1®ßˆ*ÔVë–-‘š–†ëQQ¸{ïÔ«WWWÀÓO=‰Ÿ~þcG¿†³¡h_àzŸƒƒ}¡öâãã±s÷^œ»p ˆ{‡ #wï+•J4kÒ7nêÅÔûUñ󃓓RSÓpëöm¨54¨WOû¾¾gu qptBJR¢ô_)I‰pp,|àõñöÄÄÄÀ½¡ùÏëëN`Þ<–]6·nßAZZ5l`VM7¢£¡Ñh0ó£¡È«Ùêl¤¦æÿëL_º¸þfíõ°l~›»O)¸7â²µý%%§â¹–æ=–doow¦cɲåHIIѾ^µZÎ'Z††…i_Óh4¿tuôPU»ÜkÇOœÄSO´×¾®R©Ð¬ic¬Ýð#>ÿÛ½W¯Dêoͺõ8tä(âãã±fÝz¤¦¥â™NÍ~ß\.NNèÓ³æ/\„ÿ.^ÄÇñX»áG³‡wSyÀÕÍáagÌ&<ì \Ý<àfà/Àaƒ_@ƒõ1â7ñËÖßq-27¢oâ»÷àðQÓcsç±ìp*wwtêøÿíÝoheðozI{×?v`[íº6®u (ÃvÒù‡½Qp[Wݘvk†ÙÖÚÍJÅ?`Ù ÿ¼&íØt¬ &ˆB„½ADEÊ¡-Š[]е+[XÛd—Ú&õEú4O®w—KLi2¿8š]–K›<Íóíóüž»m8:p—ÆÇÒu Ÿ;·¼ª¢¢¢?þ4ŠÉÉËÐun·­û[ðÞàiü02‚h4ŠËSS¶Ä ÛŸ¹Õh@ê¯w:Ÿ)âq©þül ”«2 EÁPg9ŠÜÓËSV[ 0"wCå …ANôtwÁãN,ßèí9„ûîÝŠWúŽ Õw³3A }.‹?U7ÕÕAÓŠ† …mÜh4êh͵·ºÝÏu`ðÌØÛvß £±qåLã= 8qòöìkÃè/¿âä±~x<Ç÷§â¥žÃØR_Þ×^GÛÁvÌ--ÍËKþg»¢(¨òÖ" 9úÿmôô;އ¶7áùž^\¸p1é÷bÄögn5ÚÞëêgŠ ÿüÚ;Õ¬GØ(WeüZº®ãÉÁ+› £°PCª.wöó ˜ ‡qýºŽM·ªê(³¬x¿‘ø:ºðxsvíØžÖýÿÕÕ@;wïÅ·_~‚|û?A×uLøÿ@pö*×× ì–Ê3ú{Ââ’uX_³ññ>æ*¶?r±-ÐêK÷Z¿§¦iø¤³ç/éøügßÿ~ þ©Øšàš›=xðŽBìØ\†¯fºÄ2ïâØ6TU¦ô «iª¼µÎNc:pù1Ž­ˆ(P5”Ü´UÞ:—”ò}$[l$¤Ó({­Êå¼UUÅÖÛ=hðjˆDJ——læ¹\P'åi rîO¿~ÿ8¶Ôß+Þ?u­--)GUUx<—”"‰ð}$GØþHÈT[ ìä4@,þt]Ž¢(üå^#ÁÙ Î|ø޼ù6*Ê˰»¹5íLëX|)Ul$d²-Ъ2öéÆ>ßT²7€|*â5EˆÕ@ ¤ý­QV(,*~±ˆâ5aÿ Vÿ`Za· cÑpÛ¸Qî³ëã-û{'Ë8£KˆJ[ÄöDDD”+"HìãEŸo+Y€ˆJ_Å#pp`"""Ê rß.‡Û¾Þ¬ˆÒ8„!n‹'X°PXT|±úˆ|ÄÎá  ^CÁ3…­=yAôãóˆÕ8Èurˆ0f€SÉVaÃxâÄ +UÄC„(ºT ½T8¥E„‚åAÄÃCxiÂ,D˜² râ0K-b”Òý 8ADD”mŒ}yñ!6qÆI¹Âvá„Ý„U€Ã¼_.0@e³Ùqšj'”U „Kº-žÐ…Ä` î“G%“ÿGDDDkGIALeÌ6c-„|Œv#¢úÒ…Ä!$ö™M]0<e³Y¹&Â,<¬8y”Ì®Bž¦pî“‹1äi QÁJ""¢ìauZ9HÈE”rpH¹B`. We are also connecting to the application's ``activate`` event, where we will create the window. .. literalinclude:: examples/simple_example.py :lines: 7,9-10 In the ``on_activate`` callback we will create an empty window, and then display it using the :meth:`Gtk.Window.present` method. .. literalinclude:: examples/simple_example.py :lines: 18 Finally, we start the application using the :meth:`Gio.Application.run` method. Minimal Example without GtkApplication ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In GTK 4, if you don't want to use :class:`Gtk.Application` you can use this replacement that will iterate the default main loop until all windows have been closed: .. attention:: Doing this is only useful for very specific use cases like tests. For app development you should always use :class:`Gtk.Application`. .. code:: python import gi gi.require_version('Gtk', '4.0') from gi.repository import GLib, Gtk win = Gtk.Window() win.present() while (len(Gtk.Window.get_toplevels()) > 0): GLib.MainContext.default().iteration(True) .. _extended-example: Extended Example ---------------- For something a little more useful, here's the PyGObject version of the classic "Hello World" program. .. image:: images/extended_example.png .. literalinclude:: examples/extended_example.py :linenos: This example differs from the simple example as we sub-class :class:`Gtk.ApplicationWindow` to define our own ``MyWindow`` class. .. seealso:: For more info about subclassing read :doc:`GObject Subclassing `. .. literalinclude:: examples/extended_example.py :lines: 7 In the class's constructor we have to call the constructor of the super class. In addition, we tell it to set the value of the property title to *Hello World*. Note that we are also receiving and passing ``**kargs``, so we can redirect other arguments passed on ``MyWindow`` construction to the base class. .. literalinclude:: examples/extended_example.py :lines: 8-9 The next three lines are used to create a button widget, connect to its ``clicked`` signal and add it as child to the top-level window. .. literalinclude:: examples/extended_example.py :lines: 11-13 Accordingly, the method `on_button_clicked` will be called if you click on the button. In this example we are using the method to print ``Hello World`` and calling the window :meth:`Gtk.Window.close` method to close the window. .. literalinclude:: examples/extended_example.py :lines: 15-17 The last block, outside of the class, is very similar to the simple example above, but instead of creating an instance of the generic :class:`Gtk.ApplicationWindow` or :class:`Gtk.Window` class, we create an instance of ``MyWindow``. .. _Getting Started with GTK: https://docs.gtk.org/gtk4/getting_started.html ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/layout-widgets.rst0000664000000000000000000002566615074673150021727 0ustar00rootroot.. currentmodule:: gi.repository Layout Containers ================= While many GUI toolkits require you to precisely place widgets in a window, using absolute positioning, GTK uses a different approach. Rather than specifying the position and size of each widget in the window, you can arrange your widgets in rows, columns, and/or tables. The size of your window can be determined automatically, based on the sizes of the widgets it contains. And the sizes of the widgets are, in turn, determined by the amount of text they contain, or the minimum and maximum sizes that you specify, and/or how you have requested that the available space should be shared between sets of widgets. You can perfect your layout by specifying padding distance and centering values for each of your widgets. GTK then uses all this information to resize and reposition everything sensibly and smoothly when the user manipulates the window. GTK widgets can parent other widgets hierarchically, and the way those widgets are displayed depend on the :class:`Gtk.LayoutManager` set in the :attr:`Gtk.Widget.props.layout_manager` property. For ease of use, GTK provides "pre made" containers that have default layout managers for different needs. Most of these containers implement the :class:`Gtk.Orientable` interface, it allows to set the widget orientation using :attr:`Gtk.Orientable.props.orientation`, you can either set :attr:`Gtk.Orientation.HORIZONTAL` or :attr:`Gtk.Orientation.VERTICAL`. Some containers / layout managers like :class:`Gtk.Box` allow you to influence the allocation of a child using the :attr:`Gtk.Widget.props.halign`, :attr:`Gtk.Widget.props.valign`, :attr:`Gtk.Widget.props.hexpand` and :attr:`Gtk.Widget.props.vexpand` properties. The main container widgets are: * :class:`Gtk.Box` * :class:`Gtk.CenterBox` * :class:`Gtk.HeaderBar` * :class:`Gtk.Grid` * :class:`Gtk.ListBox` * :class:`Gtk.FlowBox` * :class:`Gtk.Stack` * :class:`Gtk.Notebook` We are looking into each one in the following sections. Boxes ----- Boxes are invisible containers into which we can pack our widgets. When packing widgets into a horizontal box, the objects are inserted horizontally from left to right or right to left depending on whether :meth:`Gtk.Box.prepend` or :meth:`Gtk.Box.append` is used. You can also use the :meth:`Gtk.Box.insert_child_after` or :meth:`Gtk.Box.reorder_child_after` methods to insert a widget on a specific position. In a vertical box, widgets are packed from top to bottom or vice versa. You may use any combination of boxes inside or beside other boxes to create the desired effect. Example ^^^^^^^ Let's take a look at a slightly modified version of the :ref:`extended-example` with two buttons. .. image:: images/layout_box.png .. literalinclude:: examples/layout_box.py :linenos: First, we create a horizontally orientated box container where 6 pixels are placed between children. This box becomes the child of the top-level window. .. literalinclude:: examples/layout_box.py :lines: 11-12 Subsequently, we add two different buttons to the box container. .. literalinclude:: examples/layout_box.py :lines: 14-21 CenterBox --------- :class:`Gtk.CenterBox` arranges three children in a row or a column depending on its orientation, keeping the middle child centered as well as possible. To add children you use :meth:`Gtk.CenterBox.set_start_widget`, :meth:`Gtk.CenterBox.set_center_widget`, and :meth:`Gtk.CenterBox.set_end_widget`. Example ^^^^^^^ .. image:: images/layout_center.png .. literalinclude:: examples/layout_center.py :linenos: HeaderBar --------- A :class:`Gtk.HeaderBar` is similar to a horizontal :class:`Gtk.CenterBox`, it allows to place children at the start or the end. In addition, it allows a title to be displayed. The title will be centered with respect to the width of the box, even if the children at either side take up different amounts of space. :class:`Gtk.HeaderBar` is designed to be used as a window titlebar. This means that it can show typical window frame controls, such as minimize, maximize and close buttons, or the window icon. It is also draggable, meaning that you can move the parent window from it. You can use the :meth:`Gtk.Window.set_titlebar` method to set it as so. To add children you use :meth:`Gtk.HeaderBar.pack_start`, :meth:`Gtk.HeaderBar.pack_end`, and :meth:`Gtk.HeaderBar.set_title_widget` for the center one. By default if no ``title_widget`` is set it will have a label with the window's :attr:`Gtk.Window.props.title`. Example ^^^^^^^ .. image:: images/layout_headerbar.png .. literalinclude:: examples/layout_headerbar.py :linenos: Grid ---- :class:`Gtk.Grid` is a container which arranges its child widgets in rows and columns, but you do not need to specify the dimensions in the constructor. Children are added using :meth:`Gtk.Grid.attach`. They can span multiple rows or columns. The :meth:`Gtk.Grid.attach` method takes five parameters: 1. The ``child`` parameter is the :class:`Gtk.Widget` to add. 2. ``left`` is the column number to attach the left side of ``child`` to. 3. ``top`` indicates the row number to attach the top side of ``child`` to. 4. ``width`` and ``height`` indicate the number of columns that the ``child`` will span, and the number of rows that the ``child`` will span, respectively. It is also possible to add a child next to an existing child, using :meth:`Gtk.Grid.attach_next_to`, which also takes five parameters: 1. ``child`` is the :class:`Gtk.Widget` to add, as above. 2. ``sibling`` is an existing child widget of ``self`` (a :class:`Gtk.Grid` instance) or ``None``. The ``child`` widget will be placed next to ``sibling``, or if ``sibling`` is ``None``, at the beginning or end of the grid. 3. ``side`` is a :class:`Gtk.PositionType` indicating the side of ``sibling`` that ``child`` is positioned next to. 4. ``width`` and ``height`` indicate the number of columns and rows the ``child`` widget will span, respectively. Example ^^^^^^^ .. image:: images/layout_grid.png .. literalinclude:: examples/layout_grid.py :linenos: ListBox ------- A :class:`Gtk.ListBox` is a vertical container that contains :class:`Gtk.ListBoxRow` children. These rows can be dynamically sorted and filtered, and headers can be added dynamically depending on the row content. It also allows keyboard and mouse navigation and selection like a typical list. Although a :class:`Gtk.ListBox` must have only :class:`Gtk.ListBoxRow` children, you can add any kind of widget to it via :meth:`Gtk.ListBox.append` or :meth:`Gtk.ListBox.insert` and a :class:`Gtk.ListBoxRow` widget will automatically be inserted between the list and the widget. :class:`Gtk.ListBox` allows activating and selecting its children. Selection can be configured with :attr:`Gtk.ListBox.props.selection_mode`, selection modes are :attr:`Gtk.SelectionMode.NONE` (not selection at all), :attr:`Gtk.SelectionMode.SINGLE` (one or none elements can be selected), :attr:`Gtk.SelectionMode.BROWSE` (user can't deselect a currently selected element except by selecting another element) and :attr:`Gtk.SelectionMode.MULTIPLE` (any number of elements may be selected). It will emit the :func:`row-activated ` signal when a row is activated in any form, and :func:`row-selected ` when a row is selected. Example ^^^^^^^ .. image:: images/layout_listbox.png .. literalinclude:: examples/layout_listbox.py :linenos: FlowBox ------- A :class:`Gtk.FlowBox` is a container that positions child widgets in sequence according to its orientation. For instance, with the horizontal orientation, the widgets will be arranged from left to right, starting a new row under the previous row when necessary. Reducing the width in this case will require more rows, so a larger height will be requested. Likewise, with the vertical orientation, the widgets will be arranged from top to bottom, starting a new column to the right when necessary. Reducing the height will require more columns, so a larger width will be requested. :class:`Gtk.FlowBox` behaves similar to :class:`Gtk.ListBox`, we could say that is its "grid" counterpart. Just like :class:`Gtk.ListBox`, the children of a :class:`Gtk.FlowBox` can be dynamically sorted and filtered, and also activated and selected. Although a :class:`Gtk.FlowBox` must have only :class:`Gtk.FlowBoxChild` children, you can add any kind of widget to it via :meth:`Gtk.FlowBox.append` or :meth:`Gtk.FlowBox.insert`, and a :class:`Gtk.FlowBoxChild` widget will automatically be inserted between the box and the widget. Example ^^^^^^^ .. image:: images/layout_flowbox.png .. literalinclude:: examples/layout_flowbox.py :linenos: Stack and StackSwitcher ----------------------- A :class:`Gtk.Stack` is a container which only shows one of its children at a time. In contrast to :class:`Gtk.Notebook`, :class:`Gtk.Stack` does not provide a means for users to change the visible child. Instead, the :class:`Gtk.StackSwitcher` widget can be used with :class:`Gtk.Stack` to provide this functionality. Transitions between pages can be animated as slides or fades. This can be controlled with :attr:`Gtk.Stack.props.transition_type`. These animations respect the ``gtk-enable-animations`` setting. Transition speed can be adjusted with :attr:`Gtk.Stack.props.transition_duration`. The :class:`Gtk.StackSwitcher` widget acts as a controller for a :class:`Gtk.Stack`; it shows a row of buttons to switch between the various pages of the associated stack widget. :class:`Gtk.Stack` uses the auxiliary :class:`Gtk.StackPage` object. :class:`Gtk.Stack` will return a :class:`Gtk.StackPage` every time you add a new children, either with :meth:`Gtk.Stack.add_child`, :meth:`Gtk.Stack.add_named` or :meth:`Gtk.Stack.add_titled`. :class:`Gtk.StackPage` holds important properties for the stack's children, like the name, the title to display, or if the page needs attention, then this data can be used for example by :class:`Gtk.StackSwitcher`. It is possible to associate multiple :class:`Gtk.StackSwitcher` widgets with the same :class:`Gtk.Stack` widget. Example ^^^^^^^ .. image:: images/layout_stack.png .. literalinclude:: examples/layout_stack.py :linenos: Notebook -------- The :class:`Gtk.Notebook` is a container whose children are pages switched between using tabs. There are many configuration options for GtkNotebook. Among other things, you can choose on which edge the tabs appear (see :meth:`Gtk.Notebook.set_tab_pos`), whether, if there are too many tabs to fit the notebook should be made bigger or scrolling arrows added (see :meth:`Gtk.Notebook.set_scrollable`), and whether there will be a popup menu allowing the users to switch pages (see :meth:`Gtk.Notebook.popup_enable`, :meth:`Gtk.Notebook.popup_disable`). You can add children with :meth:`Gtk.Notebook.append_page`, it takes two widgets, the first is the widget to show as a page, and the second is the widget to show as the tab content. Example ^^^^^^^ .. image:: images/layout_notebook.png .. literalinclude:: examples/layout_notebook.py :linenos: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/popovers.rst0000664000000000000000000000332615074673150020610 0ustar00rootroot.. currentmodule:: gi.repository Popovers ======== The :class:`Gtk.Popover` is an special kind of window used for displaying additional information and is often used with button menus and context menus. Popovers are attached to a parent widget and point to it. It's position can be configured with :attr:`Gtk.Popover.props.position`. :class:`Gtk.Popover` shows an arrow to visually connect where it points to, this can be disabled setting :attr:`Gtk.Popover.props.has_arrow` to ``False``. A :class:`Gtk.Popover` can be opened using :meth:`Gtk.Popover.popup` and hidden with :meth:`Gtk.Widget.hide`. GTK also provides :class:`Gtk.MenuButton`, it's an special button that can show and hide a :class:`Gtk.Popover` attached to it using :attr:`Gtk.MenuButton.props.popover`. Custom Popover -------------- A child widget can be added to a popover using :meth:`Gtk.Popover.set_child`. The parent of the popover can be set using :meth:`Gtk.Widget.set_parent`. Example ^^^^^^^ .. image:: images/popover.png .. literalinclude:: examples/popover.py :linenos: Menu Popover ------------ GTK also has :class:`Gtk.PopoverMenu`, it's a :class:`Gtk.Popover` subclass designed to display a menu model. A popover can be created from a :class:`Gio.MenuModel` using :meth:`Gtk.PopoverMenu.new_from_model` and can be changed after creation with :attr:`Gtk.PopoverMenu.props.menu_model`. :class:`Gtk.MenuButton` also can construct a :class:`Gtk.PopoverMenu` passing it a :class:`Gio.MenuModel` to :attr:`Gtk.MenuButton.props.menu_model`. .. seealso:: In :doc:`GTK Application ` we also showed examples of menu models. Example ^^^^^^^ .. image:: images/popover_menu.png .. literalinclude:: examples/popover_menu.py ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4/textview.rst0000664000000000000000000001373215074673150020614 0ustar00rootroot.. currentmodule:: gi.repository Text View ========= The :class:`Gtk.TextView` widget can be used to display and edit large amounts of formatted text. Like the :class:`Gtk.ListView`, it has a model/view design. In this case the :class:`Gtk.TextBuffer` is the model which represents the text being edited. This allows two or more :class:`Gtk.TextView` widgets to share the same :class:`Gtk.TextBuffer`, and allows those text buffers to be displayed slightly differently. Or you could maintain several text buffers and choose to display each one at different times in the same :class:`Gtk.TextView` widget. .. seealso:: `Text Widget Overview`_ in the GTK documentation. The View -------- The :class:`Gtk.TextView` is the frontend with which the user can add, edit and delete textual data. They are commonly used to edit multiple lines of text. When creating a :class:`Gtk.TextView` it contains its own default :class:`Gtk.TextBuffer`, which is kept in the :attr:`Gtk.TextView.props.buffer` property. By default, text can be added, edited and removed from the :class:`Gtk.TextView`. You can disable this by changing :attr:`Gtk.TextView.props.editable`. If the text is not editable, you usually want to hide the text cursor with :attr:`Gtk.TextView.props.cursor_visible` as well. In some cases it may be useful to set the justification of the text with :attr:`Gtk.TextView.props.justification`. The text can be displayed at the left edge, (:attr:`Gtk.Justification.LEFT`), at the right edge (:attr:`Gtk.Justification.RIGHT`), centered (:attr:`Gtk.Justification.CENTER`), or distributed across the complete width (:attr:`Gtk.Justification.FILL`). Another default setting of the :class:`Gtk.TextView` widget is long lines of text will continue horizontally until a break is entered. To wrap the text and prevent it going off the edges of the screen set :attr:`Gtk.TextView.props.wrap_mode` similar to :doc:`/tutorials/gtk4/display-widgets/label`. The Model --------- The :class:`Gtk.TextBuffer` is the core of the :class:`Gtk.TextView` widget, and is used to hold whatever text is being displayed in the :class:`Gtk.TextView`. Setting and retrieving the contents is possible with :attr:`Gtk.TextBuffer.props.text`. However, most text manipulation is accomplished with *iterators*, represented by a :class:`Gtk.TextIter`. An iterator represents a position between two characters in the text buffer. Iterators are not valid indefinitely; whenever the buffer is modified in a way that affects the contents of the buffer, all outstanding iterators become invalid. Because of this, iterators can't be used to preserve positions across buffer modifications. To preserve a position, use :class:`Gtk.TextMark`. A text buffer contains two built-in marks; an "insert" mark (which is the position of the cursor) and the "selection_bound" mark. Both of them can be retrieved using :meth:`Gtk.TextBuffer.get_insert` and :meth:`Gtk.TextBuffer.get_selection_bound`, respectively. By default, the location of a :class:`Gtk.TextMark` is not shown. This can be changed by calling :meth:`Gtk.TextMark.set_visible`. Many methods exist to retrieve a :class:`Gtk.TextIter`. For instance, :meth:`Gtk.TextBuffer.get_start_iter` returns an iterator pointing to the first position in the text buffer, whereas :meth:`Gtk.TextBuffer.get_end_iter` returns an iterator pointing past the last valid character. Retrieving the bounds of the selected text can be achieved by calling :meth:`Gtk.TextBuffer.get_selection_bounds`. To insert text at a specific position use :meth:`Gtk.TextBuffer.insert`. Another useful method is :meth:`Gtk.TextBuffer.insert_at_cursor` which inserts text wherever the cursor may be currently positioned. To remove portions of the text buffer use :meth:`Gtk.TextBuffer.delete`. In addition, :class:`Gtk.TextIter` can be used to locate textual matches in the buffer using :meth:`Gtk.TextIter.forward_search` and :meth:`Gtk.TextIter.backward_search`. The start and end iters are used as the starting point of the search and move forwards/backwards depending on requirements. Tags ---- Text in a buffer can be marked with tags. A tag is an attribute that can be applied to some range of text. For example, a tag might be called "bold" and make the text inside the tag bold. However, the tag concept is more general than that; tags don't have to affect appearance. They can instead affect the behavior of mouse and key presses, "lock" a range of text so the user can't edit it, or countless other things. A tag is represented by a :class:`Gtk.TextTag` object. One :class:`Gtk.TextTag` can be applied to any number of text ranges in any number of buffers. Each tag is stored in a :class:`Gtk.TextTagTable`. A tag table defines a set of tags that can be used together. Each buffer has one tag table associated with it; only tags from that tag table can be used with the buffer. A single tag table can be shared between multiple buffers, however. To specify that some text in the buffer should have specific formatting, you must define a tag to hold that formatting information, and then apply that tag to the region of text using :meth:`Gtk.TextBuffer.create_tag` and :meth:`Gtk.TextBuffer.apply_tag`: .. code:: python tag = textbuffer.create_tag('orange_bg', background='orange') textbuffer.apply_tag(tag, start_iter, end_iter) The following are some of the common styles applied to text: * Background colour ("background" property) * Foreground colour ("foreground" property) * Underline ("underline" property) * Bold ("weight" property) * Italics ("style" property) * Strikethrough ("strikethrough" property) * Justification ("justification" property) * Size ("size" and "size-points" properties) * Text wrapping ("wrap-mode" property) You can also delete particular tags later using :meth:`Gtk.TextBuffer.remove_tag` or delete all tags in a given region by calling :meth:`Gtk.TextBuffer.remove_all_tags`. Example ------- .. image:: images/textview.png .. literalinclude:: examples/textview.py :linenos: .. _Text Widget Overview: https://docs.gtk.org/gtk4/section-text-widget.html ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/gtk4.rst0000664000000000000000000000063715074673150016735 0ustar00rootrootGTK4 ==== GTK is a library for creating graphical user interfaces. The main objects of GTK are "widgets" which are components such as buttons, text input, or windows. .. toctree:: :maxdepth: 2 :caption: Contents gtk4/introduction gtk4/basics gtk4/application gtk4/layout-widgets gtk4/controls gtk4/display-widgets gtk4/popovers gtk4/textview gtk4/clipboard gtk4/drag-and-drop ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/index.rst0000664000000000000000000000357215074673150017174 0ustar00rootroot========= Tutorials ========= These tutorials give an introduction to writing GTK/GNOME applications in Python. Prior to working through these tutorials, it is recommended that you have a reasonable grasp of the Python programming language. It is necessary for you to know how to create and run Python files, understand basic interpreter errors, and work with strings, integers, floats and boolean values. For the more advanced parts of these examples, good knowledge of lists and tuples will be needed. Although here we try to describe the most important classes and methods from GObject based libraries like GTK, it is not supposed to serve as an API reference. Please refer to the :ref:`api-references` list where you will find a detailed description of the API for each library. Also there's a `Python-specific reference `_ available. .. note:: Our tutorial list is still not as extensive as we would like, so if you have experience with PyGObject, contributing docs is a great way to help. Some areas that could use your help: libadwaita components, GLib and Gio features. .. _api-references: API References -------------- * `GObject `_ * `Gtk 4 `_ * `Gdk 4 `_ * `Gio `_ * `GLib `_ * `Adwaita `_ * `Python-specific references `_ Other Resources --------------- * The :devdocs:`GNOME Developer Documentation ` has some tutorials that include Python examples. .. toctree:: :maxdepth: 1 :hidden: :caption: Contents gobject gtk4 libadwaita gtk3 .. toctree:: :maxdepth: 1 :hidden: :caption: External Resources .. toctree:: :maxdepth: 1 :hidden: :caption: About ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/libadwaita/application.rst0000664000000000000000000000273115074673150022465 0ustar00rootroot.. currentmodule:: gi.repository Adwaita Application =================== :class:`Adw.Application` extends :class:`Gtk.Application` to ease some task related to creating applications for GNOME. .. seealso:: We previously touched :class:`Gtk.Application` in :doc:`this tutorial `. Adwaita also have :class:`Adw.ApplicationWindow`, it's a subclass of :class:`Gtk.ApplicationWindow` that provides the same "freform" features from :class:`Adw.Window`. .. note:: Using :class:`Adw.Application` will also call :func:`Adw.init` for you, this function initialize de library, making sure that translations, types, themes, icons and stylesheets needed by the library are set up properly. Stylesheets ----------- If you make use of :class:`Gio.Resource`, :class:`Adw.Application` will automatically load stylesheets located in the application's resource base path. This way you don't need to manually load stylesheets, and it will load the matching stylesheets depending on the system appearance settings exposed by :class:`Adw.StyleManager`. * ``style.css`` contains the base styles. * ``style-dark.css`` contains styles only used when :attr:`Adw.StyleManager.props.dark` is ``True``. * ``style-hc.css`` contains styles used when :attr:`Adw.StyleManager.props.high_contrast` is ``True``. * ``style-hc-dark.css`` contains styles used when :attr:`Adw.StyleManager.props.high_contrast` and :attr:`Adw.StyleManager.props.dark` are both ``True``. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/docs/tutorials/libadwaita.rst0000664000000000000000000000075215074673150020163 0ustar00rootrootAdwaita ======= `Adwaita `_ (``libadwaita``) offers application developers many widgets and objects to build GNOME applications scaling from desktop workstations to mobile phones. Adwaita is the library you must use if you want to build applications targeting the GNOME desktop and follow its `Human Interface Guidelines `_. .. toctree:: :maxdepth: 3 :caption: Contents libadwaita/application ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/__init__.py0000664000000000000000000001452615074673150015066 0ustar00rootroot# Copyright (C) 2005-2009 Johan Dahlin # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA # support overrides in different directories than our gi module from pkgutil import extend_path __path__ = extend_path(__path__, __name__) import sys import os import importlib import types _static_binding_error = ( "When using gi.repository you must not import static " 'modules like "gobject". Please change all occurrences ' 'of "import gobject" to "from gi.repository import GObject". ' "See: https://bugzilla.gnome.org/show_bug.cgi?id=709183" ) # we can't have pygobject 2 loaded at the same time we load the internal _gobject if "gobject" in sys.modules: raise ImportError(_static_binding_error) from . import _gi from ._gi import _API as _API from ._gi import Repository from ._gi import PyGIDeprecationWarning as PyGIDeprecationWarning from ._gi import PyGIWarning as PyGIWarning _versions = {} _overridesdir = os.path.join(os.path.dirname(__file__), "overrides") # Needed for compatibility with "pygobject.h"/pygobject_init() _gobject = types.ModuleType("gi._gobject") sys.modules[_gobject.__name__] = _gobject _gobject._PyGObject_API = _gi._PyGObject_API _gobject.pygobject_version = _gi.pygobject_version version_info = _gi.pygobject_version[:] __version__ = "{}.{}.{}".format(*version_info) _gi.register_foreign() # Options which can be enabled or disabled after importing 'gi'. This may affect # repository imports or binding machinery in a backwards incompatible way. _options = { # When True, importing Gtk or Gdk will call Gtk.init() or Gdk.init() respectively. "legacy_autoinit": True, } class _DummyStaticModule(types.ModuleType): __path__ = None def __getattr__(self, name): raise AttributeError(_static_binding_error) sys.modules["glib"] = _DummyStaticModule("glib", _static_binding_error) sys.modules["gobject"] = _DummyStaticModule("gobject", _static_binding_error) sys.modules["gio"] = _DummyStaticModule("gio", _static_binding_error) sys.modules["gtk"] = _DummyStaticModule("gtk", _static_binding_error) sys.modules["gtk.gdk"] = _DummyStaticModule("gtk.gdk", _static_binding_error) def check_version(version): if isinstance(version, str): version_list = tuple(map(int, version.split("."))) else: version_list = version if version_list > version_info: raise ValueError( f"pygobject's version {version} required, and available version " f"{__version__} is not recent enough" ) def require_version(namespace, version): """Ensures the correct versions are loaded when importing `gi` modules. :param namespace: The name of module to require. :type namespace: str :param version: The version of module to require. :type version: str :raises ValueError: If module/version is already loaded, already required, or unavailable. :Example: .. code-block:: python import gi gi.require_version("Gtk", "3.0") """ repository = Repository.get_default() if not isinstance(version, str): raise ValueError("Namespace version needs to be a string.") if namespace in repository.get_loaded_namespaces(): loaded_version = repository.get_version(namespace) if loaded_version != version: raise ValueError( f"Namespace {namespace} is already loaded with version {loaded_version}" ) if namespace in _versions and _versions[namespace] != version: raise ValueError( f"Namespace {namespace} already requires version {_versions[namespace]}" ) available_versions = repository.enumerate_versions(namespace) if not available_versions: raise ValueError(f"Namespace {namespace} not available") if version not in available_versions: raise ValueError(f"Namespace {namespace} not available for version {version}") _versions[namespace] = version def require_versions(requires): """Utility function for consolidating multiple `gi.require_version()` calls. :param requires: The names and versions of modules to require. :type requires: dict :Example: .. code-block:: python import gi gi.require_versions({"Gtk": "3.0", "GLib": "2.0", "Gio": "2.0"}) """ for module_name, module_version in requires.items(): require_version(module_name, module_version) def get_required_version(namespace): return _versions.get(namespace) def require_foreign(namespace, symbol=None): """Ensure the given foreign marshaling module is available and loaded. :param str namespace: Introspection namespace of the foreign module (e.g. "cairo") :param symbol: Optional symbol typename to ensure a converter exists. :type symbol: str or None :raises: ImportError :Example: .. code-block:: python import gi import cairo gi.require_foreign("cairo") """ try: _gi.require_foreign(namespace, symbol) except Exception as e: raise ImportError(str(e)) importlib.import_module("gi.repository", namespace) def get_option(name): """Get option by name. :param str name: Name of the option. """ return _options.get(name) def disable_legacy_autoinit(): """Disable the legacy initialization of Gdk and Gtk. These modules are automatically initialized on import from `gi.repository`. This is not required, and was only kept for backwards compatibility reason. This behavior may eventually be dropped for future Gtk major releases. Usually, users should not manually perform these initializations but let e.g. `Gtk.Application` manage it when needed. """ _options["legacy_autoinit"] = False ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/_constants.py0000664000000000000000000000360515074673150015476 0ustar00rootroot# pygobject - Python bindings for the GObject library # Copyright (C) 2006-2007 Johan Dahlin # # gi/_constants.py: GObject type constants # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, see . from . import _gi TYPE_INVALID = _gi.TYPE_INVALID TYPE_NONE = _gi.GType.from_name("void") TYPE_INTERFACE = _gi.GType.from_name("GInterface") TYPE_CHAR = _gi.GType.from_name("gchar") TYPE_UCHAR = _gi.GType.from_name("guchar") TYPE_BOOLEAN = _gi.GType.from_name("gboolean") TYPE_INT = _gi.GType.from_name("gint") TYPE_UINT = _gi.GType.from_name("guint") TYPE_LONG = _gi.GType.from_name("glong") TYPE_ULONG = _gi.GType.from_name("gulong") TYPE_INT64 = _gi.GType.from_name("gint64") TYPE_UINT64 = _gi.GType.from_name("guint64") TYPE_ENUM = _gi.GType.from_name("GEnum") TYPE_FLAGS = _gi.GType.from_name("GFlags") TYPE_FLOAT = _gi.GType.from_name("gfloat") TYPE_DOUBLE = _gi.GType.from_name("gdouble") TYPE_STRING = _gi.GType.from_name("gchararray") TYPE_POINTER = _gi.GType.from_name("gpointer") TYPE_BOXED = _gi.GType.from_name("GBoxed") TYPE_PARAM = _gi.GType.from_name("GParam") TYPE_OBJECT = _gi.GType.from_name("GObject") TYPE_PYOBJECT = _gi.GType.from_name("PyObject") TYPE_GTYPE = _gi.GType.from_name("GType") TYPE_STRV = _gi.GType.from_name("GStrv") TYPE_VARIANT = _gi.GType.from_name("GVariant") TYPE_UNICHAR = TYPE_UINT ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/_enum.py0000664000000000000000000000523515074673150014427 0ustar00rootroot# -*- Mode: Python; py-indent-offset: 4 -*- # vim: tabstop=4 shiftwidth=4 expandtab # # Copyright (C) 2025 James Henstridge # # _enum.py: base classes for enumeration and flags types. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import enum import warnings from . import _gi class GEnumMeta(enum.EnumMeta): def __new__(metacls, name, bases, classdict, /, **kwargs): enum_class = super().__new__(metacls, name, bases, classdict, **kwargs) # If __gtype__ is not set, this is a new enum or flags defined # from Python. Register a new GType for it. if "__gtype__" not in enum_class.__dict__: type_name = enum_class.__dict__.get("__gtype_name__") _gi.enum_register(enum_class, type_name) return enum_class @property def __enum_values__(self): from gi import PyGIDeprecationWarning warnings.warn( 'Calling "__enum_values__" on enums is deprecated.', PyGIDeprecationWarning ) return {m.value: m for m in self} class GEnum(enum.IntEnum, metaclass=GEnumMeta): __module__ = _gi.__name__ __gtype__ = None class GFlagsMeta(enum.EnumMeta): def __new__(metacls, name, bases, classdict, /, **kwargs): flags_class = super().__new__(metacls, name, bases, classdict, **kwargs) # If __gtype__ is not set, this is a new enum or flags defined # from Python. Register a new GType for it. if "__gtype__" not in flags_class.__dict__: type_name = flags_class.__dict__.get("__gtype_name__") _gi.flags_register(flags_class, type_name) return flags_class @property def __flags_values__(self): from gi import PyGIDeprecationWarning warnings.warn( 'Calling "__flags_values__" on flags is deprecated. ', PyGIDeprecationWarning, ) return {m.value: m for m in self} class GFlags(enum.IntFlag, metaclass=GFlagsMeta): __module__ = _gi.__name__ __gtype__ = None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/_error.py0000664000000000000000000000364315074673150014615 0ustar00rootroot# Copyright (C) 2014 Simon Feltman # # _error.py: GError Python implementation # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA # NOTE: This file should not have any dependencies on introspection libs # like gi.repository.GLib because it would cause a circular dependency. # Developers wanting to use the GError class in their applications should # use gi.repository.GLib.GError class GError(RuntimeError): def __init__(self, message="unknown error", domain="pygi-error", code=0): super().__init__(message) self.message = message self.domain = domain self.code = code def __str__(self): return f"{self.domain:s}: {self.message:s} ({self.code:d})" def __repr__(self): return f"{GError.__module__.rsplit('.', 1)[-1]:s}.{GError.__name__:s}('{self.message:s}', '{self.domain:s}', {self.code:d})" def copy(self): return GError(self.message, self.domain, self.code) def matches(self, domain, code): """Placeholder that will be monkey patched in GLib overrides.""" raise NotImplementedError @staticmethod def new_literal(domain, message, code): """Placeholder that will be monkey patched in GLib overrides.""" raise NotImplementedError ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/_gtktemplate.py0000664000000000000000000002333215074673150016002 0ustar00rootroot# Copyright 2015 Dustin Spicuzza # 2018 Nikita Churaev # 2018 Christoph Reiter # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import os from collections import abc from functools import partial from gi.repository import GLib, GObject, Gio def _extract_handler_and_args(obj_or_map, handler_name): handler = None if isinstance(obj_or_map, abc.Mapping): handler = obj_or_map.get(handler_name, None) else: handler = getattr(obj_or_map, handler_name, None) if handler is None: raise AttributeError(f"Handler {handler_name} not found") args = () if isinstance(handler, abc.Sequence): if len(handler) == 0: raise TypeError(f"Handler {handler} tuple can not be empty") args = handler[1:] handler = handler[0] elif not callable(handler): raise TypeError(f"Handler {handler} is not a method, function or tuple") return handler, args def define_builder_scope(): from gi.repository import Gtk class BuilderScope(GObject.GObject, Gtk.BuilderScope): def __init__(self, scope_object=None): super().__init__() self._scope_object = scope_object def do_create_closure(self, builder, func_name, flags, obj): current_object = builder.get_current_object() or self._scope_object if not self._scope_object: current_object = builder.get_current_object() if func_name not in current_object.__gtktemplate_methods__: return None current_object.__gtktemplate_handlers__.add(func_name) handler_name = current_object.__gtktemplate_methods__[func_name] else: current_object = self._scope_object handler_name = func_name swapped = int(flags & Gtk.BuilderClosureFlags.SWAPPED) if swapped: raise RuntimeError(f"{GObject.ConnectFlags.SWAPPED!r} not supported") return None handler, args = _extract_handler_and_args(current_object, handler_name) if obj: p = partial(handler, *args, swap_data=obj) else: p = partial(handler, *args) p.__gtk_template__ = True return p return BuilderScope def connect_func(builder, obj, signal_name, handler_name, connect_object, flags, cls): if handler_name not in cls.__gtktemplate_methods__: return method_name = cls.__gtktemplate_methods__[handler_name] template_inst = builder.get_object(cls.__gtype_name__) template_inst.__gtktemplate_handlers__.add(handler_name) handler = getattr(template_inst, method_name) after = int(flags & GObject.ConnectFlags.AFTER) swapped = int(flags & GObject.ConnectFlags.SWAPPED) if swapped: raise RuntimeError(f"{GObject.ConnectFlags.SWAPPED!r} not supported") if connect_object is not None: func = obj.connect_object_after if after else obj.connect_object func(signal_name, handler, connect_object) else: func = obj.connect_after if after else obj.connect func(signal_name, handler) def register_template(cls): from gi.repository import Gtk bound_methods = {} bound_widgets = {} for attr_name, obj in list(cls.__dict__.items()): if isinstance(obj, CallThing): setattr(cls, attr_name, obj._func) handler_name = obj._name if handler_name is None: handler_name = attr_name if handler_name in bound_methods: old_attr_name = bound_methods[handler_name] raise RuntimeError( f"Error while exposing handler {handler_name!r} as {attr_name!r}, " f"already available as {old_attr_name!r}" ) bound_methods[handler_name] = attr_name elif isinstance(obj, Child): widget_name = obj._name if widget_name is None: widget_name = attr_name if widget_name in bound_widgets: old_attr_name = bound_widgets[widget_name] raise RuntimeError( f"Error while exposing child {widget_name!r} as {attr_name!r}, " f"already available as {old_attr_name!r}" ) bound_widgets[widget_name] = attr_name cls.bind_template_child_full(widget_name, obj._internal, 0) cls.__gtktemplate_methods__ = bound_methods cls.__gtktemplate_widgets__ = bound_widgets if Gtk._version == "4.0": BuilderScope = define_builder_scope() cls.set_template_scope(BuilderScope()) else: cls.set_connect_func(connect_func, cls) base_init_template = cls.init_template cls.__dontuse_ginstance_init__ = lambda s: init_template(s, cls, base_init_template) # To make this file work with older PyGObject we expose our init code # as init_template() but make it a noop when we call it ourselves first cls.init_template = cls.__dontuse_ginstance_init__ def init_template(self, cls, base_init_template): self.init_template = lambda: None if self.__class__ is not cls: raise TypeError( "Inheritance from classes with @Gtk.Template decorators " "is not allowed at this time" ) self.__gtktemplate_handlers__ = set() base_init_template(self) for widget_name, attr_name in self.__gtktemplate_widgets__.items(): self.__dict__[attr_name] = self.get_template_child(cls, widget_name) for handler_name, attr_name in self.__gtktemplate_methods__.items(): if handler_name not in self.__gtktemplate_handlers__: raise RuntimeError( f"Handler '{handler_name}' was declared with @Gtk.Template.Callback " "but was not present in template" ) class Child: def __init__(self, name=None, **kwargs): self._name = name self._internal = kwargs.pop("internal", False) if kwargs: raise TypeError(f"Unhandled arguments: {kwargs!r}") class CallThing: def __init__(self, name, func): self._name = name self._func = func class Callback: def __init__(self, name=None): self._name = name def __call__(self, func): return CallThing(self._name, func) def validate_resource_path(path): """Raises GLib.Error in case the resource doesn't exist.""" try: Gio.resources_get_info(path, Gio.ResourceLookupFlags.NONE) except GLib.Error: # resources_get_info() doesn't handle overlays but we keep using it # as a fast path. # https://gitlab.gnome.org/GNOME/pygobject/issues/230 Gio.resources_lookup_data(path, Gio.ResourceLookupFlags.NONE) class Template: def __init__(self, **kwargs): self.string = None self.filename = None self.resource_path = None if "string" in kwargs: self.string = kwargs.pop("string") elif "filename" in kwargs: self.filename = kwargs.pop("filename") elif "resource_path" in kwargs: self.resource_path = kwargs.pop("resource_path") else: raise TypeError( "Requires one of the following arguments: " "string, filename, resource_path" ) if kwargs: raise TypeError(f"Unhandled keyword arguments {kwargs!r}") @classmethod def from_file(cls, filename): return cls(filename=filename) @classmethod def from_string(cls, string): return cls(string=string) @classmethod def from_resource(cls, resource_path): return cls(resource_path=resource_path) Callback = Callback Child = Child def __call__(self, cls): from gi.repository import Gtk if not isinstance(cls, type) or not issubclass(cls, Gtk.Widget): raise TypeError("Can only use @Gtk.Template on Widgets") if "__gtype_name__" not in cls.__dict__: raise TypeError( f"{cls.__name__!r} does not have a __gtype_name__. Set it to the name " "of the class in your template" ) if hasattr(cls, "__gtktemplate_methods__"): raise TypeError("Cannot nest template classes") if self.string is not None: data = self.string if not isinstance(data, bytes): data = data.encode("utf-8") bytes_ = GLib.Bytes.new(data) cls.set_template(bytes_) register_template(cls) return cls if self.resource_path is not None: validate_resource_path(self.resource_path) cls.set_template_from_resource(self.resource_path) register_template(cls) return cls assert self.filename is not None file_ = Gio.File.new_for_path(os.fspath(self.filename)) bytes_ = GLib.Bytes.new(file_.load_contents()[1]) cls.set_template(bytes_) register_template(cls) return cls __all__ = ["Template"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/_option.py0000664000000000000000000003244615074673150014777 0ustar00rootroot# pygobject - Python bindings for the GObject library # Copyright (C) 2006 Johannes Hoelzl # # glib/option.py: GOption command line parser # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, see . """GOption command line parser. Extends optparse to use the GOptionGroup, GOptionEntry and GOptionContext objects. So it is possible to use the gtk, gnome_program and gstreamer command line groups and contexts. Use this interface instead of the raw wrappers of GOptionContext and GOptionGroup in glib. """ import sys import optparse import warnings from optparse import ( OptParseError, OptionError, OptionValueError, BadOptionError, OptionConflictError, ) from .module import get_introspection_module from gi import _gi, PyGIDeprecationWarning from gi._error import GError GLib = get_introspection_module("GLib") OPTION_CONTEXT_ERROR_QUARK = GLib.quark_to_string(GLib.option_error_quark()) __all__ = [ "BadOptionError", "OptParseError", "Option", "OptionConflictError", "OptionError", "OptionGroup", "OptionParser", "OptionValueError", "make_option", ] class Option(optparse.Option): """Represents a command line option. To use the extended possibilities of the GOption API Option (and make_option) are extended with new types and attributes. Types: filename The supplied arguments are read as filename, GOption parses this type in with the GLib filename encoding. :ivar optional_arg: This does not need a arguement, but it can be supplied. :ivar hidden: The help list does not show this option :ivar in_main: This option apears in the main group, this should only be used for backwards compatibility. Use Option.REMAINING as option name to get all positional arguments. .. NOTE:: Every argument to an option is passed as utf-8 coded string, the only exception are options which use the 'filename' type, its arguments are passed as strings in the GLib filename encoding. For further help, see optparse.Option. """ TYPES = (*optparse.Option.TYPES, "filename") ATTRS = [*optparse.Option.ATTRS, "hidden", "in_main", "optional_arg"] REMAINING = "--" + GLib.OPTION_REMAINING def __init__(self, *args, **kwargs): warnings.warn( "gi.repository.GLib.option.Option is deprecated, use gi.repository.GLib.OptionEntry instead", PyGIDeprecationWarning, stacklevel=2, ) optparse.Option.__init__(self, *args, **kwargs) if not self._long_opts: raise ValueError("%s at least one long option name.") if len(self._long_opts) < len(self._short_opts): raise ValueError( "%s at least more long option names than short option names." ) if not self.help: raise ValueError("%s needs a help message.", self._long_opts[0]) def _set_opt_string(self, opts): if self.REMAINING in opts: self._long_opts.append(self.REMAINING) optparse.Option._set_opt_string(self, opts) if len(self._short_opts) > len(self._long_opts): raise OptionError( "goption.Option needs more long option names than short option names" ) def _to_goptionentries(self): flags = 0 if self.hidden: flags |= GLib.OptionFlags.HIDDEN if self.in_main: flags |= GLib.OptionFlags.IN_MAIN if self.takes_value(): if self.optional_arg: flags |= GLib.OptionFlags.OPTIONAL_ARG else: flags |= GLib.OptionFlags.NO_ARG if self.type == "filename": flags |= GLib.OptionFlags.FILENAME for long_name, short_name in zip(self._long_opts, self._short_opts): short_bytes = short_name[1] if not isinstance(short_bytes, bytes): short_bytes = short_bytes.encode("utf-8") yield (long_name[2:], short_bytes, flags, self.help, self.metavar) for long_name in self._long_opts[len(self._short_opts) :]: yield (long_name[2:], b"\0", flags, self.help, self.metavar) class OptionGroup(optparse.OptionGroup): """A group of command line options. :param str name: The groups name, used to create the --help-{name} option :param str description: Shown as title of the groups help view :param str help_description: Shown as help to the --help-{name} option :param list option_list: The options used in this group, must be option.Option() :param dict defaults: A dicitionary of default values :param translation_domain: Sets the translation domain for gettext(). .. NOTE:: This OptionGroup does not exactly map the optparse.OptionGroup interface. There is no parser object to supply, but it is possible to set default values and option_lists. Also the default values and values are not shared with the OptionParser. To pass a OptionGroup into a function which expects a GOptionGroup (e.g. gnome_program_init() ). OptionGroup.get_option_group() can be used. For further help, see optparse.OptionGroup. """ def __init__( self, name, description, help_description="", option_list=None, defaults=None, translation_domain=None, ): warnings.warn( "gi.repository.GLib.option.OptionGroup is deprecated, use gi.repository.GLib.OptionContext instead", PyGIDeprecationWarning, stacklevel=2, ) optparse.OptionContainer.__init__(self, Option, "error", description) self.name = name self.parser = None self.help_description = help_description if defaults: self.defaults = defaults self.values = None self.translation_domain = translation_domain if option_list: for option in option_list: self.add_option(option) def _create_option_list(self): self.option_list = [] self._create_option_mappings() def _to_goptiongroup(self, parser): def callback(option_name, option_value, group): if option_name.startswith("--"): opt = self._long_opt[option_name] else: opt = self._short_opt[option_name] try: opt.process(option_name, option_value, self.values, parser) except OptionValueError: error = sys.exc_info()[1] gerror = GError(str(error)) gerror.domain = OPTION_CONTEXT_ERROR_QUARK gerror.code = GLib.OptionError.BAD_VALUE gerror.message = str(error) raise gerror group = _gi.OptionGroup( self.name, self.description, self.help_description, callback ) if self.translation_domain: group.set_translation_domain(self.translation_domain) entries = [] for option in self.option_list: entries.extend(option._to_goptionentries()) group.add_entries(entries) return group def get_option_group(self, parser=None): """Returns the corresponding GOptionGroup object. Can be used as parameter for gnome_program_init(), gtk_init(). """ self.set_values_to_defaults() return self._to_goptiongroup(parser) def set_values_to_defaults(self): for option in self.option_list: default = self.defaults.get(option.dest) if isinstance(default, str): opt_str = option.get_opt_string() self.defaults[option.dest] = option.check_value(opt_str, default) self.values = optparse.Values(self.defaults) class OptionParser(optparse.OptionParser): """Command line parser with GOption support. :param bool help_enabled: The --help, --help-all and --help-{group} options are enabled (default). :param bool ignore_unknown_options: Do not throw a exception when a option is not knwon, the option will be in the result list. .. NOTE:: The OptionParser interface is not the exactly the same as the optparse.OptionParser interface. Especially the usage parameter is only used to show the metavar of the arguements. OptionParser.add_option_group() does not only accept OptionGroup instances but also glib.OptionGroup, which is returned by gtk_get_option_group(). Only glib.option.OptionGroup and glib.option.Option instances should be passed as groups and options. For further help, see optparse.OptionParser. """ def __init__(self, *args, **kwargs): warnings.warn( "gi.repository.GLib.option.OptionParser is deprecated, use gi.repository.GLib.OptionContext instead", PyGIDeprecationWarning, stacklevel=2, ) if "option_class" not in kwargs: kwargs["option_class"] = Option self.help_enabled = kwargs.pop("help_enabled", True) self.ignore_unknown_options = kwargs.pop("ignore_unknown_options", False) optparse.OptionParser.__init__(self, add_help_option=False, *args, **kwargs) def set_usage(self, usage): if usage is None: self.usage = "" elif usage.startswith("%prog"): self.usage = usage[len("%prog") :] else: self.usage = usage def _to_goptioncontext(self, values): if self.description: parameter_string = self.usage + " - " + self.description else: parameter_string = self.usage context = _gi.OptionContext(parameter_string) context.set_help_enabled(self.help_enabled) context.set_ignore_unknown_options(self.ignore_unknown_options) for option_group in self.option_groups: if isinstance(option_group, _gi.OptionGroup): g_group = option_group else: g_group = option_group.get_option_group(self) context.add_group(g_group) def callback(option_name, option_value, group): if option_name.startswith("--"): opt = self._long_opt[option_name] else: opt = self._short_opt[option_name] opt.process(option_name, option_value, values, self) main_group = _gi.OptionGroup(None, None, None, callback) main_entries = [] for option in self.option_list: main_entries.extend(option._to_goptionentries()) main_group.add_entries(main_entries) context.set_main_group(main_group) return context def add_option_group(self, *args, **kwargs): if isinstance(args[0], str): optparse.OptionParser.add_option_group( self, OptionGroup(self, *args, **kwargs) ) return if len(args) == 1 and not kwargs: if isinstance(args[0], OptionGroup): if not args[0].parser: args[0].parser = self if args[0].parser is not self: raise ValueError("invalid OptionGroup (wrong parser)") if isinstance(args[0], _gi.OptionGroup): self.option_groups.append(args[0]) return optparse.OptionParser.add_option_group(self, *args, **kwargs) def _get_all_options(self): options = self.option_list[:] for group in self.option_groups: if isinstance(group, optparse.OptionGroup): options.extend(group.option_list) return options def _process_args(self, largs, rargs, values): context = self._to_goptioncontext(values) # _process_args() returns the remaining parameters in rargs. # The prepended program name is used to all g_set_prgname() # The program name is cut away so it doesn't appear in the result. rargs[:] = context.parse([sys.argv[0], *rargs])[1:] def parse_args(self, args=None, values=None): try: options, args = optparse.OptionParser.parse_args(self, args, values) except GError: error = sys.exc_info()[1] if error.domain != OPTION_CONTEXT_ERROR_QUARK: raise if error.code == GLib.OptionError.BAD_VALUE: raise OptionValueError(error.message) if error.code == GLib.OptionError.UNKNOWN_OPTION: raise BadOptionError(error.message) if error.code == GLib.OptionError.FAILED: raise OptParseError(error.message) raise for group in self.option_groups: for key, value in group.values.__dict__.items(): options.ensure_value(key, value) return options, args make_option = Option ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/_ossighelper.py0000664000000000000000000002063615074673150016011 0ustar00rootroot# Copyright 2017 Christoph Reiter # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, see . import os import socket import signal import asyncio import threading from contextlib import closing, contextmanager from . import _gi def ensure_socket_not_inheritable(sock): """Ensures that the socket is not inherited by child processes. Raises: EnvironmentError NotImplementedError: With Python <3.4 on Windows """ if hasattr(sock, "set_inheritable"): sock.set_inheritable(False) else: try: import fcntl except ImportError: raise NotImplementedError("Not implemented for older Python on Windows") else: fd = sock.fileno() flags = fcntl.fcntl(fd, fcntl.F_GETFD) fcntl.fcntl(fd, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC) _wakeup_fd_is_active = False """Since we can't check if set_wakeup_fd() is already used for nested event loops without introducing a race condition we keep track of it globally. """ @contextmanager def wakeup_on_signal(): """A decorator for functions which create a glib event loop to keep Python signal handlers working while the event loop is idling. In case an OS signal is received will wake the default event loop up shortly so that any registered Python signal handlers registered through signal.signal() can run. In case the wrapped function is not called from the main thread it will be called as is and it will not wake up the default loop for signals. """ global _wakeup_fd_is_active if _wakeup_fd_is_active: yield return from gi.repository import GLib read_socket, write_socket = socket.socketpair() with closing(read_socket), closing(write_socket): for sock in [read_socket, write_socket]: sock.setblocking(False) ensure_socket_not_inheritable(sock) try: orig_fd = signal.set_wakeup_fd(write_socket.fileno()) except ValueError: # Raised in case this is not the main thread -> give up. yield return else: _wakeup_fd_is_active = True def signal_notify(source, condition): if condition & GLib.IO_IN: try: return bool(read_socket.recv(1)) except OSError: return False return True return False try: if os.name == "nt": channel = GLib.IOChannel.win32_new_socket(read_socket.fileno()) else: channel = GLib.IOChannel.unix_new(read_socket.fileno()) source_id = GLib.io_add_watch( channel, GLib.PRIORITY_DEFAULT, ( GLib.IOCondition.IN | GLib.IOCondition.HUP | GLib.IOCondition.NVAL | GLib.IOCondition.ERR ), signal_notify, ) try: yield finally: GLib.source_remove(source_id) finally: write_fd = signal.set_wakeup_fd(orig_fd) if write_fd != write_socket.fileno(): # Someone has called set_wakeup_fd while func() was active, # so let's re-revert again. signal.set_wakeup_fd(write_fd) _wakeup_fd_is_active = False PyOS_getsig = _gi.pyos_getsig PyOS_setsig = _gi.pyos_setsig # We save the signal pointer so we can detect if glib has changed the # signal handler behind Python's back (GLib.unix_signal_add) if signal.getsignal(signal.SIGINT) is signal.default_int_handler: startup_sigint_ptr = PyOS_getsig(signal.SIGINT) else: # Something has set the handler before import, we can't get a ptr # for the default handler so make sure the pointer will never match. startup_sigint_ptr = -1 def sigint_handler_is_default(): """Returns if on SIGINT the default Python handler would be called.""" return ( signal.getsignal(signal.SIGINT) is signal.default_int_handler and PyOS_getsig(signal.SIGINT) == startup_sigint_ptr ) @contextmanager def sigint_handler_set_and_restore_default(handler): """Context manager for saving/restoring the SIGINT handler default state. Will only restore the default handler again if the handler is not changed while the context is active. """ assert sigint_handler_is_default() signal.signal(signal.SIGINT, handler) sig_ptr = PyOS_getsig(signal.SIGINT) try: yield finally: if ( signal.getsignal(signal.SIGINT) is handler and PyOS_getsig(signal.SIGINT) == sig_ptr ): signal.signal(signal.SIGINT, signal.default_int_handler) def is_main_thread(): """Returns True in case the function is called from the main thread.""" return threading.current_thread().name == "MainThread" _callback_stack = [] _sigint_called = False @contextmanager def register_sigint_fallback(callback): """Installs a SIGINT signal handler in case the default Python one is active which calls 'callback' in case the signal occurs. Only does something if called from the main thread. In case of nested context managers the signal handler will be only installed once and the callbacks will be called in the reverse order of their registration. The old signal handler will be restored in case no signal handler is registered while the context is active. """ # To handle multiple levels of event loops we need to call the last # callback first, wait until the inner most event loop returns control # and only then call the next callback, and so on... until we # reach the outer most which manages the signal handler and raises # in the end global _callback_stack, _sigint_called if not is_main_thread(): yield return if not sigint_handler_is_default(): if _callback_stack: # This is an inner event loop, append our callback # to the stack so the parent context can call it. _callback_stack.append(callback) try: yield finally: cb = _callback_stack.pop() if _sigint_called: cb() else: # There is a signal handler set by the user, just do nothing yield return _sigint_called = False def sigint_handler(sig_num, frame): global _callback_stack, _sigint_called if _sigint_called: return _sigint_called = True _callback_stack.pop()() _callback_stack.append(callback) try: with sigint_handler_set_and_restore_default(sigint_handler): yield finally: if _sigint_called: signal.default_int_handler(signal.SIGINT, None) else: _callback_stack.pop() class DummyEventLoop: @classmethod @contextmanager def paused(cls): yield @classmethod @contextmanager def running(cls, quit_func): with wakeup_on_signal(): yield def get_event_loop(ctx): """Return the correct GLibEventLoop or a dummy that just registers the signal wakeup mechanism. """ from . import events # Try to use the running loop. If there is none, get the policy and # try getting one in the hope that this will give us an event loop for the # correct context. loop = asyncio._get_running_loop() if loop is None: policy = asyncio.get_event_loop_policy() if isinstance(policy, events.GLibEventLoopPolicy): loop = policy.get_event_loop_for_context(ctx) if ( isinstance(loop, events.GLibEventLoop) and ctx is not None and hash(loop._context) == hash(ctx) ): return loop return DummyEventLoop ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/_propertyhelper.py0000664000000000000000000003377015074673150016554 0ustar00rootroot# pygobject - Python bindings for the GObject library # Copyright (C) 2007 Johan Dahlin # # gi/_propertyhelper.py: GObject property wrapper/helper # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, see . from . import _gi from ._constants import ( TYPE_NONE, TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR, TYPE_BOOLEAN, TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_INT64, TYPE_UINT64, TYPE_ENUM, TYPE_FLAGS, TYPE_FLOAT, TYPE_DOUBLE, TYPE_STRING, TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV, TYPE_VARIANT, ) G_MAXFLOAT = _gi.G_MAXFLOAT G_MAXDOUBLE = _gi.G_MAXDOUBLE G_MININT = _gi.G_MININT G_MAXINT = _gi.G_MAXINT G_MAXUINT = _gi.G_MAXUINT G_MINLONG = _gi.G_MINLONG G_MAXLONG = _gi.G_MAXLONG G_MAXULONG = _gi.G_MAXULONG class Property: """Creates a new Property which when used in conjunction with GObject subclass will create a Python property accessor for the GObject ParamSpec. :param callable getter: getter to get the value of the property :param callable setter: setter to set the value of the property :param type type: type of property :param default: default value, must match the property type. :param str nick: short description :param str blurb: long description :param GObject.ParamFlags flags: parameter flags :keyword minimum: minimum allowed value (int, float, long only) :keyword maximum: maximum allowed value (int, float, long only) .. code-block:: python class MyObject(GObject.Object): prop = GObject.Property(type=str) obj = MyObject() obj.prop = "value" obj.prop # now is 'value' The API is similar to the builtin :py:func:`property`: .. code-block:: python class AnotherObject(GObject.Object): value = 0 @GObject.Property def prop(self): "Read only property." return 1 @GObject.Property(type=int) def propInt(self): "Read-write integer property." return self.value @propInt.setter def propInt(self, value): self.value = value """ _type_from_pytype_lookup = { int: TYPE_INT, bool: TYPE_BOOLEAN, float: TYPE_DOUBLE, str: TYPE_STRING, object: TYPE_PYOBJECT, } _min_value_lookup = { TYPE_UINT: 0, TYPE_ULONG: 0, TYPE_UINT64: 0, # Remember that G_MINFLOAT and G_MINDOUBLE are something different. TYPE_FLOAT: -G_MAXFLOAT, TYPE_DOUBLE: -G_MAXDOUBLE, TYPE_INT: G_MININT, TYPE_LONG: G_MINLONG, TYPE_INT64: -(2**63), } _max_value_lookup = { TYPE_UINT: G_MAXUINT, TYPE_ULONG: G_MAXULONG, TYPE_INT64: 2**63 - 1, TYPE_UINT64: 2**64 - 1, TYPE_FLOAT: G_MAXFLOAT, TYPE_DOUBLE: G_MAXDOUBLE, TYPE_INT: G_MAXINT, TYPE_LONG: G_MAXLONG, } _default_lookup = { TYPE_INT: 0, TYPE_UINT: 0, TYPE_LONG: 0, TYPE_ULONG: 0, TYPE_INT64: 0, TYPE_UINT64: 0, TYPE_STRING: "", TYPE_FLOAT: 0.0, TYPE_DOUBLE: 0.0, } class __metaclass__(type): def __repr__(self): return "" def __init__( self, getter=None, setter=None, type=None, default=None, nick="", blurb="", flags=_gi.PARAM_READWRITE, minimum=None, maximum=None, ): self.name = None if type is None: type = object self.type = self._type_from_python(type) self.default = self._get_default(default) self._check_default() if not isinstance(nick, str): raise TypeError("nick must be a string") self.nick = nick if not isinstance(blurb, str): raise TypeError("blurb must be a string") self.blurb = blurb # Always clobber __doc__ with blurb even if blurb is empty because # we don't want the lengthy Property class documentation showing up # on instances. self.__doc__ = blurb self.flags = flags # Call after setting blurb for potential __doc__ usage. if getter and not setter: setter = self._readonly_setter elif setter and not getter: getter = self._writeonly_getter elif not setter and not getter: getter = self._default_getter setter = self._default_setter self.getter(getter) # do not call self.setter() here, as this defines the property name # already self.fset = setter if minimum is not None: if minimum < self._get_minimum(): msg = f"Minimum for type {self.type:s} cannot be lower than {self._get_minimum():d}" raise TypeError(msg) else: minimum = self._get_minimum() self.minimum = minimum if maximum is not None: if maximum > self._get_maximum(): msg = f"Maximum for type {self.type:s} cannot be higher than {self._get_maximum():d}" raise TypeError(msg) else: maximum = self._get_maximum() self.maximum = maximum self._exc = None def __repr__(self): return f"" def __get__(self, instance, klass): if instance is None: return self self._exc = None value = self.fget(instance) if self._exc: exc = self._exc self._exc = None raise exc return value def __set__(self, instance, value): if instance is None: raise TypeError self._exc = None instance.set_property(self.name, value) if self._exc: exc = self._exc self._exc = None raise exc def __call__(self, fget): """Allows application of the getter along with init arguments.""" return self.getter(fget) def getter(self, fget): """Set the getter function to fget. For use as a decorator.""" if fget.__doc__: # Always clobber docstring and blurb with the getter docstring. self.blurb = fget.__doc__ self.__doc__ = fget.__doc__ self.fget = fget return self def setter(self, fset): """Set the setter function to fset. For use as a decorator.""" self.fset = fset # with a setter decorator, we must ignore the name of the method in # install_properties, as this does not need to be a valid property name # and does not define the property name. So set the name here. if not self.name: self.name = self.fget.__name__ return self def _type_from_python(self, type_): if type_ in self._type_from_pytype_lookup: return self._type_from_pytype_lookup[type_] if isinstance(type_, type) and issubclass( type_, (_gi.GObject, _gi.GEnum, _gi.GFlags, _gi.GBoxed, _gi.GInterface) ): return type_.__gtype__ if type_ in ( TYPE_NONE, TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR, TYPE_INT, TYPE_UINT, TYPE_BOOLEAN, TYPE_LONG, TYPE_ULONG, TYPE_INT64, TYPE_UINT64, TYPE_FLOAT, TYPE_DOUBLE, TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, TYPE_STRING, TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV, TYPE_VARIANT, ): return type_ raise TypeError(f"Unsupported type: {type_!r}") def _get_default(self, default): if default is not None: return default return self._default_lookup.get(self.type, None) def _check_default(self): ptype = self.type default = self.default if ptype == TYPE_BOOLEAN and (default not in (True, False)): raise TypeError(f"default must be True or False, not {default!r}") if ptype == TYPE_PYOBJECT: if default is not None: raise TypeError("object types does not have default values") elif ptype == TYPE_GTYPE: if default is not None: raise TypeError("GType types does not have default values") elif ptype.is_a(TYPE_ENUM): if default is None: raise TypeError("enum properties needs a default value") if not _gi.GType(default).is_a(ptype): raise TypeError( f"enum value {default} must be an instance of {ptype!r}" ) elif ptype.is_a(TYPE_FLAGS): if not _gi.GType(default).is_a(ptype): raise TypeError( f"flags value {default} must be an instance of {ptype!r}" ) elif ptype.is_a(TYPE_STRV) and default is not None: if not isinstance(default, list): raise TypeError(f"Strv value {default!r} must be a list") for val in default: if type(val) not in (str, bytes): raise TypeError(f"Strv value {default!s} must contain only strings") elif ( ptype.is_a(TYPE_VARIANT) and default is not None and ( not hasattr(default, "__gtype__") or not _gi.GType(default).is_a(TYPE_VARIANT) ) ): raise TypeError(f"variant value {default} must be an instance of {ptype!r}") def _get_minimum(self): return self._min_value_lookup.get(self.type, None) def _get_maximum(self): return self._max_value_lookup.get(self.type, None) # # Getter and Setter # def _default_setter(self, instance, value): setattr(instance, "_property_helper_" + self.name, value) def _default_getter(self, instance): return getattr(instance, "_property_helper_" + self.name, self.default) def _readonly_setter(self, instance, value): self._exc = TypeError( f"{self.name} property of {type(instance).__name__} is read-only" ) def _writeonly_getter(self, instance): self._exc = TypeError( f"{self.name} property of {type(instance).__name__} is write-only" ) # # Public API # def get_pspec_args(self): ptype = self.type if ptype in ( TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_INT64, TYPE_UINT64, TYPE_FLOAT, TYPE_DOUBLE, ): args = self.minimum, self.maximum, self.default elif ( ptype in (TYPE_STRING, TYPE_BOOLEAN) or ptype.is_a(TYPE_ENUM) or ptype.is_a(TYPE_FLAGS) or ptype.is_a(TYPE_VARIANT) ): args = (self.default,) elif ( ptype in (TYPE_PYOBJECT, TYPE_GTYPE) or ptype.is_a(TYPE_OBJECT) or ptype.is_a(TYPE_BOXED) ): args = () else: raise NotImplementedError(ptype) return (self.type, self.nick, self.blurb, *args, self.flags) def install_properties(cls): """Scans the given class for instances of Property and merges them into the classes __gproperties__ dict if it exists or adds it if not. """ gproperties = cls.__dict__.get("__gproperties__", {}) props = [] for name, prop in cls.__dict__.items(): if isinstance(prop, Property): # not same as the built-in # if a property was defined with a decorator, it may already have # a name; if it was defined with an assignment (prop = Property(...)) # we set the property's name to the member name if not prop.name: prop.name = name # we will encounter the same property multiple times in case of # custom setter methods if prop.name in gproperties: if gproperties[prop.name] == prop.get_pspec_args(): continue raise ValueError( f"Property {prop.name} was already found in __gproperties__" ) gproperties[prop.name] = prop.get_pspec_args() props.append(prop) if not props: return cls.__gproperties__ = gproperties if "do_get_property" in cls.__dict__ or "do_set_property" in cls.__dict__: for prop in props: if prop.fget != prop._default_getter or prop.fset != prop._default_setter: raise TypeError( f"GObject subclass {cls.__name__!r} defines do_get/set_property" " and it also uses a property with a custom setter" " or getter. This is not allowed" ) def obj_get_property(self, pspec): name = pspec.name.replace("-", "_") return getattr(self, name, None) cls.do_get_property = obj_get_property def obj_set_property(self, pspec, value): name = pspec.name.replace("-", "_") prop = getattr(cls, name, None) if prop: prop.fset(self, value) cls.do_set_property = obj_set_property ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/_signalhelper.py0000664000000000000000000002244415074673150016141 0ustar00rootroot# pygobject - Python bindings for the GObject library # Copyright (C) 2012 Simon Feltman # # gi/_signalhelper.py: GObject signal binding decorator object # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, see . from . import _gi class Signal(str): """Object which gives a nice API for creating and binding signals. :param name: Name of signal or callable closure when used as a decorator. :type name: str or callable :param callable func: Callable closure method. :param GObject.SignalFlags flags: Flags specifying when to run closure. :param type return_type: Return type of the Signal. :param list arg_types: List of argument types specifying the signals function signature :param str doc: Documentation of signal object. :param callable accumulator: Accumulator method with the signature: func(ihint, return_accu, handler_return, accu_data) -> boolean :param object accu_data: User data passed to the accumulator. :Example: .. code-block:: python class Spam(GObject.Object): velocity = 0 @GObject.Signal def pushed(self): self.velocity += 1 @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST) def pulled(self): self.velocity -= 1 stomped = GObject.Signal('stomped', arg_types=(int,)) @GObject.Signal def annotated_signal(self, a:int, b:str): "Python3 annotation support for parameter types. def on_pushed(obj): print(obj) spam = Spam() spam.pushed.connect(on_pushed) spam.pushed.emit() """ class BoundSignal(str): """Temporary binding object which can be used for connecting signals without specifying the signal name string to connect. """ def __new__(cls, name, *args, **kargs): return str.__new__(cls, name) def __init__(self, signal, gobj): str.__init__(self) self.signal = signal self.gobj = gobj def __repr__(self): return f'BoundSignal("{self}")' def __call__(self, *args, **kargs): """Call the signals closure.""" return self.signal.func(self.gobj, *args, **kargs) def connect(self, callback, *args, **kargs): """Same as GObject.Object.connect except there is no need to specify the signal name. """ return self.gobj.connect(self, callback, *args, **kargs) def connect_detailed(self, callback, detail, *args, **kargs): """Same as GObject.Object.connect except there is no need to specify the signal name. In addition concats "::" to the signal name when connecting; for use with notifications like "notify" when a property changes. """ return self.gobj.connect(self + "::" + detail, callback, *args, **kargs) def disconnect(self, handler_id): """Same as GObject.Object.disconnect.""" self.gobj.disconnect(handler_id) def emit(self, *args, **kargs): """Same as GObject.Object.emit except there is no need to specify the signal name. """ return self.gobj.emit(str(self), *args, **kargs) def __new__(cls, name="", *args, **kargs): if callable(name): name = name.__name__ return str.__new__(cls, name) def __init__( self, name="", func=None, flags=_gi.SIGNAL_RUN_FIRST, return_type=None, arg_types=None, doc="", accumulator=None, accu_data=None, ): if func is None and callable(name): func = name if func and not doc: doc = func.__doc__ str.__init__(self) if func and not (return_type or arg_types): return_type, arg_types = get_signal_annotations(func) if arg_types is None: arg_types = () self.func = func self.flags = flags self.return_type = return_type self.arg_types = arg_types self.__doc__ = doc self.accumulator = accumulator self.accu_data = accu_data def __get__(self, instance, owner=None): """Returns a BoundSignal when accessed on an object instance.""" if instance is None: return self return self.BoundSignal(self, instance) def __call__(self, obj, *args, **kargs): """Allows for instantiated Signals to be used as a decorator or calling of the underlying signal method. """ # If obj is a GObject, than we call this signal as a closure otherwise # it is used as a re-application of a decorator. if isinstance(obj, _gi.GObject): self.func(obj, *args, **kargs) else: # If self is already an allocated name, use it otherwise create a new named # signal using the closure name as the name. name = str(self) if str(self) else obj.__name__ # Return a new value of this type since it is based on an immutable string. return type(self)( name=name, func=obj, flags=self.flags, return_type=self.return_type, arg_types=self.arg_types, doc=self.__doc__, accumulator=self.accumulator, accu_data=self.accu_data, ) return None def copy(self, newName=None): """Returns a renamed copy of the Signal.""" return type(self)( name=newName, func=self.func, flags=self.flags, return_type=self.return_type, arg_types=self.arg_types, doc=self.__doc__, accumulator=self.accumulator, accu_data=self.accu_data, ) def get_signal_args(self): """Returns a tuple of: (flags, return_type, arg_types, accumulator, accu_data).""" return ( self.flags, self.return_type, self.arg_types, self.accumulator, self.accu_data, ) class SignalOverride(Signal): """Specialized sub-class of Signal which can be used as a decorator for overriding existing signals on GObjects. :Example: .. code-block:: python class MyWidget(Gtk.Widget): @GObject.SignalOverride def configure_event(self): pass """ def get_signal_args(self): """Returns the string 'override'.""" return "override" def get_signal_annotations(func): """Attempt pulling python 3 function annotations off of 'func' for use as a signals type information. Returns an ordered nested tuple of (return_type, (arg_type1, arg_type2, ...)). If the given function does not have annotations then (None, tuple()) is returned. """ arg_types = () return_type = None if hasattr(func, "__annotations__"): # import inspect only when needed because it takes ~10 msec to load import inspect spec = inspect.getfullargspec(func) arg_types = tuple( spec.annotations[arg] for arg in spec.args if arg in spec.annotations ) if "return" in spec.annotations: return_type = spec.annotations["return"] return return_type, arg_types def install_signals(cls): """Adds Signal instances on a GObject derived class into the '__gsignals__' dictionary to be picked up and registered as real GObject signals. """ gsignals = cls.__dict__.get("__gsignals__", {}) newsignals = {} for name, signal in cls.__dict__.items(): if isinstance(signal, Signal): signalName = str(signal) # Fixup a signal which is unnamed by using the class variable name. # Since Signal is based on string which immutable, # we must copy and replace the class variable. if not signalName: signalName = name signal = signal.copy(name) setattr(cls, name, signal) if signalName in gsignals: raise ValueError(f'Signal "{name}" has already been registered.') newsignals[signalName] = signal gsignals[signalName] = signal.get_signal_args() cls.__gsignals__ = gsignals # Setup signal closures by adding the specially named # method to the class in the form of "do_". for name, signal in newsignals.items(): if signal.func is not None: funcName = "do_" + name.replace("-", "_") if not hasattr(cls, funcName): setattr(cls, funcName, signal.func) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/_signature.py0000664000000000000000000001445715074673150015472 0ustar00rootroot# Copyright (C) 2024 James Henstridge # # _signature.py: callable signature generator for gi. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA from importlib import import_module from inspect import Parameter, Signature from typing import Any, Callable, Optional from ._error import GError from ._gi import ( VFuncInfo, FunctionInfo, CallableInfo, CallbackInfo, Direction, GType, TypeInfo, TypeTag, ) __all__ = ["generate_signature"] tag_pytype = { TypeTag.BOOLEAN: bool, TypeTag.INT8: int, TypeTag.UINT8: int, TypeTag.INT16: int, TypeTag.UINT16: int, TypeTag.INT32: int, TypeTag.UINT32: int, TypeTag.INT64: int, TypeTag.UINT64: int, TypeTag.FLOAT: float, TypeTag.DOUBLE: float, TypeTag.GTYPE: GType, TypeTag.UTF8: str, TypeTag.FILENAME: str, TypeTag.UNICHAR: str, TypeTag.ERROR: GError, } list_tag_types = {TypeTag.GLIST, TypeTag.GSLIST, TypeTag.ARRAY} def get_pytype(gi_type: TypeInfo) -> object: tag = gi_type.get_tag() if pytype := tag_pytype.get(tag): return pytype if tag == TypeTag.VOID: if gi_type.is_pointer(): return Any return None if tag in list_tag_types: value_type = get_pytype(gi_type.get_param_type(0)) if value_type is Parameter.empty: return list return list[value_type] if tag == TypeTag.GHASH: key_type = get_pytype(gi_type.get_param_type(0)) value_type = get_pytype(gi_type.get_param_type(1)) if key_type is Parameter.empty or value_type is Parameter.empty: return dict return dict[key_type, value_type] if tag == TypeTag.INTERFACE: info = gi_type.get_interface() if isinstance(info, CallbackInfo): sig = generate_signature(info) return Callable[ [param.annotation for param in sig.parameters.values()], sig.return_annotation, ] info_name = info.get_name() if not info_name: return gi_type.get_tag_as_string() info_namespace = info.get_namespace() module = import_module(f"gi.repository.{info_namespace}") try: return getattr(module, info_name) except NotImplementedError: return f"{info_namespace}.{info_name}" else: return gi_type.get_tag_as_string() def generate_signature(info: CallableInfo) -> Signature: args = info.get_arguments() arg_names = {arg.get_name() for arg in args} def unique(name): while name in arg_names: name += "_" arg_names.add(name) return name params = [] if isinstance(info, FunctionInfo): if info.is_constructor(): params.append(Parameter(unique("cls"), Parameter.POSITIONAL_OR_KEYWORD)) elif info.is_method(): params.append(Parameter(unique("self"), Parameter.POSITIONAL_OR_KEYWORD)) elif isinstance(info, VFuncInfo): params.append(Parameter(unique("type"), Parameter.POSITIONAL_OR_KEYWORD)) params.append(Parameter(unique("self"), Parameter.POSITIONAL_OR_KEYWORD)) # Build lists of indices prior to adding the docs because it is possible # the index retrieved comes before input arguments being used. ignore_indices = {info.get_return_type().get_array_length_index()} user_data_indices = set() for arg in args: ignore_indices.add(arg.get_destroy_index()) ignore_indices.add(arg.get_type_info().get_array_length_index()) user_data_indices.add(arg.get_closure_index()) for i, arg in enumerate(args): if arg.get_direction() == Direction.OUT: continue # skip exclusively output args if i in ignore_indices: continue default = Parameter.empty annotation = get_pytype(arg.get_type_info()) if arg.may_be_null() or i in user_data_indices: # allow-none or user_data from a closure default = None if annotation is not Parameter.empty and annotation is not Any: annotation = Optional[annotation] elif arg.is_optional(): # TODO: Can we retrieve the default value? default = ... params.append( Parameter( arg.get_name(), Parameter.POSITIONAL_OR_KEYWORD, default=default, annotation=annotation, ) ) # Remove defaults from params after the last required parameter. last_required = max( (i for (i, param) in enumerate(params) if param.default is Parameter.empty), default=0, ) for i, param in enumerate(params): if i >= last_required: break if param.default is not Parameter.empty: params[i] = param.replace(default=Parameter.empty) return_annotation = get_pytype(info.get_return_type()) if info.may_return_null(): return_annotation = Optional[return_annotation] out_args = [] for i, arg in enumerate(args): if arg.get_direction() == Direction.IN: continue # skip exclusively input args if i in ignore_indices: continue annotation = get_pytype(arg.get_type_info()) if arg.may_be_null() and annotation is not Parameter.empty: annotation = Optional[annotation] out_args.append(annotation) if return_annotation is not None: out_args.insert(0, return_annotation) if len(out_args) > 1: return_annotation = tuple[tuple(out_args)] elif len(out_args) == 1: return_annotation = out_args[0] return Signature(params, return_annotation=return_annotation) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/docstring.py0000664000000000000000000001377315074673150015326 0ustar00rootroot# Copyright (C) 2013 Simon Feltman # # docstring.py: documentation string generator for gi. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA from ._gi import ( VFuncInfo, FunctionInfo, CallableInfo, ObjectInfo, StructInfo, Direction, TypeTag, ) #: Module storage for currently registered doc string generator function. _generate_doc_string_func = None def set_doc_string_generator(func): """Set doc string generator function. :param callable func: Callable which takes a GIInfoStruct and returns documentation for it. """ global _generate_doc_string_func _generate_doc_string_func = func def get_doc_string_generator(): """Returns the currently registered doc string generator.""" return _generate_doc_string_func def generate_doc_string(info): """Generate a doc string given a GIInfoStruct. :param gi.types.BaseInfo info: GI info instance to generate documentation for. :returns: Generated documentation as a string. :rtype: str This passes the info struct to the currently registered doc string generator and returns the result. """ return _generate_doc_string_func(info) _type_tag_to_py_type = { TypeTag.BOOLEAN: bool, TypeTag.INT8: int, TypeTag.UINT8: int, TypeTag.INT16: int, TypeTag.UINT16: int, TypeTag.INT32: int, TypeTag.UINT32: int, TypeTag.INT64: int, TypeTag.UINT64: int, TypeTag.FLOAT: float, TypeTag.DOUBLE: float, TypeTag.GLIST: list, TypeTag.GSLIST: list, TypeTag.ARRAY: list, TypeTag.GHASH: dict, TypeTag.UTF8: str, TypeTag.FILENAME: str, TypeTag.UNICHAR: str, TypeTag.INTERFACE: None, TypeTag.GTYPE: None, TypeTag.ERROR: None, TypeTag.VOID: None, } def _get_pytype_hint(gi_type): type_tag = gi_type.get_tag() py_type = _type_tag_to_py_type.get(type_tag) if py_type and hasattr(py_type, "__name__"): return py_type.__name__ if type_tag == TypeTag.INTERFACE: iface = gi_type.get_interface() info_name = iface.get_name() if not info_name: return gi_type.get_tag_as_string() return f"{iface.get_namespace()}.{info_name}" return gi_type.get_tag_as_string() def _generate_callable_info_doc(info): in_args_strs = [] if isinstance(info, VFuncInfo) or ( isinstance(info, FunctionInfo) and info.is_method() ): in_args_strs = ["self"] args = info.get_arguments() hint_blacklist = ("void",) # Build lists of indices prior to adding the docs because it is possible # the index retrieved comes before input arguments being used. ignore_indices = {info.get_return_type().get_array_length_index()} user_data_indices = set() for arg in args: ignore_indices.add(arg.get_destroy_index()) ignore_indices.add(arg.get_type_info().get_array_length_index()) user_data_indices.add(arg.get_closure_index()) # Build input argument strings for i, arg in enumerate(args): if arg.get_direction() == Direction.OUT: continue # skip exclusively output args if i in ignore_indices: continue argstr = arg.get_name() hint = _get_pytype_hint(arg.get_type_info()) if hint not in hint_blacklist: argstr += ":" + hint if arg.may_be_null() or i in user_data_indices: # allow-none or user_data from a closure argstr += "=None" elif arg.is_optional(): argstr += "=" in_args_strs.append(argstr) in_args_str = ", ".join(in_args_strs) # Build return + output argument strings out_args_strs = [] return_hint = _get_pytype_hint(info.get_return_type()) if not info.skip_return() and return_hint and return_hint not in hint_blacklist: argstr = return_hint if info.may_return_null(): argstr += " or None" out_args_strs.append(argstr) for i, arg in enumerate(args): if arg.get_direction() == Direction.IN: continue # skip exclusively input args if i in ignore_indices: continue argstr = arg.get_name() hint = _get_pytype_hint(arg.get_type_info()) if hint not in hint_blacklist: argstr += ":" + hint out_args_strs.append(argstr) if out_args_strs: return f"{info.__name__}({in_args_str}) -> {', '.join(out_args_strs)}" return f"{info.__name__}({in_args_str})" def _generate_class_info_doc(info): header = "\n:Constructors:\n\n::\n\n" # start with \n to avoid auto indent of other lines doc = "" if isinstance(info, StructInfo): # Don't show default constructor for disguised (0 length) structs if info.get_size() > 0: doc += " " + info.get_name() + "()\n" else: doc += " " + info.get_name() + "(**properties)\n" for method_info in info.get_methods(): if method_info.is_constructor(): doc += " " + _generate_callable_info_doc(method_info) + "\n" if doc: return header + doc return "" def _generate_doc_dispatch(info): if isinstance(info, (ObjectInfo, StructInfo)): return _generate_class_info_doc(info) if isinstance(info, CallableInfo): return _generate_callable_info_doc(info) return "" set_doc_string_generator(_generate_doc_dispatch) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/events.py0000664000000000000000000007366115074673150014640 0ustar00rootroot# -*- Mode: Python; py-indent-offset: 4 -*- # pygobject - Python bindings for the GObject library # Copyright (C) 2021 Benjamin Berg # # gi/asyncio.py: GObject asyncio integration # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, see . __all__ = ["GLibEventLoop", "GLibEventLoopPolicy"] import contextlib import sys import asyncio from asyncio import coroutines import signal import threading import selectors import weakref import warnings from collections.abc import Mapping from contextlib import contextmanager from . import _ossighelper from gi.repository import GLib try: g_main_loop_run = super(GLib.MainLoop, GLib.MainLoop).run except AttributeError: g_main_loop_run = GLib.MainLoop.run class _IdleSource(GLib.Source): """Internal helper source for idle task handling The only advantage is that we can keep the source around. """ def __init__(self, loop): super().__init__() self._loop = loop # _may_iterate will be False anyway, but might as well set it self.set_can_recurse(False) def prepare(self): if not self._loop._may_iterate: return False, -1 return bool(self._loop._idle_tasks), -1 def check(self): if not self._loop._may_iterate: return False return bool(self._loop._idle_tasks) def dispatch(self, callback, args): self._loop._glib_idle_dispatch() return GLib.SOURCE_CONTINUE class GLibTask(asyncio.Task): """This is a simple asyncio.Task subclass that will be returned when using the GLibEventLoop. It adds functionality to set the priority that is used to iterate the task's coroutine. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._glib_idle_priority = GLib.PRIORITY_DEFAULT def set_priority(self, priority): """Set the GLib priority used to iterate the task's coroutine""" assert isinstance(priority, int) self._glib_idle_priority = priority def get_priority(self, priority): """Get the GLib priority used to iterate the task's coroutine""" return self._glib_idle_priority @classmethod def _factory(cls, loop, coro, **kwargs): return GLibTask(coro, loop=loop, **kwargs) class _GLibEventLoopMixin: """Base functionally required for both proactor and selector. The proactor/selector is always available through _selector, and we assume it has the following extra functionality that we provide: * _source: the GSource subclass * _dispatching: boolean whether it is dispatching currently * attach/detach: add/remove the GSource from the main context In principle, we simply override run_forever to call into GLib, with the assumption that a GSource is registered which will then call back into the python mainloop _run_once handler when needed. This in turn calls self._selector.select(), which means we just need to make sure to return our already prepared events at that point. """ def __init__(self, main_context): # A mainloop in case we want to run our context assert main_context is not None self._context = main_context self._main_loop = GLib.MainLoop.new(self._context, False) self._quit_funcs = [] self._idle_tasks = [] self._may_iterate = False @contextmanager def paused(self): """This context manager ensures the EventLoop is *not* being iterated. It purely exists to handle the case where python code iterates the main context more gracefully. """ # Nothing to do if we are not running or dispatched by ourselves if not self._may_iterate: yield return try: self._may_iterate = False self._selector.detach() yield finally: self._may_iterate = True self._selector.attach() @contextmanager def running(self, quit_func): """This context manager ensures the EventLoop is marked as running while other API is iterating its main context. The passed quit function is used to stop all recursion levels when stop() is called. """ assert self._context.acquire() self._quit_funcs.append(quit_func) # Nested main context iteration (by using glib API) if self.is_running(): try: yield finally: self._context.release() self._quit_funcs.pop() # Stop recursively if self._stopping: self._quit_funcs[-1]() return # Outermost nesting self._check_closed() self._set_coroutine_origin_tracking(self._debug) self._thread_id = threading.get_ident() old_agen_hooks = sys.get_asyncgen_hooks() sys.set_asyncgen_hooks( firstiter=self._asyncgen_firstiter_hook, finalizer=self._asyncgen_finalizer_hook, ) try: asyncio._set_running_loop(self) assert not self._selector._source._dispatching self._may_iterate = True self._selector.attach() self._idle_source = _IdleSource(self) self._idle_source.attach(self._context) self._idle_source.set_name("GLibEventLoop._idle_source") if self._idle_tasks: self._idle_source.set_priority(self._idle_tasks[0][0]) yield finally: self._may_iterate = False self._idle_source.destroy() self._idle_source = None self._selector.detach() self._context.release() self._thread_id = None asyncio._set_running_loop(None) with contextlib.suppress(AttributeError): self._set_coroutine_origin_tracking(False) sys.set_asyncgen_hooks(*old_agen_hooks) self._quit_funcs.pop() assert len(self._quit_funcs) == 0 self._stopping = False def time(self): return GLib.get_monotonic_time() / 1000000 def _get_timeout_ms(self): if not self.is_running(): warnings.warn( "GLibEventLoop is iterated without being marked as running. Missing override or invalid use of existing API!", RuntimeWarning, ) if self._stopping is True: warnings.warn( "GLibEventLoop is not stopping properly. Missing override or invalid use of existing API!", RuntimeWarning, ) if self._ready: return 0 if self._scheduled: # The time is floor'ed here. # Python dispatches everything ready within the next _clock_resolution. timeout = int((self._scheduled[0]._when - self.time()) * 1000) return timeout if timeout >= 0 else 0 return -1 def _call_soon(self, callback, args, context): try: # Try to access the corresponding Task (or whatever) through the # self parameter of the bound method. # If _glib_idle_priority does not exist or it is not a bound method # then we'll just catch the AttributeError exception. priority = callback.__self__._glib_idle_priority except AttributeError: priority = GLib.PRIORITY_DEFAULT if priority == GLib.PRIORITY_DEFAULT: # Just use the underlying python dispatch. return super()._call_soon(callback, args, context) handle = asyncio.Handle(callback, args, self, context) self._idle_tasks.append((priority, handle)) self._idle_tasks.sort(key=lambda x: x[0]) # Update priority self._idle_source.set_priority(self._idle_tasks[0][0]) return handle def _glib_dispatch(self): assert self._may_iterate # The idle source disables itself and we are in the other which will not recurse self._may_iterate = False self._run_once() self._may_iterate = True def _glib_idle_dispatch(self): assert self._may_iterate # Pause so that the main Source is not going to dispatch # Note that this is pretty expensive, we could optimize it by detecting # it when it happens and only doing the detach/attach dance if needed. with self.paused(): priority = self._idle_source.get_priority() ready_handles = [] while self._idle_tasks and self._idle_tasks[0][0] == priority: ready_handles.append(self._idle_tasks.pop(0)[1]) for handle in ready_handles: handle._run() # There are (new) tasks available to run, ensure the priority is correct if self._idle_tasks: self._idle_source.set_priority(self._idle_tasks[0][0]) def stop(self): # Simply quit the mainloop self._stopping = True if self._quit_funcs: self._quit_funcs[-1]() def __repr__(self): return ( f"<{self.__class__.__name__} running={self.is_running()} " f"closed={self.is_closed()} debug={self.get_debug()} " f"ctx=0x{hash(self._context):X} loop=0x{hash(self._main_loop):X}>" ) class _GLibEventLoopRunMixin: # This class exists so we don't need to copy the ProactorEventLoop.run_forever, # instead, we change the MRO using a metaclass, so that super() sees this class # when called in ProactorEventLoop.run_forever. def run_forever(self): # NOTE: self._check_running was only added in 3.8 (with a typo in 3.7) if self.is_running(): raise RuntimeError("This event loop is already running") with ( _ossighelper.register_sigint_fallback(self._main_loop.quit), self.running(self._main_loop.quit), ): g_main_loop_run(self._main_loop) class _SourceBase(GLib.Source): """Common Source functionality for both unix and win32""" def __init__(self, selector): super().__init__() self._dispatching = False # It is *not* safe to run the *python* part of the mainloop recursively. # This error must be caught further up in the chain, otherwise the # mainloop will be blocking without an obvious reason. self.set_can_recurse(False) self.set_name("python asyncio integration") # WARNING: We must not under *any* circumstance have a reference back # and creating a loop. The GLib.Source.__del__ handler sets the pointer # to NULL and the BaseEventLoop.__del__ tries to close the loop causing # FDs to be unregistered. # By making sure there are no references back we (hopefully) force the # GC to be well behaved and first clean up the eventloop and selector # before destroying the source. self._selector = weakref.ref(selector) self._ready = [] def _loop(self): return self._selector()._loop def dispatch(self, callback, args): # Now, wag the dog by its tail self._dispatching = True try: self._loop()._glib_dispatch() finally: self._dispatching = False return GLib.SOURCE_CONTINUE def _get_ready(self): if not self._dispatching: raise RuntimeError( "gi.asyncio.Selector.select only works while it is dispatching!" ) ready = self._ready self._ready = [] return ready class _SelectorMixin: """A Mixin for common functionality of the Selector and Proactor.""" def __init__(self, context, loop): super().__init__() self._context = context self._loop = loop self._fd_to_key = {} self._source = _Source(self) def close(self): if self._source: self._source.destroy() self._source = None super().close() def select(self, timeout=None): return self._source._get_ready() def _real_select(self, timeout=None): return super().select(timeout) if sys.platform != "win32": class GLibEventLoop( _GLibEventLoopMixin, _GLibEventLoopRunMixin, asyncio.SelectorEventLoop ): """An asyncio event loop that runs the python mainloop inside GLib. Based on the asyncio.SelectorEventLoop """ _GLIB_SIGNALS = { signal.SIGHUP, signal.SIGINT, signal.SIGTERM, signal.SIGUSR1, signal.SIGUSR2, signal.SIGWINCH, } # This is based on the selector event loop, but never actually runs select() # in the strict sense. # We use the selector to register all FDs with the main context using our # own GSource. For python timeouts/idle equivalent, we directly query them # from the context by providing the _get_timeout_ms function that the # GSource uses. This in turn accesses _ready and _scheduled to calculate # the timeout and whether python can dispatch anything non-FD based yet. # # The Selector select() method simply returns the information we already # collected. # # The rest is done by the mixin which overrides run_forever to simply # iterate the main context. def __init__(self, main_context): _GLibEventLoopMixin.__init__(self, main_context) # _UnixSelectorEventLoop uses _signal_handlers, we could do the same, # with the difference that close() would clean up the handlers for us. self.__signal_handlers = {} selector = _Selector(self._context, self) asyncio.SelectorEventLoop.__init__(self, selector) # Used by run_once to not busy loop if the timeout is floor'ed to zero self._clock_resolution = 1e-3 # Use our custom Task subclass self._task_factory = GLibTask._factory def add_signal_handler(self, sig, callback, *args): """Add a handler for UNIX signal""" if coroutines.iscoroutine(callback) or coroutines.iscoroutinefunction( callback ): raise TypeError("coroutines cannot be used with add_signal_handler()") self._check_closed() # Can be useful while testing failures # assert sig != signal.SIGALRM if sig not in self._GLIB_SIGNALS: return super().add_signal_handler(sig, callback, *args) # Pure python demands that there is only one signal handler source = self.__signal_handlers.get(sig, (None, None, None))[0] if source: source.destroy() # Set up a new source with a higher priority than our main one source = GLib.unix_signal_source_new(sig) source.set_name(f"asyncio signal watch for {sig}") source.set_priority(GLib.PRIORITY_HIGH) source.attach(self._context) source.set_callback(self._signal_cb, sig) self.__signal_handlers[sig] = (source, callback, args) del source return None def remove_signal_handler(self, sig): if sig not in self._GLIB_SIGNALS: return super().remove_signal_handler(sig) try: source, _, _ = self.__signal_handlers[sig] del self.__signal_handlers[sig] # Really unref the underlying GSource so that GLib resets the signal handler source.destroy() source._clear_boxed() # GLib does not restore the original signal handler. # Try to restore the python handler for SIGINT, this makes # Ctrl+C work after the mainloop has quit. if ( sig == signal.SIGINT and _ossighelper.PyOS_getsig(signal.SIGINT) == 0 and _ossighelper.startup_sigint_ptr > 0 ): _ossighelper.PyOS_setsig( signal.SIGINT, _ossighelper.startup_sigint_ptr ) return True except KeyError: return False def _signal_cb(self, sig): _source, cb, args = self.__signal_handlers.get(sig) # Pass over to python mainloop self.call_soon(cb, *args) def close(self): super().close() for s in list(self.__signal_handlers): self.remove_signal_handler(s) def _fileobj_to_fd(fileobj): # Note: SelectorEventloop should only be passing FDs if isinstance(fileobj, int): return fileobj return fileobj.fileno() class _Source(_SourceBase): def prepare(self): timeout = self._loop()._get_timeout_ms() # NOTE: Always return False, FDs are queried in check and the timeout # needs to be rechecked anyway. return False, timeout def check(self): ready = [] for key in self._selector()._fd_to_key.values(): condition = self.query_unix_fd(key._tag) events = 0 # ERR/HUP/NVAL trigger both read/write (PRI cannot happen) if condition & ~GLib.IOCondition.OUT: events |= selectors.EVENT_READ if condition & ~GLib.IOCondition.IN: events |= selectors.EVENT_WRITE if events: ready.append((key, events)) self._ready = ready timeout = self._loop()._get_timeout_ms() if timeout == 0: return True return bool(ready) class _SelectorKey(selectors.SelectorKey): # Subclass to attach _tag pass class _FileObjectMapping(Mapping): def __init__(self, fd_dict): self.fd_dict = fd_dict def __len__(self): return len(self.fd_dict) def get(self, fileobj, default=None): fd = _fileobj_to_fd(fileobj) return self.fd_dict.get(fd, default) def __getitem__(self, fileobj): value = self.get(fileobj) if value is None: raise KeyError(f"{fileobj!r} is not registered") return value def __iter__(self): return iter(self.fd_dict) class _Selector(_SelectorMixin, selectors.BaseSelector): """A Selector for gi.events.GLibEventLoop registering python IO with GLib.""" def __init__(self, context, loop): super().__init__(context, loop) self._map = _FileObjectMapping(self._fd_to_key) def attach(self): self._source.attach(self._loop._context) def detach(self): self._source.destroy() self._source = _Source(self) # re-register the keys with the new source for key in self._fd_to_key.values(): self._register_key(key) def _register_key(self, key): condition = GLib.IOCondition(0) if key.events & selectors.EVENT_READ: condition |= GLib.IOCondition.IN if key.events & selectors.EVENT_WRITE: condition |= GLib.IOCondition.OUT key._tag = self._source.add_unix_fd(key.fd, condition) def register(self, fileobj, events, data=None): if (not events) or ( events & ~(selectors.EVENT_READ | selectors.EVENT_WRITE) ): raise ValueError(f"Invalid events: {events!r}") fd = _fileobj_to_fd(fileobj) if fd in self._fd_to_key: raise KeyError(f"{fileobj!r} (FD {fd}) is already registered") key = _SelectorKey(fileobj, fd, events, data) self._register_key(key) self._fd_to_key[fd] = key return key def unregister(self, fileobj): # NOTE: may be called after __del__ has been called. fd = _fileobj_to_fd(fileobj) key = self._fd_to_key[fd] if self._source: self._source.remove_unix_fd(key._tag) del self._fd_to_key[fd] return key # We could override modify, but it is only slightly when the "events" change. def get_key(self, fileobj): return self._map[fileobj] def get_map(self): """Return a mapping of file objects or file descriptors to selector keys. """ return self._map else: class _PushRunMixinBackMeta(type): # This metaclass changes the MRO so that when run_forever is called, it # first calls asyncio.ProactorEventLoop and then chains into # _GLibEventLoopRunMixin.run_forever using super(). # The alternative would be to copy asyncio.ProactorEventLoop.run_forever def mro(cls): mro = type.mro(cls) idx = mro.index(_GLibEventLoopRunMixin) return [*mro[:idx], mro[idx + 1], mro[idx], *mro[idx + 2 :]] class GLibEventLoop( _GLibEventLoopMixin, _GLibEventLoopRunMixin, asyncio.ProactorEventLoop, metaclass=_PushRunMixinBackMeta, ): """An asyncio event loop that runs the python mainloop inside GLib. Based on the asyncio.WindowsProactorEventLoopPolicy """ # This is based on the Windows ProactorEventLoop def __init__(self, main_context): _GLibEventLoopMixin.__init__(self, main_context) proactor = _Proactor(self._context, self) # Sets both self._proactor and self._selector to the proactor asyncio.ProactorEventLoop.__init__(self, proactor) # Used by run_once to not busy loop if the timeout is floor'ed to zero self._clock_resolution = 1e-3 # Use our custom Task subclass self._task_factory = GLibTask._factory class _Source(_SourceBase): def __init__(self, proactor): super().__init__(proactor) # None denotes it is disabled (and will also not handle timeouts) self._poll_fd = None def enable(self): assert self._poll_fd is None self._poll_fd = GLib.PollFD(self._selector()._iocp, GLib.IO_IN) self.add_poll(self._poll_fd) def disable(self): self.remove_poll(self._poll_fd) self._poll_fd = None def prepare(self): # Disabled, do not handle timeouts either if self._poll_fd is None: return False, -1 timeout = self._loop()._get_timeout_ms() return bool(self._ready), timeout def check(self): if self._poll_fd is None: return False if self._poll_fd.revents: self._ready.extend(self._selector()._real_select(0)) if self._ready: return True return self._loop()._get_timeout_ms() == 0 class _Proactor(_SelectorMixin, asyncio.IocpProactor): """A Proactor for gi.events.GLibEventLoop registering python IO with GLib.""" def __init__(self, context, loop): super().__init__(context, loop) # We always use the same Source on windows, it disables itself self._source = _Source(self) self._source.attach(context) def attach(self): self._source.enable() def detach(self): self._source.disable() class GLibEventLoopPolicy(asyncio.AbstractEventLoopPolicy): """An asyncio event loop policy that runs the GLib main loop. The policy allows creating a new EventLoop for threads other than the main thread. For the main thread, you can use get_event_loop() to retrieve the correct mainloop and run it. Note that, unlike GLib, python does not support running the EventLoop recursively. You should never iterate the GLib.MainContext from within the python EventLoop as doing so prevents asyncio events from being dispatched. As such, do not use API such as GLib.MainLoop.run or Gtk.Dialog.run. Instead use the proper asynchronous patterns to prevent entirely blocking asyncio. """ def __init__(self): self._loops = {} self._child_watcher = None self.__orig_policy = None def get_event_loop(self): """Get the event loop for the current context. Returns an event loop object for the thread default GLib.MainContext or in case of the main thread for the default GLib.MainContext. An exception will be thrown if there is no GLib.MainContext for the current thread. In that case, using new_event_loop() will create a new main context and main loop which can subsequently attached to the thread by calling set_event_loop(). Returns a new GLibEventLoop or raises an exception. """ # Get the thread default main context ctx = GLib.MainContext.get_thread_default() # If there is none, and we are on the main thread, then use the default context if ctx is None and threading.current_thread() is threading.main_thread(): ctx = GLib.MainContext.default() # We do not create a main context implicitly; # we create a mainloop for an existing context though if ctx is None: raise RuntimeError( f"There is no main context set for thread {threading.current_thread().name!r}." ) return self.get_event_loop_for_context(ctx) def get_event_loop_for_context(self, ctx): """Get the event loop for a specific context.""" # Note: We cannot attach it to ctx, as getting the default will always # return a new python wrapper. But, we can use hash() as that returns # the pointer to the C structure. try: loop = self._loops[hash(ctx)] if not loop.is_closed(): return loop except KeyError: pass self._loops[hash(ctx)] = GLibEventLoop(ctx) if self._child_watcher and ctx == GLib.MainContext.default(): self._child_watcher.attach_loop(self.get_event_loop()) return self._loops[hash(ctx)] def set_event_loop(self, loop): """Set the event loop for the current context (python thread) to loop. This is only permitted if the thread has no thread default main context with the main thread using the default main context. """ # Only accept glib event loops, otherwise things will just mess up assert loop is None or isinstance(loop, GLibEventLoop) ctx = ctx_td = GLib.MainContext.get_thread_default() if ctx is None and threading.current_thread() is threading.main_thread(): ctx = GLib.MainContext.default() if loop is None: # We do permit unsetting the current loop/context old = self._loops.pop(hash(ctx), None) if old: if hash(old._context) != hash(ctx): warnings.warn( "GMainContext was changed unknowingly by asyncio integration!", RuntimeWarning, ) if ctx_td: GLib.MainContext.pop_thread_default(ctx_td) else: # Only allow attaching if the thread has no main context yet if ctx: raise RuntimeError( f"Thread {threading.current_thread().name!r} already has a main context, " "get_event_loop() will create a new loop if needed" ) GLib.MainContext.push_thread_default(loop._context) self._loops[hash(loop._context)] = loop def new_event_loop(self): """Create and return a new event loop that iterates a new GLib.MainContext. """ return GLibEventLoop(GLib.MainContext()) def __enter__(self): self.__orig_policy = asyncio.get_event_loop_policy() asyncio.set_event_loop_policy(self) return self def __exit__(self, exc_type, exc_value, traceback): # We shouldn't have any running loops at this point, and the ones that # got created should be closed eventually. # Explicitly close all loops here, it is not reasonable for them to be # used after we unregister the EventLoopPolicy below. for loop in self._loops.values(): loop.close() asyncio.set_event_loop_policy(self.__orig_policy) # Do not supress any exceptions return False # NOTE: We do *not* provide a GLib based ChildWatcher implementation! # This is *intentional* and *required*. The issue is that python provides # API which uses wait4() internally. GLib at the same time uses a thread to # handle SIGCHLD signals, which causes a race condition resulting in a # critical warning. # We just provide a reasonable sane child watcher and disallow the user # from choosing one as e.g. MultiLoopChildWatcher is problematic. # # TODO: Use PidfdChildWatcher when available if sys.platform != "win32": def get_child_watcher(self): if self._child_watcher is None: self._child_watcher = asyncio.ThreadedChildWatcher() if threading.current_thread() is threading.main_thread(): self._child_watcher.attach_loop(self.get_event_loop()) return self._child_watcher ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/gimodule.c0000664000000000000000000022751115074673150014726 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2005-2009 Johan Dahlin * * gimodule.c: wrapper for the gobject-introspection library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA */ #include #include #include "config.h" #include "gimodule.h" #include "pygboxed.h" #include "pygenum.h" #include "pygflags.h" #include "pygi-async.h" #include "pygi-basictype.h" #include "pygi-boxed.h" #include "pygi-ccallback.h" #include "pygi-closure.h" #include "pygi-error.h" #include "pygi-foreign.h" #include "pygi-fundamental.h" #include "pygi-info.h" #include "pygi-property.h" #include "pygi-repository.h" #include "pygi-resulttuple.h" #include "pygi-source.h" #include "pygi-struct.h" #include "pygi-type.h" #include "pygi-util.h" #include "pygi-value.h" #include "pyginterface.h" #include "pygobject-internal.h" #include "pygobject-object.h" #include "pygoptioncontext.h" #include "pygoptiongroup.h" #include "pygpointer.h" #include "pygspawn.h" PyObject *PyGIWarning; PyObject *PyGIDeprecationWarning; PyObject *_PyGIDefaultArgPlaceholder; static int _gi_exec (PyObject *module); static void pyg_flags_add_constants (PyObject *module, GType flags_type, const gchar *strip_prefix); /** * pyg_enum_add_constants: * @module: a Python module * @enum_type: the GType of the enumeration. * @strip_prefix: the prefix to strip from the constant names. * * Adds constants to the given Python module for each value name of * the enumeration. A prefix will be stripped from each enum name. */ static void pyg_enum_add_constants (PyObject *module, GType enum_type, const gchar *strip_prefix) { GEnumClass *eclass; guint i; if (!G_TYPE_IS_ENUM (enum_type)) { if (G_TYPE_IS_FLAGS (enum_type)) /* See bug #136204 */ pyg_flags_add_constants (module, enum_type, strip_prefix); else g_warning ("`%s' is not an enum type", g_type_name (enum_type)); return; } g_return_if_fail (strip_prefix != NULL); eclass = G_ENUM_CLASS (g_type_class_ref (enum_type)); for (i = 0; i < eclass->n_values; i++) { const gchar *name = eclass->values[i].value_name; gint value = eclass->values[i].value; PyModule_AddIntConstant ( module, (char *)pyg_constant_strip_prefix (name, strip_prefix), (long)value); } g_type_class_unref (eclass); } /** * pyg_flags_add_constants: * @module: a Python module * @flags_type: the GType of the flags type. * @strip_prefix: the prefix to strip from the constant names. * * Adds constants to the given Python module for each value name of * the flags set. A prefix will be stripped from each flag name. */ static void pyg_flags_add_constants (PyObject *module, GType flags_type, const gchar *strip_prefix) { GFlagsClass *fclass; guint i; if (!G_TYPE_IS_FLAGS (flags_type)) { if (G_TYPE_IS_ENUM (flags_type)) /* See bug #136204 */ pyg_enum_add_constants (module, flags_type, strip_prefix); else g_warning ("`%s' is not an flags type", g_type_name (flags_type)); return; } g_return_if_fail (strip_prefix != NULL); fclass = G_FLAGS_CLASS (g_type_class_ref (flags_type)); for (i = 0; i < fclass->n_values; i++) { const gchar *name = fclass->values[i].value_name; guint value = fclass->values[i].value; PyModule_AddIntConstant ( module, (char *)pyg_constant_strip_prefix (name, strip_prefix), (long)value); } g_type_class_unref (fclass); } /** * pyg_set_thread_block_funcs: * Deprecated, only available for ABI compatibility. */ static void _pyg_set_thread_block_funcs (PyGThreadBlockFunc block_threads_func, PyGThreadBlockFunc unblock_threads_func) { PyGILState_STATE state = PyGILState_Ensure (); PyErr_Warn (PyExc_DeprecationWarning, "Using pyg_set_thread_block_funcs is not longer needed. " "PyGObject always uses Py_BLOCK/UNBLOCK_THREADS."); PyGILState_Release (state); } static GParamSpec * create_property (const gchar *prop_name, GType prop_type, const gchar *nick, const gchar *blurb, PyObject *args, GParamFlags flags) { GParamSpec *pspec = NULL; switch (G_TYPE_FUNDAMENTAL (prop_type)) { case G_TYPE_CHAR: { gchar minimum, maximum, default_value; if (!PyArg_ParseTuple (args, "ccc", &minimum, &maximum, &default_value)) return NULL; pspec = g_param_spec_char (prop_name, nick, blurb, minimum, maximum, default_value, flags); break; } case G_TYPE_UCHAR: { gchar minimum, maximum, default_value; if (!PyArg_ParseTuple (args, "ccc", &minimum, &maximum, &default_value)) return NULL; pspec = g_param_spec_uchar (prop_name, nick, blurb, minimum, maximum, default_value, flags); break; } case G_TYPE_BOOLEAN: { gboolean default_value; if (!PyArg_ParseTuple (args, "i", &default_value)) return NULL; pspec = g_param_spec_boolean (prop_name, nick, blurb, default_value, flags); break; } case G_TYPE_INT: { gint minimum, maximum, default_value; if (!PyArg_ParseTuple (args, "iii", &minimum, &maximum, &default_value)) return NULL; pspec = g_param_spec_int (prop_name, nick, blurb, minimum, maximum, default_value, flags); break; } case G_TYPE_UINT: { guint minimum, maximum, default_value; if (!PyArg_ParseTuple (args, "III", &minimum, &maximum, &default_value)) return NULL; pspec = g_param_spec_uint (prop_name, nick, blurb, minimum, maximum, default_value, flags); break; } case G_TYPE_LONG: { glong minimum, maximum, default_value; if (!PyArg_ParseTuple (args, "lll", &minimum, &maximum, &default_value)) return NULL; pspec = g_param_spec_long (prop_name, nick, blurb, minimum, maximum, default_value, flags); break; } case G_TYPE_ULONG: { gulong minimum, maximum, default_value; if (!PyArg_ParseTuple (args, "kkk", &minimum, &maximum, &default_value)) return NULL; pspec = g_param_spec_ulong (prop_name, nick, blurb, minimum, maximum, default_value, flags); break; } case G_TYPE_INT64: { gint64 minimum, maximum, default_value; if (!PyArg_ParseTuple (args, "LLL", &minimum, &maximum, &default_value)) return NULL; pspec = g_param_spec_int64 (prop_name, nick, blurb, minimum, maximum, default_value, flags); break; } case G_TYPE_UINT64: { guint64 minimum, maximum, default_value; if (!PyArg_ParseTuple (args, "KKK", &minimum, &maximum, &default_value)) return NULL; pspec = g_param_spec_uint64 (prop_name, nick, blurb, minimum, maximum, default_value, flags); break; } case G_TYPE_ENUM: { gint default_value; PyObject *pydefault; if (!PyArg_ParseTuple (args, "O", &pydefault)) return NULL; if (pyg_enum_get_value (prop_type, pydefault, (gint *)&default_value)) return NULL; pspec = g_param_spec_enum (prop_name, nick, blurb, prop_type, default_value, flags); break; } case G_TYPE_FLAGS: { guint default_value; PyObject *pydefault; if (!PyArg_ParseTuple (args, "O", &pydefault)) return NULL; if (pyg_flags_get_value (prop_type, pydefault, &default_value)) return NULL; pspec = g_param_spec_flags (prop_name, nick, blurb, prop_type, default_value, flags); break; } case G_TYPE_FLOAT: { gfloat minimum, maximum, default_value; if (!PyArg_ParseTuple (args, "fff", &minimum, &maximum, &default_value)) return NULL; pspec = g_param_spec_float (prop_name, nick, blurb, minimum, maximum, default_value, flags); break; } case G_TYPE_DOUBLE: { gdouble minimum, maximum, default_value; if (!PyArg_ParseTuple (args, "ddd", &minimum, &maximum, &default_value)) return NULL; pspec = g_param_spec_double (prop_name, nick, blurb, minimum, maximum, default_value, flags); break; } case G_TYPE_STRING: { const gchar *default_value; if (!PyArg_ParseTuple (args, "z", &default_value)) return NULL; pspec = g_param_spec_string (prop_name, nick, blurb, default_value, flags); break; } case G_TYPE_PARAM: if (!PyArg_ParseTuple (args, "")) return NULL; pspec = g_param_spec_param (prop_name, nick, blurb, prop_type, flags); break; case G_TYPE_BOXED: if (!PyArg_ParseTuple (args, "")) return NULL; pspec = g_param_spec_boxed (prop_name, nick, blurb, prop_type, flags); break; case G_TYPE_POINTER: if (!PyArg_ParseTuple (args, "")) return NULL; if (prop_type == G_TYPE_GTYPE) pspec = g_param_spec_gtype (prop_name, nick, blurb, G_TYPE_NONE, flags); else pspec = g_param_spec_pointer (prop_name, nick, blurb, flags); break; case G_TYPE_OBJECT: case G_TYPE_INTERFACE: if (!PyArg_ParseTuple (args, "")) return NULL; pspec = g_param_spec_object (prop_name, nick, blurb, prop_type, flags); break; case G_TYPE_VARIANT: { PyObject *pydefault; GVariant *default_value = NULL; if (!PyArg_ParseTuple (args, "O", &pydefault)) return NULL; if (!Py_IsNone (pydefault)) default_value = pyg_boxed_get (pydefault, GVariant); pspec = g_param_spec_variant ( prop_name, nick, blurb, G_VARIANT_TYPE_ANY, default_value, flags); break; } default: /* unhandled pspec type ... */ break; } if (!pspec) { char buf[128]; g_snprintf (buf, sizeof (buf), "could not create param spec for type %s", g_type_name (prop_type)); PyErr_SetString (PyExc_TypeError, buf); return NULL; } return pspec; } static PyObject * pyg_param_spec_new (GParamSpec *pspec) { PyErr_SetString (PyExc_NotImplementedError, "Creating ParamSpecs through pyg_param_spec_new is no " "longer supported"); return NULL; } static GParamSpec * pyg_param_spec_from_object (PyObject *tuple) { PyErr_SetString (PyExc_NotImplementedError, "Creating ParamSpecs through pyg_param_spec_from_object " "is no longer supported"); return NULL; } G_GNUC_BEGIN_IGNORE_DEPRECATIONS /** * pyg_parse_constructor_args: helper function for PyGObject constructors * @obj_type: GType of the GObject, for parameter introspection * @arg_names: %NULL-terminated array of constructor argument names * @prop_names: %NULL-terminated array of property names, with direct * correspondence to @arg_names * @params: GParameter array where parameters will be placed; length * of this array must be at least equal to the number of * arguments/properties * @nparams: output parameter to contain actual number of arguments found * @py_args: array of PyObject* containing the actual constructor arguments * * Parses an array of PyObject's and creates a GParameter array * * Return value: %TRUE if all is successful, otherwise %FALSE and * python exception set. **/ static gboolean pyg_parse_constructor_args (GType obj_type, char **arg_names, char **prop_names, GParameter *params, guint *nparams, PyObject **py_args) { guint arg_i, param_i; GObjectClass *oclass; oclass = g_type_class_ref (obj_type); g_return_val_if_fail (oclass, FALSE); for (param_i = arg_i = 0; arg_names[arg_i]; ++arg_i) { GParamSpec *spec; if (!py_args[arg_i]) continue; spec = g_object_class_find_property (oclass, prop_names[arg_i]); params[param_i].name = prop_names[arg_i]; g_value_init (¶ms[param_i].value, spec->value_type); if (pyg_value_from_pyobject (¶ms[param_i].value, py_args[arg_i]) == -1) { guint i; PyErr_Format (PyExc_TypeError, "could not convert parameter '%s' of type '%s'", arg_names[arg_i], g_type_name (spec->value_type)); g_type_class_unref (oclass); for (i = 0; i < param_i; ++i) g_value_unset (¶ms[i].value); return FALSE; } ++param_i; } g_type_class_unref (oclass); *nparams = param_i; return TRUE; } G_GNUC_END_IGNORE_DEPRECATIONS /* Only for backwards compatibility */ static int pygobject_enable_threads (void) { return 0; } static int pygobject_gil_state_ensure (void) { return PyGILState_Ensure (); } static void pygobject_gil_state_release (int flag) { PyGILState_Release (flag); } static void pyg_register_class_init (GType gtype, PyGClassInitFunc class_init) { GSList *list; list = g_type_get_qdata (gtype, pygobject_class_init_key); list = g_slist_prepend (list, class_init); g_type_set_qdata (gtype, pygobject_class_init_key, list); } static gboolean add_properties (GObjectClass *klass, PyObject *properties) { gboolean ret = TRUE; Py_ssize_t pos = 0; PyObject *key, *value; while (PyDict_Next (properties, &pos, &key, &value)) { const gchar *prop_name; GType prop_type; const gchar *nick, *blurb; GParamFlags flags; Py_ssize_t val_length; PyObject *slice, *item, *py_prop_type; GParamSpec *pspec; /* values are of format (type,nick,blurb, type_specific_args, flags) */ if (!PyUnicode_Check (key)) { PyErr_SetString (PyExc_TypeError, "__gproperties__ keys must be strings"); ret = FALSE; break; } prop_name = PyUnicode_AsUTF8 (key); if (!PyTuple_Check (value)) { PyErr_SetString (PyExc_TypeError, "__gproperties__ values must be tuples"); ret = FALSE; break; } val_length = PyTuple_Size (value); if (val_length < 4) { PyErr_SetString ( PyExc_TypeError, "__gproperties__ values must be at least 4 elements long"); ret = FALSE; break; } slice = PySequence_GetSlice (value, 0, 3); if (!slice) { ret = FALSE; break; } if (!PyArg_ParseTuple (slice, "Ozz", &py_prop_type, &nick, &blurb)) { Py_DECREF (slice); ret = FALSE; break; } Py_DECREF (slice); prop_type = pyg_type_from_object (py_prop_type); if (!prop_type) { ret = FALSE; break; } item = PyTuple_GetItem (value, val_length - 1); if (!PyLong_Check (item)) { PyErr_SetString ( PyExc_TypeError, "last element in __gproperties__ value tuple must be an int"); ret = FALSE; break; } if (!pygi_gint_from_py (item, &flags)) { ret = FALSE; break; } /* slice is the extra items in the tuple */ slice = PySequence_GetSlice (value, 3, val_length - 1); pspec = create_property (prop_name, prop_type, nick, blurb, slice, flags); Py_DECREF (slice); if (pspec) { g_object_class_install_property (klass, 1, pspec); } else { PyObject *type, *pvalue, *traceback; ret = FALSE; PyErr_Fetch (&type, &pvalue, &traceback); if (PyUnicode_Check (pvalue)) { char msg[256]; g_snprintf ( msg, 256, "%s (while registering property '%s' for GType '%s')", PyUnicode_AsUTF8 (pvalue), prop_name, G_OBJECT_CLASS_NAME (klass)); Py_DECREF (pvalue); value = PyUnicode_FromString (msg); } PyErr_Restore (type, pvalue, traceback); break; } } return ret; } static gboolean override_signal (GType instance_type, const gchar *signal_name) { guint signal_id; signal_id = g_signal_lookup (signal_name, instance_type); if (!signal_id) { gchar buf[128]; g_snprintf (buf, sizeof (buf), "could not look up %s", signal_name); PyErr_SetString (PyExc_TypeError, buf); return FALSE; } g_signal_override_class_closure (signal_id, instance_type, pyg_signal_class_closure_get ()); return TRUE; } typedef struct _PyGSignalAccumulatorData { PyObject *callable; PyObject *user_data; } PyGSignalAccumulatorData; static gboolean _pyg_signal_accumulator (GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, gpointer _data) { PyObject *py_ihint, *py_return_accu, *py_handler_return, *py_detail; PyObject *py_retval; gboolean retval = FALSE; PyGSignalAccumulatorData *data = _data; PyGILState_STATE state; state = PyGILState_Ensure (); if (ihint->detail) py_detail = PyUnicode_FromString (g_quark_to_string (ihint->detail)); else { py_detail = Py_NewRef (Py_None); } py_ihint = Py_BuildValue ("lNi", (long int)ihint->signal_id, py_detail, ihint->run_type); py_handler_return = pyg_value_as_pyobject (handler_return, TRUE); py_return_accu = pyg_value_as_pyobject (return_accu, FALSE); if (data->user_data) py_retval = PyObject_CallFunction (data->callable, "NNNO", py_ihint, py_return_accu, py_handler_return, data->user_data); else py_retval = PyObject_CallFunction (data->callable, "NNN", py_ihint, py_return_accu, py_handler_return); if (!py_retval) PyErr_Print (); else { if (!PyTuple_Check (py_retval) || PyTuple_Size (py_retval) != 2) { PyErr_SetString (PyExc_TypeError, "accumulator function must return" " a (bool, object) tuple"); PyErr_Print (); } else { retval = PyObject_IsTrue (PyTuple_GET_ITEM (py_retval, 0)); if (pyg_value_from_pyobject (return_accu, PyTuple_GET_ITEM (py_retval, 1))) { PyErr_Print (); } } Py_DECREF (py_retval); } PyGILState_Release (state); return retval; } static gboolean create_signal (GType instance_type, const gchar *signal_name, PyObject *tuple) { GSignalFlags signal_flags; PyObject *py_return_type, *py_param_types; GType return_type; guint n_params, i; Py_ssize_t py_n_params; GType *param_types; guint signal_id; GSignalAccumulator accumulator = NULL; PyGSignalAccumulatorData *accum_data = NULL; PyObject *py_accum = NULL, *py_accum_data = NULL; if (!PyArg_ParseTuple (tuple, "iOO|OO", &signal_flags, &py_return_type, &py_param_types, &py_accum, &py_accum_data)) { gchar buf[128]; PyErr_Clear (); g_snprintf (buf, sizeof (buf), "value for __gsignals__['%s'] not in correct format", signal_name); PyErr_SetString (PyExc_TypeError, buf); return FALSE; } if (py_accum && !Py_IsNone (py_accum) && !PyCallable_Check (py_accum)) { gchar buf[128]; g_snprintf (buf, sizeof (buf), "accumulator for __gsignals__['%s'] must be callable", signal_name); PyErr_SetString (PyExc_TypeError, buf); return FALSE; } return_type = pyg_type_from_object (py_return_type); if (!return_type) return FALSE; if (!PySequence_Check (py_param_types)) { gchar buf[128]; g_snprintf ( buf, sizeof (buf), "third element of __gsignals__['%s'] tuple must be a sequence", signal_name); PyErr_SetString (PyExc_TypeError, buf); return FALSE; } py_n_params = PySequence_Length (py_param_types); if (py_n_params < 0) return FALSE; if (!pygi_guint_from_pyssize (py_n_params, &n_params)) return FALSE; param_types = g_new (GType, n_params); for (i = 0; i < n_params; i++) { PyObject *item = PySequence_GetItem (py_param_types, i); param_types[i] = pyg_type_from_object (item); if (param_types[i] == 0) { Py_DECREF (item); g_free (param_types); return FALSE; } Py_DECREF (item); } if (py_accum != NULL && !Py_IsNone (py_accum)) { accum_data = g_new (PyGSignalAccumulatorData, 1); accum_data->callable = Py_NewRef (py_accum); accum_data->user_data = Py_XNewRef (py_accum_data); accumulator = _pyg_signal_accumulator; } signal_id = g_signal_newv (signal_name, instance_type, signal_flags, pyg_signal_class_closure_get (), accumulator, accum_data, gi_cclosure_marshal_generic, return_type, n_params, param_types); g_free (param_types); if (signal_id == 0) { gchar buf[128]; g_snprintf (buf, sizeof (buf), "could not create signal for %s", signal_name); PyErr_SetString (PyExc_RuntimeError, buf); return FALSE; } return TRUE; } static PyObject * add_signals (GObjectClass *klass, PyObject *signals) { gboolean ret = TRUE; Py_ssize_t pos = 0; PyObject *key, *value, *overridden_signals = NULL; GType instance_type = G_OBJECT_CLASS_TYPE (klass); overridden_signals = PyDict_New (); while (PyDict_Next (signals, &pos, &key, &value)) { const gchar *signal_name; gchar *signal_name_canon, *c; if (!PyUnicode_Check (key)) { PyErr_SetString (PyExc_TypeError, "__gsignals__ keys must be strings"); ret = FALSE; break; } signal_name = PyUnicode_AsUTF8 (key); if (Py_IsNone (value) || (PyUnicode_Check (value) && !strcmp (PyUnicode_AsUTF8 (value), "override"))) { /* canonicalize signal name, replacing '-' with '_' */ signal_name_canon = g_strdup (signal_name); for (c = signal_name_canon; *c; ++c) if (*c == '-') *c = '_'; if (PyDict_SetItemString (overridden_signals, signal_name_canon, key)) { g_free (signal_name_canon); ret = FALSE; break; } g_free (signal_name_canon); ret = override_signal (instance_type, signal_name); } else { ret = create_signal (instance_type, signal_name, value); } if (!ret) break; } if (ret) return overridden_signals; else { Py_XDECREF (overridden_signals); return NULL; } } static void pyg_object_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PyObject *object_wrapper, *retval; PyGILState_STATE state; state = PyGILState_Ensure (); object_wrapper = g_object_get_qdata (object, pygobject_wrapper_key); if (object_wrapper) Py_INCREF (object_wrapper); else object_wrapper = pygobject_new (object); if (object_wrapper == NULL) { PyGILState_Release (state); return; } retval = pygi_call_do_get_property (object_wrapper, pspec); if (retval && pyg_value_from_pyobject (value, retval) < 0) { PyErr_Print (); } Py_DECREF (object_wrapper); Py_XDECREF (retval); PyGILState_Release (state); } static void pyg_object_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PyObject *object_wrapper, *retval; PyObject *py_pspec, *py_value; PyGILState_STATE state; state = PyGILState_Ensure (); object_wrapper = g_object_get_qdata (object, pygobject_wrapper_key); if (object_wrapper) Py_INCREF (object_wrapper); else object_wrapper = pygobject_new (object); if (object_wrapper == NULL) { PyGILState_Release (state); return; } py_pspec = pygi_fundamental_new (pspec); py_value = pyg_value_as_pyobject (value, TRUE); retval = PyObject_CallMethod (object_wrapper, "do_set_property", "OO", py_pspec, py_value); if (retval) { Py_DECREF (retval); } else { PyErr_Print (); } Py_DECREF (object_wrapper); Py_DECREF (py_pspec); Py_DECREF (py_value); PyGILState_Release (state); } static void pyg_object_dispose (GObject *object) { PyObject *object_wrapper, *retval; GObjectClass *parent_class; PyGILState_STATE state = PyGILState_Ensure (); object_wrapper = g_object_get_qdata (object, pygobject_wrapper_key); Py_XINCREF (object_wrapper); if (object_wrapper != NULL && PyObject_HasAttrString (object_wrapper, "do_dispose")) { retval = PyObject_CallMethod (object_wrapper, "do_dispose", NULL); if (retval) Py_DECREF (retval); else PyErr_Print (); } Py_XDECREF (object_wrapper); PyGILState_Release (state); /* Find the first non-pygobject dispose method. */ parent_class = g_type_class_peek (g_type_parent (G_TYPE_FROM_INSTANCE (object))); while (parent_class && parent_class->dispose == pyg_object_dispose) { parent_class = g_type_class_peek ( g_type_parent (G_TYPE_FROM_CLASS (parent_class))); } if (parent_class && parent_class->dispose) { parent_class->dispose (object); } } static void pyg_object_class_init (GObjectClass *class, PyObject *py_class) { PyObject *gproperties, *gsignals, *overridden_signals; PyObject *class_dict = ((PyTypeObject *)py_class)->tp_dict; class->set_property = pyg_object_set_property; class->get_property = pyg_object_get_property; class->dispose = pyg_object_dispose; /* install signals */ /* we look this up in the instance dictionary, so we don't * accidentally get a parent type's __gsignals__ attribute. */ gsignals = PyDict_GetItemString (class_dict, "__gsignals__"); if (gsignals) { if (!PyDict_Check (gsignals)) { PyErr_SetString (PyExc_TypeError, "__gsignals__ attribute not a dict!"); return; } if (!(overridden_signals = add_signals (class, gsignals))) { return; } if (PyDict_SetItemString (class_dict, "__gsignals__", overridden_signals)) { return; } Py_DECREF (overridden_signals); PyDict_DelItemString (class_dict, "__gsignals__"); } else { PyErr_Clear (); } /* install properties */ /* we look this up in the instance dictionary, so we don't * accidentally get a parent type's __gproperties__ attribute. */ gproperties = PyDict_GetItemString (class_dict, "__gproperties__"); if (gproperties) { if (!PyDict_Check (gproperties)) { PyErr_SetString (PyExc_TypeError, "__gproperties__ attribute not a dict!"); return; } if (!add_properties (class, gproperties)) { return; } PyDict_DelItemString (class_dict, "__gproperties__"); /* Borrowed reference. Py_DECREF(gproperties); */ } else { PyErr_Clear (); } } static GPrivate pygobject_construction_wrapper; static inline void pygobject_init_wrapper_set (PyObject *wrapper) { g_private_set (&pygobject_construction_wrapper, wrapper); } static inline PyObject * pygobject_init_wrapper_get (void) { return (PyObject *)g_private_get (&pygobject_construction_wrapper); } /** * Like g_object_new_with_properties() but also works with older glib versions. */ GObject * pygobject_object_new_with_properties (GType object_type, guint n_properties, const char *names[], const GValue values[]) { GObject *obj; #if GLIB_CHECK_VERSION(2, 54, 0) obj = g_object_new_with_properties (object_type, n_properties, names, values); #else { GParameter *parameters; uint i; parameters = g_new (GParameter, n_properties); for (i = 0; i < n_properties; i++) { parameters[i].name = names[i]; parameters[i].value = values[i]; } obj = g_object_newv (object_type, n_properties, parameters); g_free (parameters); } #endif return obj; } int pygobject_constructv (PyGObject *self, guint n_properties, const char *names[], const GValue values[]) { GObject *obj; g_assert (self->obj == NULL); pygobject_init_wrapper_set ((PyObject *)self); obj = pygobject_object_new_with_properties ( pyg_type_from_object ((PyObject *)self), n_properties, names, values); if (g_object_is_floating (obj)) self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING; pygobject_sink (obj); pygobject_init_wrapper_set (NULL); self->obj = obj; pygobject_register_wrapper ((PyObject *)self); return 0; } static void pygobject__g_instance_init (GTypeInstance *instance, gpointer g_class) { GObject *object; PyObject *wrapper, *result; PyGILState_STATE state; gboolean needs_init = FALSE; g_return_if_fail (G_IS_OBJECT (instance)); object = (GObject *)instance; wrapper = g_object_get_qdata (object, pygobject_wrapper_key); if (wrapper == NULL) { wrapper = pygobject_init_wrapper_get (); if (wrapper && ((PyGObject *)wrapper)->obj == NULL) { ((PyGObject *)wrapper)->obj = object; pygobject_register_wrapper (wrapper); } } pygobject_init_wrapper_set (NULL); state = PyGILState_Ensure (); if (wrapper == NULL) { /* this looks like a python object created through * g_object_new -> we have no python wrapper, so create it * now */ if (g_object_is_floating (object)) { g_object_ref (object); wrapper = pygobject_new_full (object, /*steal=*/TRUE, g_class); g_object_force_floating (object); } else { wrapper = pygobject_new_full (object, /*steal=*/FALSE, g_class); } /* float the wrapper ref here because we are going to orphan it * so we don't destroy the wrapper. The next call to pygobject_new_full * will take the ref */ pygobject_ref_float ((PyGObject *)wrapper); needs_init = TRUE; } /* XXX: used for Gtk.Template */ gboolean is_final_subclass = G_OBJECT_TYPE (object) == G_OBJECT_CLASS_TYPE (g_class); if (is_final_subclass && PyObject_HasAttrString ((PyObject *)Py_TYPE (wrapper), "__dontuse_ginstance_init__")) { result = PyObject_CallMethod (wrapper, "__dontuse_ginstance_init__", NULL); if (result == NULL) PyErr_Print (); else Py_DECREF (result); } if (needs_init) { result = PyObject_CallMethod (wrapper, "__init__", NULL); if (result == NULL) PyErr_Print (); else Py_DECREF (result); } PyGILState_Release (state); } /* This implementation is bad, see bug 566571 for an example why. * Instead of scanning explicitly declared bases for interfaces, we * should automatically initialize all implemented interfaces to * prevent bugs like that one. However, this will lead to * performance degradation as each virtual method in derived classes * will round-trip through do_*() stuff, *even* if it is not * overriden. We need to teach codegen to retain parent method * instead of setting virtual to *_proxy_do_*() if corresponding * do_*() is not overriden. Ok, that was a messy explanation. */ static void pyg_type_add_interfaces (PyTypeObject *class, GType instance_type, PyObject *bases, GType *parent_interfaces, guint n_parent_interfaces) { int i; if (!bases) { g_warning ("type has no bases"); return; } for (i = 0; i < PyTuple_GET_SIZE (bases); ++i) { PyObject *base = PyTuple_GET_ITEM (bases, i); GType itype; const GInterfaceInfo *iinfo; GInterfaceInfo iinfo_copy; /* 'base' can also be a PyClassObject, see bug #566571. */ if (!PyType_Check (base)) continue; if (!PyType_IsSubtype ((PyTypeObject *)base, &PyGInterface_Type)) continue; itype = pyg_type_from_object (base); /* Happens for _implementations_ of an interface. */ if (!G_TYPE_IS_INTERFACE (itype)) continue; iinfo = pyg_lookup_interface_info (itype); if (!iinfo) { gchar *error; error = g_strdup_printf ( "Interface type %s " "has no Python implementation support", ((PyTypeObject *)base)->tp_name); PyErr_Warn (PyExc_RuntimeWarning, error); g_free (error); continue; } iinfo_copy = *iinfo; iinfo_copy.interface_data = class; g_type_add_interface_static (instance_type, itype, &iinfo_copy); } } static int pyg_run_class_init (GType gtype, gpointer gclass, PyTypeObject *pyclass) { GSList *list; PyGClassInitFunc class_init; GType parent_type; int rv; parent_type = g_type_parent (gtype); if (parent_type) { rv = pyg_run_class_init (parent_type, gclass, pyclass); if (rv) return rv; } list = g_type_get_qdata (gtype, pygobject_class_init_key); for (; list; list = list->next) { class_init = list->data; rv = class_init (gclass, pyclass); if (rv) return rv; } return 0; } static char * get_type_name_for_class (PyTypeObject *class) { gint i, name_serial; char name_serial_str[16]; PyObject *module; char *type_name = NULL; /* make name for new GType */ name_serial = 1; /* give up after 1000 tries, just in case.. */ while (name_serial < 1000) { g_free (type_name); g_snprintf (name_serial_str, 16, "-v%i", name_serial); module = PyObject_GetAttrString ((PyObject *)class, "__module__"); if (module && PyUnicode_Check (module)) { type_name = g_strconcat (PyUnicode_AsUTF8 (module), ".", class->tp_name, name_serial > 1 ? name_serial_str : NULL, NULL); Py_DECREF (module); } else { if (module) Py_DECREF (module); else PyErr_Clear (); type_name = g_strconcat (class->tp_name, name_serial > 1 ? name_serial_str : NULL, NULL); } /* convert '.' in type name to '+', which isn't banned (grumble) */ for (i = 0; type_name[i] != '\0'; i++) if (type_name[i] == '.') type_name[i] = '+'; if (g_type_from_name (type_name) == 0) break; /* we now have a unique name */ ++name_serial; } return type_name; } static int pyg_type_register (PyTypeObject *class, const char *type_name) { PyObject *gtype; GType parent_type, instance_type; GType *parent_interfaces; guint n_parent_interfaces; GTypeQuery query; gpointer gclass; GTypeInfo type_info = { 0, /* class_size */ (GBaseInitFunc)NULL, (GBaseFinalizeFunc)NULL, (GClassInitFunc)NULL, (GClassFinalizeFunc)NULL, NULL, /* class_data */ 0, /* instance_size */ 0, /* n_preallocs */ (GInstanceInitFunc)NULL, }; gchar *new_type_name; if (PyType_IsSubtype (class, &PyGObject_Type)) { type_info.class_init = (GClassInitFunc)pyg_object_class_init; type_info.instance_init = pygobject__g_instance_init; } /* find the GType of the parent */ parent_type = pyg_type_from_object ((PyObject *)class); if (!parent_type) return -1; parent_interfaces = g_type_interfaces (parent_type, &n_parent_interfaces); if (type_name) /* care is taken below not to free this */ new_type_name = (gchar *)type_name; else new_type_name = get_type_name_for_class (class); /* set class_data that will be passed to the class_init function. */ type_info.class_data = class; /* fill in missing values of GTypeInfo struct */ g_type_query (parent_type, &query); type_info.class_size = (guint16)query.class_size; type_info.instance_size = (guint16)query.instance_size; /* create new typecode */ instance_type = g_type_register_static (parent_type, new_type_name, &type_info, 0); if (instance_type == 0) { PyErr_Format (PyExc_RuntimeError, "could not create new GType: %s (subclass of %s)", new_type_name, g_type_name (parent_type)); if (type_name == NULL) g_free (new_type_name); return -1; } if (type_name == NULL) g_free (new_type_name); /* store pointer to the class with the GType */ Py_INCREF (class); g_type_set_qdata (instance_type, pygobject_class_key, class); /* Mark this GType as a custom python type */ g_type_set_qdata (instance_type, pygobject_custom_key, GINT_TO_POINTER (1)); /* set new value of __gtype__ on class */ gtype = pyg_type_wrapper_new (instance_type); PyObject_SetAttrString ((PyObject *)class, "__gtype__", gtype); Py_DECREF (gtype); /* if no __doc__, set it to the auto doc descriptor */ if (PyDict_GetItemString (class->tp_dict, "__doc__") == NULL) { PyDict_SetItemString (class->tp_dict, "__doc__", pyg_object_descr_doc_get ()); } /* * Note, all interfaces need to be registered before the first * g_type_class_ref(), see bug #686149. * * See also comment above pyg_type_add_interfaces(). */ pyg_type_add_interfaces (class, instance_type, class->tp_bases, parent_interfaces, n_parent_interfaces); gclass = g_type_class_ref (instance_type); if (PyErr_Occurred () != NULL) { g_type_class_unref (gclass); g_free (parent_interfaces); return -1; } if (pyg_run_class_init (instance_type, gclass, class)) { g_type_class_unref (gclass); g_free (parent_interfaces); return -1; } g_type_class_unref (gclass); g_free (parent_interfaces); if (PyErr_Occurred () != NULL) return -1; return 0; } static PyObject * _wrap_pyg_type_register (PyObject *self, PyObject *args) { PyTypeObject *class; char *type_name = NULL; if (!PyArg_ParseTuple (args, "O!|z:gobject.type_register", &PyType_Type, &class, &type_name)) return NULL; GType base_gtype = pyg_type_from_object ((PyObject *)class->tp_base); if (base_gtype == G_TYPE_INVALID) { PyErr_SetString (PyExc_TypeError, "argument must be a Fundamental or GObject subclass"); return NULL; } /* Check if type already registered */ if (pyg_type_from_object ((PyObject *)class) == base_gtype) { if (pyg_type_register (class, type_name)) return NULL; } return Py_NewRef (class); } static PyObject * _wrap_pyg_enum_register (PyObject *self, PyObject *args) { PyTypeObject *class; const char *type_name = NULL; char *new_type_name; if (!PyArg_ParseTuple (args, "O!z:enum_register", &PyType_Type, &class, &type_name)) return NULL; if (!PyObject_IsSubclass ((PyObject *)class, (PyObject *)PyGEnum_Type)) { PyErr_SetString (PyExc_TypeError, "class is not a GEnum"); return NULL; } if (type_name) new_type_name = g_strdup (type_name); else new_type_name = get_type_name_for_class (class); if (!pyg_enum_register (class, new_type_name)) return NULL; Py_RETURN_NONE; } static PyObject * _wrap_pyg_flags_register (PyObject *self, PyObject *args) { PyTypeObject *class; const char *type_name = NULL; char *new_type_name; if (!PyArg_ParseTuple (args, "O!z:flags_register", &PyType_Type, &class, &type_name)) return NULL; if (!PyObject_IsSubclass ((PyObject *)class, (PyObject *)PyGFlags_Type)) { PyErr_SetString (PyExc_TypeError, "class is not a GFlags"); return NULL; } if (type_name) new_type_name = g_strdup (type_name); else new_type_name = get_type_name_for_class (class); if (!pyg_flags_register (class, new_type_name)) return NULL; Py_RETURN_NONE; } static GHashTable *log_handlers = NULL; static gboolean log_handlers_disabled = FALSE; static void remove_handler (gpointer domain, gpointer handler, gpointer unused) { g_log_remove_handler (domain, GPOINTER_TO_UINT (handler)); } static void _log_func (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { if (G_LIKELY (Py_IsInitialized ())) { PyGILState_STATE state; PyObject *warning = user_data; state = PyGILState_Ensure (); PyErr_Warn (warning, (char *)message); PyGILState_Release (state); } else g_log_default_handler (log_domain, log_level, message, user_data); } static void add_warning_redirection (const char *domain, PyObject *warning) { g_return_if_fail (domain != NULL); g_return_if_fail (warning != NULL); if (!log_handlers_disabled) { guint handler; gpointer old_handler; if (!log_handlers) log_handlers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); if ((old_handler = g_hash_table_lookup (log_handlers, domain))) g_log_remove_handler (domain, GPOINTER_TO_UINT (old_handler)); handler = g_log_set_handler ( domain, G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING, _log_func, warning); g_hash_table_insert (log_handlers, g_strdup (domain), GUINT_TO_POINTER (handler)); } } static void disable_warning_redirections (void) { log_handlers_disabled = TRUE; if (log_handlers) { g_hash_table_foreach (log_handlers, remove_handler, NULL); g_hash_table_destroy (log_handlers); log_handlers = NULL; } } /** * Returns 0 on success, or -1 and sets an exception. */ static int pygi_register_warnings (PyObject *d) { PyObject *warning; warning = PyErr_NewException ("gobject.Warning", PyExc_Warning, NULL); if (warning == NULL) return -1; PyDict_SetItemString (d, "Warning", warning); add_warning_redirection ("GLib", warning); add_warning_redirection ("GLib-GObject", warning); add_warning_redirection ("GThread", warning); return 0; } static PyObject * _wrap_pyg_enum_add (PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "module", "name", "g_type", "enum_info", NULL }; PyObject *module, *py_g_type; PyGIBaseInfo *py_info; const char *name; GType g_type; GIEnumInfo *info; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "OsOO:enum_add", kwlist, &module, &name, &py_g_type, &py_info)) { return NULL; } if (!Py_IsNone (module) && !PyModule_Check (module)) { PyErr_SetString (PyExc_TypeError, "first argument must be module or None"); return NULL; } g_type = pyg_type_from_object (py_g_type); if (g_type == G_TYPE_INVALID) { return NULL; } if (Py_TYPE (py_info) == &PyGIEnumInfo_Type) { info = GI_ENUM_INFO (py_info->info); } else { info = NULL; } return pyg_enum_add_full (module, name, g_type, info); } static PyObject * _wrap_pyg_flags_add (PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "module", "name", "g_type", "flags_info", NULL }; PyObject *module, *py_g_type; PyGIBaseInfo *py_info; const char *name; GType g_type; GIFlagsInfo *info; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "OsOO:flags_add", kwlist, &module, &name, &py_g_type, &py_info)) { return NULL; } if (!Py_IsNone (module) && !PyModule_Check (module)) { PyErr_SetString (PyExc_TypeError, "first argument must be module or None"); return NULL; } g_type = pyg_type_from_object (py_g_type); if (g_type == G_TYPE_INVALID) { return NULL; } if (Py_TYPE (py_info) == &PyGIEnumInfo_Type && GI_IS_FLAGS_INFO (py_info->info)) { info = GI_FLAGS_INFO (py_info->info); } else { info = NULL; } return pyg_flags_add_full (module, name, g_type, info); } static void initialize_interface (GTypeInterface *iface, PyTypeObject *pytype) { /* pygobject prints a warning if interface_init is NULL */ } static PyObject * _wrap_pyg_register_interface_info (PyObject *self, PyObject *args) { PyObject *py_g_type; GType g_type; GInterfaceInfo *info; if (!PyArg_ParseTuple (args, "O!:register_interface_info", &PyGTypeWrapper_Type, &py_g_type)) { return NULL; } g_type = pyg_type_from_object (py_g_type); if (!g_type_is_a (g_type, G_TYPE_INTERFACE)) { PyErr_SetString (PyExc_TypeError, "must be an interface"); return NULL; } info = g_new0 (GInterfaceInfo, 1); info->interface_init = (GInterfaceInitFunc)initialize_interface; pyg_register_interface_info (g_type, info); g_free (info); Py_RETURN_NONE; } static void find_vfunc_info (GIBaseInfo *vfunc_info, GType implementor_gtype, gpointer *implementor_class_ret, gpointer *implementor_vtable_ret, GIFieldInfo **field_info_ret) { GType ancestor_g_type = 0; GIBaseInfo *ancestor_info; GIStructInfo *struct_info; gpointer implementor_class = NULL; gboolean is_interface = FALSE; GIFieldInfo *field_info; ancestor_info = gi_base_info_get_container (vfunc_info); is_interface = GI_IS_INTERFACE_INFO (ancestor_info); ancestor_g_type = gi_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)ancestor_info); implementor_class = g_type_class_ref (implementor_gtype); if (is_interface) { GTypeInstance *implementor_iface_class; implementor_iface_class = g_type_interface_peek (implementor_class, ancestor_g_type); if (implementor_iface_class == NULL) { g_type_class_unref (implementor_class); PyErr_Format ( PyExc_RuntimeError, "Couldn't find GType of implementor of interface %s. " "Forgot to set __gtype_name__?", g_type_name (ancestor_g_type)); return; } *implementor_vtable_ret = implementor_iface_class; struct_info = gi_interface_info_get_iface_struct ( (GIInterfaceInfo *)ancestor_info); } else { struct_info = gi_object_info_get_class_struct ((GIObjectInfo *)ancestor_info); *implementor_vtable_ret = implementor_class; } *implementor_class_ret = implementor_class; field_info = gi_struct_info_find_field ( struct_info, gi_base_info_get_name ((GIBaseInfo *)vfunc_info)); if (field_info != NULL) { GITypeInfo *type_info; type_info = gi_field_info_get_type_info (field_info); if (gi_type_info_get_tag (type_info) == GI_TYPE_TAG_INTERFACE) { *field_info_ret = field_info; } else { gi_base_info_unref (field_info); } gi_base_info_unref (type_info); } gi_base_info_unref (struct_info); } static PyObject * _wrap_pyg_hook_up_vfunc_implementation (PyObject *self, PyObject *args) { PyGIBaseInfo *py_info; PyObject *py_type; PyObject *py_function; GType implementor_gtype = 0; gpointer implementor_class = NULL; gpointer implementor_vtable = NULL; GIFieldInfo *field_info = NULL; gpointer *method_ptr = NULL; PyGICClosure *closure = NULL; PyGIClosureCache *cache = NULL; if (!PyArg_ParseTuple (args, "O!O!O:hook_up_vfunc_implementation", &PyGIBaseInfo_Type, &py_info, &PyGTypeWrapper_Type, &py_type, &py_function)) return NULL; implementor_gtype = pyg_type_from_object (py_type); g_assert (G_TYPE_IS_CLASSED (implementor_gtype)); find_vfunc_info (py_info->info, implementor_gtype, &implementor_class, &implementor_vtable, &field_info); if (field_info != NULL) { GITypeInfo *type_info; GICallableInfo *callable_info; gint offset; type_info = gi_field_info_get_type_info (field_info); callable_info = GI_CALLABLE_INFO (gi_type_info_get_interface (type_info)); offset = gi_field_info_get_offset (field_info); method_ptr = G_STRUCT_MEMBER_P (implementor_vtable, offset); cache = pygi_closure_cache_new (callable_info); closure = _pygi_make_native_closure ((GICallableInfo *)callable_info, cache, GI_SCOPE_TYPE_NOTIFIED, py_function, NULL); *method_ptr = gi_callable_info_get_closure_native_address ( callable_info, closure->closure); gi_base_info_unref (callable_info); gi_base_info_unref (type_info); gi_base_info_unref (field_info); } g_type_class_unref (implementor_class); Py_RETURN_NONE; } #if 0 /* Not used, left around for future reference */ static PyObject * _wrap_pyg_has_vfunc_implementation (PyObject *self, PyObject *args) { PyGIBaseInfo *py_info; PyObject *py_type; PyObject *py_ret; gpointer implementor_class = NULL; gpointer implementor_vtable = NULL; GType implementor_gtype = 0; GIFieldInfo *field_info = NULL; if (!PyArg_ParseTuple (args, "O!O!:has_vfunc_implementation", &PyGIBaseInfo_Type, &py_info, &PyGTypeWrapper_Type, &py_type)) return NULL; implementor_gtype = pyg_type_from_object (py_type); g_assert (G_TYPE_IS_CLASSED (implementor_gtype)); py_ret = Py_False; find_vfunc_info (py_info->info, implementor_gtype, &implementor_class, &implementor_vtable, &field_info); if (field_info != NULL) { gpointer *method_ptr; gint offset; offset = gi_field_info_get_offset (field_info); method_ptr = G_STRUCT_MEMBER_P (implementor_vtable, offset); if (*method_ptr != NULL) { py_ret = Py_True; } gi_base_info_unref (field_info); } g_type_class_unref (implementor_class); return Py_NewRef(py_ret); } #endif static PyObject * _wrap_pyg_variant_type_from_string (PyObject *self, PyObject *args) { char *type_string; PyObject *py_type; PyObject *py_variant = NULL; if (!PyArg_ParseTuple (args, "s:variant_type_from_string", &type_string)) { return NULL; } py_type = pygi_type_import_by_name ("GLib", "VariantType"); py_variant = pygi_boxed_new ((PyTypeObject *)py_type, type_string, FALSE, 0); return py_variant; } #define CHUNK_SIZE 8192 static PyObject * pyg_channel_read (PyObject *self, PyObject *args, PyObject *kwargs) { int max_count = -1; PyObject *py_iochannel, *ret_obj = NULL; gsize total_read = 0; GError *error = NULL; GIOStatus status = G_IO_STATUS_NORMAL; GIOChannel *iochannel = NULL; if (!PyArg_ParseTuple (args, "Oi:pyg_channel_read", &py_iochannel, &max_count)) { return NULL; } if (!pyg_boxed_check (py_iochannel, G_TYPE_IO_CHANNEL)) { PyErr_SetString (PyExc_TypeError, "first argument is not a GLib.IOChannel"); return NULL; } if (max_count == 0) return PyBytes_FromString (""); iochannel = pyg_boxed_get (py_iochannel, GIOChannel); while (status == G_IO_STATUS_NORMAL && (max_count == -1 || total_read < (gsize)max_count)) { gsize single_read; char *buf; gsize buf_size; if (max_count == -1) buf_size = CHUNK_SIZE; else { buf_size = max_count - total_read; if (buf_size > CHUNK_SIZE) buf_size = CHUNK_SIZE; } if (ret_obj == NULL) { ret_obj = PyBytes_FromStringAndSize ((char *)NULL, buf_size); if (ret_obj == NULL) goto failure; } else if (buf_size + total_read > (gsize)PyBytes_Size (ret_obj)) { if (_PyBytes_Resize (&ret_obj, buf_size + total_read) == -1) goto failure; } buf = PyBytes_AsString (ret_obj) + total_read; Py_BEGIN_ALLOW_THREADS; status = g_io_channel_read_chars (iochannel, buf, buf_size, &single_read, &error); Py_END_ALLOW_THREADS; if (pygi_error_check (&error)) goto failure; total_read += single_read; } if (total_read != (gsize)PyBytes_Size (ret_obj)) { if (_PyBytes_Resize (&ret_obj, total_read) == -1) goto failure; } return ret_obj; failure: Py_XDECREF (ret_obj); return NULL; } static PyObject * pyg_main_context_query (PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_main_context; int max_priority = -1, n_fds; GMainContext *context; int timeout_msec = 0; GPollFD *fds; int n_poll, read_fds, i; PyObject *py_out, *py_fds; if (!PyArg_ParseTuple (args, "Oi:pyg_main_context_query", &py_main_context, &max_priority)) { return NULL; } if (!pyg_boxed_check (py_main_context, G_TYPE_MAIN_CONTEXT)) { PyErr_SetString (PyExc_TypeError, "first argument is not a GLib.MainContext"); return NULL; } context = pyg_boxed_get (py_main_context, GMainContext); n_fds = g_main_context_query (context, max_priority, NULL, NULL, 0); fds = g_new0 (GPollFD, n_fds); n_poll = g_main_context_query (context, max_priority, &timeout_msec, fds, n_fds); read_fds = MIN (n_fds, n_poll); py_fds = PyList_New (read_fds); for (i = 0; i < read_fds; i++) { PyObject *py_boxed = pygi_gboxed_new (G_TYPE_POLLFD, &fds[i], TRUE, TRUE); if (py_boxed == NULL) { Py_DECREF (py_fds); g_free (fds); return NULL; } PyList_SET_ITEM (py_fds, i, py_boxed); } g_free (fds); py_out = PyTuple_New (2); PyTuple_SET_ITEM (py_out, 0, PyLong_FromLong (timeout_msec)); PyTuple_SET_ITEM (py_out, 1, py_fds); return py_out; } static gboolean marshal_emission_hook (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) { PyGILState_STATE state; gboolean retval = FALSE; PyObject *func, *args; PyObject *retobj; PyObject *params; guint i; state = PyGILState_Ensure (); /* construct Python tuple for the parameter values */ params = PyTuple_New (n_param_values); for (i = 0; i < n_param_values; i++) { PyObject *item = pyg_value_as_pyobject (¶m_values[i], FALSE); /* error condition */ if (!item) { goto out; } PyTuple_SetItem (params, i, item); } args = (PyObject *)user_data; func = PyTuple_GetItem (args, 0); args = PySequence_Concat (params, PyTuple_GetItem (args, 1)); Py_DECREF (params); /* params passed to function may have extra arguments */ retobj = PyObject_CallObject (func, args); Py_DECREF (args); if (retobj == NULL) { PyErr_Print (); } retval = Py_IsTrue (retobj); Py_XDECREF (retobj); out: PyGILState_Release (state); return retval; } /** * pyg_destroy_notify: * @user_data: a PyObject pointer. * * A function that can be used as a GDestroyNotify callback that will * call Py_DECREF on the data. */ static void pyg_destroy_notify (gpointer user_data) { PyObject *obj = (PyObject *)user_data; PyGILState_STATE state; state = PyGILState_Ensure (); Py_DECREF (obj); PyGILState_Release (state); } static PyObject * pyg_add_emission_hook (PyGObject *self, PyObject *args) { PyObject *first, *callback, *extra_args, *data, *repr; gchar *name; gulong hook_id; guint sigid; Py_ssize_t len; GQuark detail = 0; GType gtype; PyObject *pygtype; len = PyTuple_Size (args); if (len < 3) { PyErr_SetString ( PyExc_TypeError, "gobject.add_emission_hook requires at least 3 arguments"); return NULL; } first = PySequence_GetSlice (args, 0, 3); if (!PyArg_ParseTuple (first, "OsO:add_emission_hook", &pygtype, &name, &callback)) { Py_DECREF (first); return NULL; } Py_DECREF (first); if ((gtype = pyg_type_from_object (pygtype)) == 0) { return NULL; } if (!PyCallable_Check (callback)) { PyErr_SetString (PyExc_TypeError, "third argument must be callable"); return NULL; } if (!g_signal_parse_name (name, gtype, &sigid, &detail, TRUE)) { repr = PyObject_Repr ((PyObject *)self); PyErr_Format (PyExc_TypeError, "%s: unknown signal name: %s", PyUnicode_AsUTF8 (repr), name); Py_DECREF (repr); return NULL; } extra_args = PySequence_GetSlice (args, 3, len); if (extra_args == NULL) return NULL; data = Py_BuildValue ("(ON)", callback, extra_args); if (data == NULL) return NULL; hook_id = g_signal_add_emission_hook (sigid, detail, marshal_emission_hook, data, (GDestroyNotify)pyg_destroy_notify); return pygi_gulong_to_py (hook_id); } static PyObject * pyg_signal_new (PyObject *self, PyObject *args) { gchar *signal_name; PyObject *py_type; GSignalFlags signal_flags; GType return_type; PyObject *py_return_type, *py_param_types; GType instance_type = 0; Py_ssize_t py_n_params; guint n_params, i; GType *param_types; guint signal_id; if (!PyArg_ParseTuple (args, "sOiOO:gobject.signal_new", &signal_name, &py_type, &signal_flags, &py_return_type, &py_param_types)) return NULL; instance_type = pyg_type_from_object (py_type); if (!instance_type) return NULL; if (!(G_TYPE_IS_INSTANTIATABLE (instance_type) || G_TYPE_IS_INTERFACE (instance_type))) { PyErr_SetString ( PyExc_TypeError, "argument 2 must be an object type or interface type"); return NULL; } return_type = pyg_type_from_object (py_return_type); if (!return_type) return NULL; if (!PySequence_Check (py_param_types)) { PyErr_SetString (PyExc_TypeError, "argument 5 must be a sequence of GType codes"); return NULL; } py_n_params = PySequence_Length (py_param_types); if (py_n_params < 0) return FALSE; if (!pygi_guint_from_pyssize (py_n_params, &n_params)) return FALSE; param_types = g_new (GType, n_params); for (i = 0; i < n_params; i++) { PyObject *item = PySequence_GetItem (py_param_types, i); param_types[i] = pyg_type_from_object (item); if (param_types[i] == 0) { PyErr_Clear (); Py_DECREF (item); PyErr_SetString (PyExc_TypeError, "argument 5 must be a sequence of GType codes"); g_free (param_types); return NULL; } Py_DECREF (item); } signal_id = g_signal_newv ( signal_name, instance_type, signal_flags, pyg_signal_class_closure_get (), (GSignalAccumulator)0, NULL, (GSignalCMarshaller)0, return_type, n_params, param_types); g_free (param_types); if (signal_id != 0) return pygi_guint_to_py (signal_id); PyErr_SetString (PyExc_RuntimeError, "could not create signal"); return NULL; } static PyObject * pyg_object_class_list_properties (PyObject *self, PyObject *args) { GParamSpec **specs; PyObject *py_itype, *list; GType itype; GObjectClass *class = NULL; gpointer iface = NULL; guint nprops; guint i; if (!PyArg_ParseTuple (args, "O:gobject.list_properties", &py_itype)) return NULL; if ((itype = pyg_type_from_object (py_itype)) == 0) return NULL; if (G_TYPE_IS_INTERFACE (itype)) { iface = g_type_default_interface_ref (itype); if (!iface) { PyErr_SetString (PyExc_RuntimeError, "could not get a reference to interface type"); return NULL; } specs = g_object_interface_list_properties (iface, &nprops); } else if (g_type_is_a (itype, G_TYPE_OBJECT)) { class = g_type_class_ref (itype); if (!class) { PyErr_SetString (PyExc_RuntimeError, "could not get a reference to type class"); return NULL; } specs = g_object_class_list_properties (class, &nprops); } else { PyErr_SetString (PyExc_TypeError, "type must be derived from GObject or an interface"); return NULL; } list = PyTuple_New (nprops); if (list == NULL) { g_free (specs); g_type_class_unref (class); return NULL; } for (i = 0; i < nprops; i++) { PyTuple_SetItem (list, i, pygi_fundamental_new (specs[i])); } g_free (specs); if (class) g_type_class_unref (class); else g_type_default_interface_unref (iface); return list; } static PyObject * pyg__install_metaclass (PyObject *dummy, PyTypeObject *metaclass) { PyGObject_MetaType = (PyTypeObject *)Py_NewRef (metaclass); Py_SET_TYPE (&PyGObject_Type, (PyTypeObject *)Py_NewRef (metaclass)); Py_RETURN_NONE; } static PyObject * _wrap_pyig_pyos_getsig (PyObject *self, PyObject *args) { int sig_num; if (!PyArg_ParseTuple (args, "i:pyos_getsig", &sig_num)) return NULL; return PyLong_FromVoidPtr ((void *)(PyOS_getsig (sig_num))); } static PyObject * _wrap_pyig_pyos_setsig (PyObject *self, PyObject *args) { int sig_num; PyObject *sig_handler; if (!PyArg_ParseTuple (args, "iO!:pyos_setsig", &sig_num, &PyLong_Type, &sig_handler)) return NULL; return PyLong_FromVoidPtr ((void *)(PyOS_setsig ( sig_num, (PyOS_sighandler_t)PyLong_AsVoidPtr (sig_handler)))); } static PyObject * _wrap_pygobject_new_full (PyObject *self, PyObject *args) { PyObject *ptr_value, *long_value; PyObject *steal; GObject *obj; if (!PyArg_ParseTuple (args, "OO", &ptr_value, &steal)) return NULL; long_value = PyNumber_Long (ptr_value); if (!long_value) { PyErr_SetString (PyExc_TypeError, "first argument must be an integer"); return NULL; } obj = PyLong_AsVoidPtr (long_value); Py_DECREF (long_value); if (!G_IS_OBJECT (obj)) { PyErr_SetString (PyExc_TypeError, "pointer is not a GObject"); return NULL; } return pygobject_new_full (obj, PyObject_IsTrue (steal), NULL); } static PyMethodDef _gi_functions[] = { { "pygobject_new_full", (PyCFunction)_wrap_pygobject_new_full, METH_VARARGS }, { "enum_add", (PyCFunction)_wrap_pyg_enum_add, METH_VARARGS | METH_KEYWORDS }, { "flags_add", (PyCFunction)_wrap_pyg_flags_add, METH_VARARGS | METH_KEYWORDS }, { "register_interface_info", (PyCFunction)_wrap_pyg_register_interface_info, METH_VARARGS }, { "hook_up_vfunc_implementation", (PyCFunction)_wrap_pyg_hook_up_vfunc_implementation, METH_VARARGS }, { "variant_type_from_string", (PyCFunction)_wrap_pyg_variant_type_from_string, METH_VARARGS }, { "source_new", (PyCFunction)pygi_source_new, METH_NOARGS }, { "pyos_getsig", (PyCFunction)_wrap_pyig_pyos_getsig, METH_VARARGS }, { "pyos_setsig", (PyCFunction)_wrap_pyig_pyos_setsig, METH_VARARGS }, { "source_set_callback", (PyCFunction)pygi_source_set_callback, METH_VARARGS }, { "io_channel_read", (PyCFunction)pyg_channel_read, METH_VARARGS }, { "main_context_query", (PyCFunction)pyg_main_context_query, METH_VARARGS }, { "require_foreign", (PyCFunction)pygi_require_foreign, METH_VARARGS | METH_KEYWORDS }, { "register_foreign", (PyCFunction)pygi_register_foreign, METH_NOARGS }, { "spawn_async", (PyCFunction)pyglib_spawn_async, METH_VARARGS | METH_KEYWORDS, "spawn_async(argv, envp=None, working_directory=None,\n" " flags=0, child_setup=None, user_data=None,\n" " standard_input=None, standard_output=None,\n" " standard_error=None) -> (pid, stdin, stdout, stderr)\n" "\n" "Execute a child program asynchronously within a glib.MainLoop()\n" "See the reference manual for a complete reference.\n" }, { "type_register", _wrap_pyg_type_register, METH_VARARGS }, { "enum_register", _wrap_pyg_enum_register, METH_VARARGS }, { "flags_register", _wrap_pyg_flags_register, METH_VARARGS }, { "signal_new", pyg_signal_new, METH_VARARGS }, { "list_properties", pyg_object_class_list_properties, METH_VARARGS }, { "new", (PyCFunction)pyg_object_new, METH_VARARGS | METH_KEYWORDS }, { "add_emission_hook", (PyCFunction)pyg_add_emission_hook, METH_VARARGS }, { "_install_metaclass", (PyCFunction)pyg__install_metaclass, METH_O }, { "_gvalue_get", (PyCFunction)pyg__gvalue_get, METH_O }, { "_gvalue_get_type", (PyCFunction)pyg__gvalue_get_type, METH_O }, { "_gvalue_set", (PyCFunction)pyg__gvalue_set, METH_VARARGS }, { NULL, NULL, 0 }, }; static struct PyGI_API CAPI = { pygi_register_foreign_struct, }; const gpointer PyGParamSpec_Type_Stub = NULL; struct _PyGObject_Functions pygobject_api_functions = { pygobject_register_class, pygobject_register_wrapper, pygobject_lookup_class, pygobject_new, pyg_closure_new, pygobject_watch_closure, pyg_destroy_notify, pyg_type_from_object, pyg_type_wrapper_new, pyg_enum_get_value, pyg_flags_get_value, pyg_register_gtype_custom, pyg_value_from_pyobject, pyg_value_as_pyobject, pyg_register_interface, &PyGBoxed_Type, pygi_register_gboxed, pygi_gboxed_new, &PyGPointer_Type, pyg_register_pointer, pyg_pointer_new, pyg_enum_add_constants, pyg_flags_add_constants, pyg_constant_strip_prefix, pygi_error_check, _pyg_set_thread_block_funcs, (PyGThreadBlockFunc)0, /* block_threads */ (PyGThreadBlockFunc)0, /* unblock_threads */ (PyTypeObject *)&PyGParamSpec_Type_Stub, pyg_param_spec_new, pyg_param_spec_from_object, pyg_pyobj_to_unichar_conv, pyg_parse_constructor_args, pyg_param_gvalue_as_pyobject, pyg_param_gvalue_from_pyobject, NULL /* PyGEnum_Type */, pyg_enum_add, pyg_enum_from_gtype, NULL /* PyGFlags_Type */, pyg_flags_add, pyg_flags_from_gtype, TRUE, /* threads_enabled */ pygobject_enable_threads, pygobject_gil_state_ensure, pygobject_gil_state_release, pyg_register_class_init, pyg_register_interface_info, pyg_closure_set_exception_handler, add_warning_redirection, disable_warning_redirections, NULL, /* previously type_register_custom */ pygi_gerror_exception_check, pyg_option_group_new, pyg_type_from_object_strict, pygobject_new_full, &PyGObject_Type, pyg_value_from_pyobject_with_error }; /** * Returns 0 on success, or -1 and sets an exception. */ static int pygi_register_api (PyObject *d) { PyObject *api; pygobject_api_functions.enum_type = PyGEnum_Type; pygobject_api_functions.flags_type = PyGFlags_Type; api = PyCapsule_New (&pygobject_api_functions, "gobject._PyGObject_API", NULL); if (api == NULL) return -1; PyDict_SetItemString (d, "_PyGObject_API", api); Py_DECREF (api); return 0; } /** * Returns 0 on success, or -1 and sets an exception. */ static int pygi_register_constants (PyObject *m) { /* PyFloat_ return a new ref, and add object takes the ref */ PyModule_AddObject (m, "G_MINFLOAT", pygi_gfloat_to_py (G_MINFLOAT)); PyModule_AddObject (m, "G_MAXFLOAT", pygi_gfloat_to_py (G_MAXFLOAT)); PyModule_AddObject (m, "G_MINDOUBLE", pygi_gdouble_to_py (G_MINDOUBLE)); PyModule_AddObject (m, "G_MAXDOUBLE", pygi_gdouble_to_py (G_MAXDOUBLE)); PyModule_AddIntConstant (m, "G_MINSHORT", G_MINSHORT); PyModule_AddIntConstant (m, "G_MAXSHORT", G_MAXSHORT); PyModule_AddIntConstant (m, "G_MAXUSHORT", G_MAXUSHORT); PyModule_AddIntConstant (m, "G_MININT", G_MININT); PyModule_AddIntConstant (m, "G_MAXINT", G_MAXINT); PyModule_AddObject (m, "G_MAXUINT", pygi_guint_to_py (G_MAXUINT)); PyModule_AddObject (m, "G_MINLONG", pygi_glong_to_py (G_MINLONG)); PyModule_AddObject (m, "G_MAXLONG", pygi_glong_to_py (G_MAXLONG)); PyModule_AddObject (m, "G_MAXULONG", pygi_gulong_to_py (G_MAXULONG)); PyModule_AddObject (m, "G_MAXSIZE", pygi_gsize_to_py (G_MAXSIZE)); PyModule_AddObject (m, "G_MAXSSIZE", pygi_gssize_to_py (G_MAXSSIZE)); PyModule_AddObject (m, "G_MINSSIZE", pygi_gssize_to_py (G_MINSSIZE)); PyModule_AddObject (m, "G_MINOFFSET", pygi_gint64_to_py (G_MINOFFSET)); PyModule_AddObject (m, "G_MAXOFFSET", pygi_gint64_to_py (G_MAXOFFSET)); PyModule_AddIntConstant (m, "SIGNAL_RUN_FIRST", G_SIGNAL_RUN_FIRST); PyModule_AddIntConstant (m, "PARAM_READWRITE", G_PARAM_READWRITE); /* The rest of the types are set in __init__.py */ PyModule_AddObject (m, "TYPE_INVALID", pyg_type_wrapper_new (G_TYPE_INVALID)); PyModule_AddObject (m, "TYPE_GSTRING", pyg_type_wrapper_new (G_TYPE_GSTRING)); return 0; } /** * Returns 0 on success, or -1 and sets an exception. */ static int pygi_register_version_tuples (PyObject *d) { PyObject *tuple; /* pygobject version */ tuple = Py_BuildValue ("(iii)", PYGOBJECT_MAJOR_VERSION, PYGOBJECT_MINOR_VERSION, PYGOBJECT_MICRO_VERSION); PyDict_SetItemString (d, "pygobject_version", tuple); Py_DECREF (tuple); return 0; } static PyModuleDef_Slot _gi_slots[] = { { Py_mod_exec, _gi_exec }, { 0, NULL }, }; static struct PyModuleDef __gimodule = { PyModuleDef_HEAD_INIT, "_gi", NULL, 0, _gi_functions, _gi_slots, NULL, NULL, NULL, }; #ifdef __GNUC__ #define PYGI_MODINIT_FUNC \ __attribute__ ((visibility ("default"))) PyMODINIT_FUNC #else #define PYGI_MODINIT_FUNC PyMODINIT_FUNC #endif PYGI_MODINIT_FUNC PyInit__gi (void); PYGI_MODINIT_FUNC PyInit__gi (void) { return PyModuleDef_Init (&__gimodule); } static int _gi_exec (PyObject *module) { PyObject *api; PyObject *module_dict = PyModule_GetDict (module); int ret; #if PY_VERSION_HEX < 0x03090000 || defined(PYPY_VERSION) /* Deprecated since 3.9 */ /* Except in PyPy it's still not a no-op: https://foss.heptapod.net/pypy/pypy/-/issues/3691, https://github.com/pypy/pypy/issues/3690 */ /* Always enable Python threads since we cannot predict which GI repositories * might accept Python callbacks run within non-Python threads or might trigger * toggle ref notifications. * See: https://bugzilla.gnome.org/show_bug.cgi?id=709223 */ PyEval_InitThreads (); #endif PyModule_AddStringConstant (module, "__package__", "gi._gi"); if ((ret = pygi_foreign_init ()) < 0) return ret; if ((ret = pygi_error_register_types (module)) < 0) return ret; if ((ret = pygi_repository_register_types (module)) < 0) return ret; if ((ret = pygi_info_register_types (module)) < 0) return ret; if ((ret = pygi_type_register_types (module_dict)) < 0) return ret; if ((ret = pygi_pointer_register_types (module_dict)) < 0) return ret; if ((ret = pygi_struct_register_types (module)) < 0) return ret; if ((ret = pygi_gboxed_register_types (module_dict)) < 0) return ret; if ((ret = pygi_fundamental_register_types (module)) < 0) return ret; if ((ret = pygi_boxed_register_types (module)) < 0) return ret; if ((ret = pygi_ccallback_register_types (module)) < 0) return ret; if ((ret = pygi_resulttuple_register_types (module)) < 0) return ret; if ((ret = pygi_async_register_types (module) < 0)) return ret; if ((ret = pygi_spawn_register_types (module_dict)) < 0) return ret; if ((ret = pygi_option_context_register_types (module_dict)) < 0) return ret; if ((ret = pygi_option_group_register_types (module_dict)) < 0) return ret; if ((ret = pygi_register_constants (module)) < 0) return ret; if ((ret = pygi_register_version_tuples (module_dict)) < 0) return ret; if ((ret = pygi_register_warnings (module_dict)) < 0) return ret; if ((ret = pyi_object_register_types (module_dict)) < 0) return ret; if ((ret = pygi_interface_register_types (module_dict)) < 0) return ret; if ((ret = pygi_enum_register_types (module)) < 0) return ret; if ((ret = pygi_flags_register_types (module)) < 0) return ret; if ((ret = pygi_register_api (module_dict)) < 0) return ret; PyGIWarning = PyErr_NewException ("gi.PyGIWarning", PyExc_Warning, NULL); if (PyGIWarning == NULL) return -1; PyGIDeprecationWarning = PyErr_NewException ( "gi.PyGIDeprecationWarning", PyExc_DeprecationWarning, NULL); /* Place holder object used to fill in "from Python" argument lists * for values not supplied by the caller but support a GI default. */ _PyGIDefaultArgPlaceholder = PyList_New (0); Py_INCREF (PyGIWarning); PyModule_AddObject (module, "PyGIWarning", PyGIWarning); Py_INCREF (PyGIDeprecationWarning); PyModule_AddObject (module, "PyGIDeprecationWarning", PyGIDeprecationWarning); api = PyCapsule_New ((void *)&CAPI, "gi._API", NULL); if (api == NULL) { return -1; } PyModule_AddObject (module, "_API", api); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/gimodule.h0000664000000000000000000000103215074673150014717 0ustar00rootroot#ifndef _PYGOBJECT_GIMODULE_H_ #define _PYGOBJECT_GIMODULE_H_ #include "pygobject-internal.h" int pygobject_constructv (PyGObject *self, guint n_properties, const char *names[], const GValue values[]); GObject *pygobject_object_new_with_properties (GType object_type, guint n_properties, const char *names[], const GValue values[]); #endif /*_PYGOBJECT_GIMODULE_H_*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/importer.py0000664000000000000000000001223415074673150015162 0ustar00rootroot# Copyright (C) 2005-2009 Johan Dahlin # 2015 Christoph Reiter # # importer.py: dynamic importer for introspected libraries. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import sys import warnings import importlib from contextlib import contextmanager import gi from ._gi import Repository, RepositoryError from ._gi import PyGIWarning from .module import get_introspection_module from .overrides import load_overrides repository = Repository.get_default() # only for backwards compatibility modules = {} @contextmanager def _check_require_version(namespace, stacklevel): """A context manager which tries to give helpful warnings about missing gi.require_version() which could potentially break code if only an older version than expected is installed or a new version gets introduced. :: with _check_require_version("Gtk", stacklevel): load_namespace_and_overrides() """ was_loaded = repository.is_registered(namespace) yield if was_loaded: # it was loaded before by another import which depended on this # namespace or by C code like libpeas return if namespace in ("GLib", "GObject", "Gio", "GioUnix", "GioWin32"): # part of glib (we have bigger problems if versions change there) return if gi.get_required_version(namespace) is not None: # the version was forced using require_version() return version = repository.get_version(namespace) warnings.warn( f"{namespace} was imported without specifying a version first. " f"Use gi.require_version('{namespace}', '{version}') before " "import to ensure that the right version gets loaded.", PyGIWarning, stacklevel=stacklevel, ) def get_import_stacklevel(import_hook): """Returns the stacklevel value for warnings.warn() for when the warning gets emitted by an imported module, but the warning should point at the code doing the import. Pass import_hook=True if the warning gets generated by an import hook (warn() gets called in load_module(), see PEP302) """ py_version = sys.version_info[:2] if py_version <= (3, 2): # 2.7 included return 4 if import_hook else 2 if py_version == (3, 3): return 8 if import_hook else 10 if py_version == (3, 4): return 10 if import_hook else 8 # fixed again in 3.5+, see https://bugs.python.org/issue24305 return 4 if import_hook else 2 class DynamicImporter: # Note: see PEP302 for the Importer Protocol implemented below. def __init__(self, path): self.path = path def _find_module_check(self, fullname): if not fullname.startswith(self.path): return False path, _namespace = fullname.rsplit(".", 1) return path == self.path def find_spec(self, fullname, path=None, target=None): if self._find_module_check(fullname): return importlib.util.spec_from_loader(fullname, self) return None def find_module(self, fullname, path=None): if self._find_module_check(fullname): return self return None def create_module(self, spec): _path, namespace = spec.name.rsplit(".", 1) # is_registered() is faster than enumerate_versions() and # in the common case of a namespace getting loaded before its # dependencies, is_registered() returns True for all dependencies. if not repository.is_registered( namespace ) and not repository.enumerate_versions(namespace): raise ImportError( f"cannot import name {namespace}, introspection typelib not found" ) stacklevel = get_import_stacklevel(import_hook=True) with _check_require_version(namespace, stacklevel=stacklevel): try: introspection_module = get_introspection_module(namespace) except RepositoryError as e: raise ImportError(e) from e # Import all dependencies first so their init functions # (gdk_init, ..) in overrides get called. # https://bugzilla.gnome.org/show_bug.cgi?id=656314 for dep in repository.get_immediate_dependencies(namespace): importlib.import_module("gi.repository." + dep.split("-")[0]) return load_overrides(introspection_module) def exec_module(self, fullname): # “exec†the module and consequently populate the module's namespace pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/meson.build0000664000000000000000000000405215074673150015110 0ustar00rootrootsources = [ 'pygboxed.c', 'pygenum.c', 'pygflags.c', 'pyginterface.c', 'pygobject-object.c', 'pygpointer.c', 'pygoptioncontext.c', 'pygoptiongroup.c', 'pygspawn.c', 'gimodule.c', 'pygi-repository.c', 'pygi-info.c', 'pygi-foreign.c', 'pygi-struct.c', 'pygi-source.c', 'pygi-argument.c', 'pygi-resulttuple.c', 'pygi-async.c', 'pygi-type.c', 'pygi-boxed.c', 'pygi-closure.c', 'pygi-ccallback.c', 'pygi-util.c', 'pygi-property.c', 'pygi-signal-closure.c', 'pygi-invoke.c', 'pygi-cache.c', 'pygi-marshal-cleanup.c', 'pygi-basictype.c', 'pygi-list.c', 'pygi-array.c', 'pygi-error.c', 'pygi-object.c', 'pygi-fundamental.c', 'pygi-value.c', 'pygi-enum-marshal.c', 'pygi-struct-marshal.c', 'pygi-hashtable.c'] headers = [ 'pygobject.h' ] install_headers(headers, subdir : 'pygobject-@0@'.format(platform_version)) python_sources = [ 'events.py', '_constants.py', 'docstring.py', '_enum.py', '_error.py', '_gtktemplate.py', 'importer.py', '__init__.py', 'module.py', '_option.py', '_ossighelper.py', '_propertyhelper.py', 'pygtkcompat.py', '_signalhelper.py', '_signature.py', 'types.py', ] python.install_sources(python_sources, pure : false, subdir : 'gi' ) # https://github.com/mesonbuild/meson/issues/4117 if host_machine.system() == 'windows' python_ext_dep = python_dep else python_ext_dep = python_dep.partial_dependency(compile_args: true) endif configure_file(output : 'config.h', configuration : cdata) giext = python.extension_module('_gi', sources, dependencies : [python_ext_dep, glib_dep, gi_dep, ffi_dep, pythoncapi_compat_dep], install: true, subdir : 'gi', c_args: pyext_c_args + main_c_args ) if cairo_dep.found() gicairoext = python.extension_module('_gi_cairo', ['pygi-foreign-cairo.c'], dependencies : [python_ext_dep, glib_dep, gi_dep, ffi_dep, pycairo_dep, cairo_dep, cairo_gobject_dep, pythoncapi_compat_dep], install: true, subdir : 'gi', c_args: pyext_c_args + main_c_args) endif subdir('overrides') subdir('repository') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/module.py0000664000000000000000000002061615074673150014611 0ustar00rootroot# Copyright (C) 2007-2009 Johan Dahlin # # module.py: dynamic module for introspected libraries. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import importlib from threading import Lock from types import ModuleType import gi from ._gi import ( Repository, FunctionInfo, RegisteredTypeInfo, EnumInfo, ObjectInfo, InterfaceInfo, ConstantInfo, StructInfo, UnionInfo, CallbackInfo, Struct, Boxed, Fundamental, CCallback, enum_add, flags_add, GInterface, ) from .types import GObjectMeta, StructMeta from ._constants import TYPE_NONE, TYPE_BOXED, TYPE_POINTER repository = Repository.get_default() # Cache of IntrospectionModules that have been loaded. _introspection_modules = {} def get_parent_for_object(object_info): parent_object_info = object_info.get_parent() if not parent_object_info: # If we reach the end of the introspection info class hierarchy, look # for an existing wrapper on the GType and use it as a base for the # new introspection wrapper. This allows static C wrappers already # registered with the GType to be used as the introspection base # (_gi.GObject for example) gtype = object_info.get_g_type() if gtype and gtype.pytype: return gtype.pytype if object_info.get_fundamental() and gtype.is_instantiatable(): return Fundamental # Otherwise use builtins.object as the base return object namespace = parent_object_info.get_namespace() name = parent_object_info.get_name() module = importlib.import_module("gi.repository." + namespace) return getattr(module, name) def get_interfaces_for_object(object_info): interfaces = [] for interface_info in object_info.get_interfaces(): namespace = interface_info.get_namespace() name = interface_info.get_name() module = importlib.import_module("gi.repository." + namespace) interfaces.append(getattr(module, name)) return interfaces class IntrospectionModule(ModuleType): """An object which wraps an introspection typelib. This wrapping creates a python module like representation of the typelib using gi repository as a foundation. Accessing attributes of the module will dynamically pull them in and create wrappers for the members. These members are then cached on this introspection module. """ def __init__(self, namespace, version=None): """Might raise gi._gi.RepositoryError.""" repository.require(namespace, version) super().__init__(f"gi.repository.{namespace}") self._namespace = namespace self._version = version path = repository.get_typelib_path(self._namespace) self.__path__ = [path] if self._version is None: self._version = repository.get_version(self._namespace) self._lock = Lock() def __getattr__(self, name): info = repository.find_by_name(self._namespace, name) if not info: raise AttributeError(f"{self.__name__!r} object has no attribute {name!r}") if isinstance(info, EnumInfo): g_type = info.get_g_type() with self._lock: wrapper = g_type.pytype if wrapper is None: if info.is_flags(): wrapper = flags_add(self, name, g_type, info) else: wrapper = enum_add(self, name, g_type, info) wrapper.__info__ = info for method_info in info.get_methods(): setattr(wrapper, method_info.__name__, method_info) if g_type != TYPE_NONE: g_type.pytype = wrapper elif isinstance(info, RegisteredTypeInfo): g_type = info.get_g_type() # Create a wrapper. if isinstance(info, ObjectInfo): parent = get_parent_for_object(info) interfaces = tuple( interface for interface in get_interfaces_for_object(info) if not issubclass(parent, interface) ) bases = (parent, *interfaces) metaclass = GObjectMeta elif isinstance(info, CallbackInfo): bases = (CCallback,) metaclass = GObjectMeta elif isinstance(info, InterfaceInfo): bases = (GInterface,) metaclass = GObjectMeta elif isinstance(info, (StructInfo, UnionInfo)): if g_type.is_a(TYPE_BOXED): bases = (Boxed,) elif ( g_type.is_a(TYPE_POINTER) or g_type == TYPE_NONE or g_type.fundamental == g_type ): bases = (Struct,) else: raise TypeError( f"unable to create a wrapper for {info.get_namespace()}.{info.get_name()}" ) metaclass = StructMeta else: raise NotImplementedError(info) with self._lock: # Check if there is already a Python wrapper that is not a parent class # of the wrapper being created. If it is a parent, it is ok to clobber # g_type.pytype with a new child class wrapper of the existing parent. # Note that the return here never occurs under normal circumstances due # to caching on the __dict__ itself. if g_type != TYPE_NONE: type_ = g_type.pytype if type_ is not None and type_ not in bases: self.__dict__[name] = type_ return type_ dict_ = { "__info__": info, "__module__": self.__name__, "__gtype__": g_type, } wrapper = metaclass(name, bases, dict_) # Register the new Python wrapper. if g_type != TYPE_NONE: g_type.pytype = wrapper elif isinstance(info, FunctionInfo): wrapper = info elif isinstance(info, ConstantInfo): wrapper = info.get_value() else: raise NotImplementedError(info) # Cache the newly created wrapper which will then be # available directly on this introspection module instead of being # lazily constructed through the __getattr__ we are currently in. self.__dict__[name] = wrapper return wrapper def __repr__(self): path = repository.get_typelib_path(self._namespace) return f"" def __dir__(self): result = set(super().__dir__()) # update *set* because some repository attributes have already been # wrapped by __getattr__() and included in self.__dict__; but skip # Callback types, as these are not real objects which we can actually # get namespace_infos = repository.get_infos(self._namespace) result.update( info.get_name() for info in namespace_infos if not isinstance(info, CallbackInfo) ) return list(result) def get_introspection_module(namespace): """:Returns: An object directly wrapping the gi module without overrides. Might raise gi._gi.RepositoryError """ if namespace in _introspection_modules: return _introspection_modules[namespace] version = gi.get_required_version(namespace) module = IntrospectionModule(namespace, version) _introspection_modules[namespace] = module return module ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/GIMarshallingTests.py0000664000000000000000000000415415074673150021031 0ustar00rootroot# Copyright (C) 2010 Simon van der Linden # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA from ..overrides import override from ..module import get_introspection_module GIMarshallingTests = get_introspection_module("GIMarshallingTests") __all__ = [] OVERRIDES_CONSTANT = 7 __all__.append("OVERRIDES_CONSTANT") class OverridesStruct(GIMarshallingTests.OverridesStruct): def __new__(cls, long_): return GIMarshallingTests.OverridesStruct.__new__(cls) def __init__(self, long_): GIMarshallingTests.OverridesStruct.__init__(self) self.long_ = long_ def method(self): return GIMarshallingTests.OverridesStruct.method(self) / 7 OverridesStruct = override(OverridesStruct) __all__.append("OverridesStruct") class OverridesObject(GIMarshallingTests.OverridesObject): def __new__(cls, long_): return GIMarshallingTests.OverridesObject.__new__(cls) def __init__(self, long_): GIMarshallingTests.OverridesObject.__init__(self) # FIXME: doesn't work yet # self.long_ = long_ @classmethod def new(cls, long_): # FIXME: doesn't work yet # self.long_ = long_ # return self return GIMarshallingTests.OverridesObject.new() def method(self): """Overridden doc string.""" return GIMarshallingTests.OverridesObject.method(self) / 7 OverridesObject = override(OverridesObject) __all__.append("OverridesObject") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/GLib.py0000664000000000000000000007403415074673150016146 0ustar00rootroot# Copyright (C) 2010 Tomeu Vizoso # Copyright (C) 2011, 2012 Canonical Ltd. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import contextlib import warnings import sys import socket from .._ossighelper import register_sigint_fallback, get_event_loop from ..module import get_introspection_module from .._gi import ( variant_type_from_string, source_new, source_set_callback, io_channel_read, main_context_query, ) from ..overrides import override, deprecated, deprecated_attr from gi import PyGIDeprecationWarning, version_info GLib = get_introspection_module("GLib") __all__ = [] from gi import _option as option option __all__.append("option") # Types and functions still needed from static bindings from gi import _gi from gi._error import GError Error = GError OptionContext = _gi.OptionContext OptionGroup = _gi.OptionGroup Pid = _gi.Pid spawn_async = _gi.spawn_async def threads_init(): warnings.warn( "Since version 3.11, calling threads_init is no longer needed. " "See: https://pygobject.gnome.org/guide/threading.html#threads-faq", PyGIDeprecationWarning, stacklevel=2, ) def gerror_matches(self, domain, code): # Handle cases where self.domain was set to an integer for compatibility # with the introspected GLib.Error. if isinstance(self.domain, str): self_domain_quark = GLib.quark_from_string(self.domain) else: self_domain_quark = self.domain return (self_domain_quark, self.code) == (domain, code) def gerror_new_literal(domain, message, code): domain_quark = GLib.quark_to_string(domain) return GError(message, domain_quark, code) # Monkey patch methods that rely on GLib introspection to be loaded at runtime. Error.__name__ = "Error" Error.__module__ = "gi.repository.GLib" Error.__gtype__ = GLib.Error.__gtype__ Error.matches = gerror_matches Error.new_literal = staticmethod(gerror_new_literal) __all__ += [ "Error", "GError", "OptionContext", "OptionGroup", "Pid", "spawn_async", "threads_init", ] class _VariantCreator: _LEAF_CONSTRUCTORS = { "b": GLib.Variant.new_boolean, "y": GLib.Variant.new_byte, "n": GLib.Variant.new_int16, "q": GLib.Variant.new_uint16, "i": GLib.Variant.new_int32, "u": GLib.Variant.new_uint32, "x": GLib.Variant.new_int64, "t": GLib.Variant.new_uint64, "h": GLib.Variant.new_handle, "d": GLib.Variant.new_double, "s": GLib.Variant.new_string, "o": GLib.Variant.new_object_path, "g": GLib.Variant.new_signature, "v": GLib.Variant.new_variant, } def _create(self, format, value): """Create a GVariant object from given format and a value that matches the format. This method recursively calls itself for complex structures (arrays, dictionaries, boxed). Returns the generated GVariant. If value is None it will generate an empty GVariant container type. """ gvtype = GLib.VariantType(format) if format in self._LEAF_CONSTRUCTORS: return self._LEAF_CONSTRUCTORS[format](value) # Since we discarded all leaf types, this must be a container builder = GLib.VariantBuilder.new(gvtype) if value is None: return builder.end() if gvtype.is_maybe(): builder.add_value(self._create(gvtype.element().dup_string(), value)) return builder.end() try: iter(value) except TypeError: raise TypeError( f"Could not create array, tuple or dictionary entry from non iterable value {format} {value}" ) if gvtype.is_tuple() and gvtype.n_items() != len(value): raise TypeError( f"Tuple mismatches value's number of elements {format} {value}" ) if gvtype.is_dict_entry() and len(value) != 2: raise TypeError( f"Dictionary entries must have two elements {format} {value}" ) if gvtype.is_array(): element_type = gvtype.element().dup_string() if isinstance(value, dict): value = value.items() for i in value: builder.add_value(self._create(element_type, i)) else: remainer_format = format[1:] for i in value: dup = variant_type_from_string(remainer_format).dup_string() builder.add_value(self._create(dup, i)) remainer_format = remainer_format[len(dup) :] return builder.end() LEAF_ACCESSORS = { "b": "get_boolean", "y": "get_byte", "n": "get_int16", "q": "get_uint16", "i": "get_int32", "u": "get_uint32", "x": "get_int64", "t": "get_uint64", "h": "get_handle", "d": "get_double", "s": "get_string", "o": "get_string", # object path "g": "get_string", # signature } class Variant(GLib.Variant): def __new__(cls, format_string, value): """Create a GVariant from a native Python object. format_string is a standard GVariant type signature, value is a Python object whose structure has to match the signature. Examples: GLib.Variant('i', 1) GLib.Variant('(is)', (1, 'hello')) GLib.Variant('(asa{sv})', ([], {'foo': GLib.Variant('b', True), 'bar': GLib.Variant('i', 2)})) """ if not GLib.VariantType.string_is_valid(format_string): raise TypeError("Invalid GVariant format string '%s'", format_string) creator = _VariantCreator() v = creator._create(format_string, value) v.format_string = format_string return v @staticmethod def new_tuple(*elements): return GLib.Variant.new_tuple(elements) def __del__(self): with contextlib.suppress(ImportError): # Calling unref will cause gi and gi.repository.GLib to be # imported. However, if the program is exiting, then these # modules have likely been removed from sys.modules and will # raise an exception. Assume that's the case for ImportError # and ignore the exception since everything will be cleaned # up, anyway. self.unref() def __str__(self): return self.print_(True) def __repr__(self): if hasattr(self, "format_string"): f = self.format_string else: f = self.get_type_string() return f"GLib.Variant('{f}', {self.print_(False)})" def __eq__(self, other): try: return self.equal(other) except TypeError: return False def __ne__(self, other): try: return not self.equal(other) except TypeError: return True def __hash__(self): # We're not using just hash(self.unpack()) because otherwise we'll have # hash collisions between the same content in different variant types, # which will cause a performance issue in set/dict/etc. return hash((self.get_type_string(), self.unpack())) def unpack(self): """Decompose a GVariant into a native Python object.""" type_string = self.get_type_string() # simple values la = LEAF_ACCESSORS.get(type_string) if la: return getattr(self, la)() # tuple if type_string.startswith("("): return tuple( self.get_child_value(i).unpack() for i in range(self.n_children()) ) # dictionary if type_string.startswith("a{"): res = {} for i in range(self.n_children()): v = self.get_child_value(i) res[v.get_child_value(0).unpack()] = v.get_child_value(1).unpack() return res # array if type_string.startswith("a"): return [self.get_child_value(i).unpack() for i in range(self.n_children())] # variant (just unbox transparently) if type_string.startswith("v"): return self.get_variant().unpack() # maybe if type_string.startswith("m"): if not self.n_children(): return None return self.get_child_value(0).unpack() raise NotImplementedError("unsupported GVariant type " + type_string) @classmethod def split_signature(klass, signature): """Return a list of the element signatures of the topmost signature tuple. If the signature is not a tuple, it returns one element with the entire signature. If the signature is an empty tuple, the result is []. This is useful for e. g. iterating over method parameters which are passed as a single Variant. """ if signature == "()": return [] if not signature.startswith("("): return [signature] result = [] head = "" tail = signature[1:-1] # eat the surrounding () while tail: c = tail[0] head += c tail = tail[1:] if c in ("m", "a"): # prefixes, keep collecting continue if c in ("(", "{"): # consume until corresponding )/} level = 1 up = c down = ")" if up == "(" else "}" while level > 0: c = tail[0] head += c tail = tail[1:] if c == up: level += 1 elif c == down: level -= 1 # otherwise we have a simple type result.append(head) head = "" return result # # Pythonic iterators # def __len__(self): if self.get_type_string() in ["s", "o", "g"]: return len(self.get_string()) # Array, dict, tuple if self.get_type_string().startswith("a") or self.get_type_string().startswith( "(" ): return self.n_children() raise TypeError( f"GVariant type {self.get_type_string()} does not have a length" ) def __getitem__(self, key): # dict if self.get_type_string().startswith("a{"): try: val = self.lookup_value(key, variant_type_from_string("*")) if val is None: raise KeyError(key) return val.unpack() except TypeError: # lookup_value() only works for string keys, which is certainly # the common case; we have to do painful iteration for other # key types for i in range(self.n_children()): v = self.get_child_value(i) if v.get_child_value(0).unpack() == key: return v.get_child_value(1).unpack() raise KeyError(key) # array/tuple if self.get_type_string().startswith("a") or self.get_type_string().startswith( "(" ): key = int(key) if key < 0: key = self.n_children() + key if key < 0 or key >= self.n_children(): raise IndexError("list index out of range") return self.get_child_value(key).unpack() # string if self.get_type_string() in ["s", "o", "g"]: return self.get_string().__getitem__(key) raise TypeError(f"GVariant type {self.get_type_string()} is not a container") # # Pythonic bool operations # def __nonzero__(self): return self.__bool__() def __bool__(self): if self.get_type_string() in ["y", "n", "q", "i", "u", "x", "t", "h", "d"]: return self.unpack() != 0 if self.get_type_string() in ["b"]: return self.get_boolean() if self.get_type_string() in ["s", "o", "g"]: return len(self.get_string()) != 0 # Array, dict, tuple if self.get_type_string().startswith("a") or self.get_type_string().startswith( "(" ): return self.n_children() != 0 # unpack works recursively, hence bool also works recursively return bool(self.unpack()) def keys(self): if not self.get_type_string().startswith("a{"): raise TypeError( f"GVariant type {self.get_type_string()} is not a dictionary" ) res = [] for i in range(self.n_children()): v = self.get_child_value(i) res.append(v.get_child_value(0).unpack()) return res def get_string(self): value, _length = GLib.Variant.get_string(self) return value setattr(Variant, "get_string", get_string) __all__.append("Variant") def markup_escape_text(text, length=-1): if isinstance(text, bytes): return GLib.markup_escape_text(text.decode("UTF-8"), length) return GLib.markup_escape_text(text, length) __all__.append("markup_escape_text") # backwards compatible names from old static bindings for n in [ "DESKTOP", "DOCUMENTS", "DOWNLOAD", "MUSIC", "PICTURES", "PUBLIC_SHARE", "TEMPLATES", "VIDEOS", ]: attr = "USER_DIRECTORY_" + n deprecated_attr("GLib", attr, "GLib.UserDirectory.DIRECTORY_" + n) globals()[attr] = getattr(GLib.UserDirectory, "DIRECTORY_" + n) __all__.append(attr) for n in ["ERR", "HUP", "IN", "NVAL", "OUT", "PRI"]: globals()["IO_" + n] = getattr(GLib.IOCondition, n) __all__.append("IO_" + n) for n in [ "APPEND", "GET_MASK", "IS_READABLE", "IS_SEEKABLE", "MASK", "NONBLOCK", "SET_MASK", ]: attr = "IO_FLAG_" + n deprecated_attr("GLib", attr, "GLib.IOFlags." + n) globals()[attr] = getattr(GLib.IOFlags, n) __all__.append(attr) # spelling for the win IO_FLAG_IS_WRITEABLE = GLib.IOFlags.IS_WRITABLE deprecated_attr("GLib", "IO_FLAG_IS_WRITEABLE", "GLib.IOFlags.IS_WRITABLE") __all__.append("IO_FLAG_IS_WRITEABLE") for n in ["AGAIN", "EOF", "ERROR", "NORMAL"]: attr = "IO_STATUS_" + n globals()[attr] = getattr(GLib.IOStatus, n) deprecated_attr("GLib", attr, "GLib.IOStatus." + n) __all__.append(attr) for n in [ "CHILD_INHERITS_STDIN", "DO_NOT_REAP_CHILD", "FILE_AND_ARGV_ZERO", "LEAVE_DESCRIPTORS_OPEN", "SEARCH_PATH", "STDERR_TO_DEV_NULL", "STDOUT_TO_DEV_NULL", ]: attr = "SPAWN_" + n globals()[attr] = getattr(GLib.SpawnFlags, n) deprecated_attr("GLib", attr, "GLib.SpawnFlags." + n) __all__.append(attr) for n in [ "HIDDEN", "IN_MAIN", "REVERSE", "NO_ARG", "FILENAME", "OPTIONAL_ARG", "NOALIAS", ]: attr = "OPTION_FLAG_" + n globals()[attr] = getattr(GLib.OptionFlags, n) deprecated_attr("GLib", attr, "GLib.OptionFlags." + n) __all__.append(attr) for n in ["UNKNOWN_OPTION", "BAD_VALUE", "FAILED"]: attr = "OPTION_ERROR_" + n deprecated_attr("GLib", attr, "GLib.OptionError." + n) globals()[attr] = getattr(GLib.OptionError, n) __all__.append(attr) # these are not currently exported in GLib gir, presumably because they are # platform dependent; so get them from our static bindings for name in [ "G_MINFLOAT", "G_MAXFLOAT", "G_MINDOUBLE", "G_MAXDOUBLE", "G_MINSHORT", "G_MAXSHORT", "G_MAXUSHORT", "G_MININT", "G_MAXINT", "G_MAXUINT", "G_MINLONG", "G_MAXLONG", "G_MAXULONG", "G_MAXSIZE", "G_MINSSIZE", "G_MAXSSIZE", "G_MINOFFSET", "G_MAXOFFSET", ]: attr = name.split("_", 1)[-1] globals()[attr] = getattr(_gi, name) __all__.append(attr) class MainLoop(GLib.MainLoop): # Backwards compatible constructor API def __new__(cls, context=None): return GLib.MainLoop.new(context, False) def __init__(self, context=None): pass def run(self): with ( register_sigint_fallback(self.quit), get_event_loop(self.get_context()).running(self.quit), ): super().run() MainLoop = override(MainLoop) __all__.append("MainLoop") class MainContext(GLib.MainContext): # Backwards compatible API with default value def iteration(self, may_block=True): with get_event_loop(self).paused(): return super().iteration(may_block) def query(self, max_priority: int) -> tuple[int, list[GLib.PollFD]]: """Determines information necessary to poll this main loop. :param max_priority: maximum priority source to check :returns: The timeout (msec) used for polling, and the list of poll fd's. Please also check the usage notes in the `C documention `__. """ return main_context_query(self, max_priority) MainContext = override(MainContext) __all__.append("MainContext") class Source(GLib.Source): def __new__(cls, *args, **kwargs): # use our custom pygi_source_new() here as g_source_new() is not # bindable source = source_new() source.__class__ = cls setattr(source, "__pygi_custom_source", True) return source def __init__(self, *args, **kwargs): return super().__init__() def __del__(self): if hasattr(self, "__pygi_custom_source"): # We destroy and finalize the box from here, as GLib might hold # a reference (e.g. while the source is pending), delaying the # finalize call until a later point. self.destroy() self.finalize() self._clear_boxed() def finalize(self): pass def set_callback(self, fn, user_data=None): if hasattr(self, "__pygi_custom_source"): # use our custom pygi_source_set_callback() if for a GSource object # with custom functions source_set_callback(self, fn, user_data) else: # otherwise, for Idle and Timeout, use the standard method super().set_callback(fn, user_data) def get_current_time(self): return GLib.get_real_time() * 0.000001 get_current_time = deprecated( get_current_time, "GLib.Source.get_time() or GLib.get_real_time()" ) # as get/set_priority are introspected, we can't use the static # property(get_priority, ..) here def __get_priority(self): return self.get_priority() def __set_priority(self, value): self.set_priority(value) priority = property(__get_priority, __set_priority) def __get_can_recurse(self): return self.get_can_recurse() def __set_can_recurse(self, value): self.set_can_recurse(value) can_recurse = property(__get_can_recurse, __set_can_recurse) Source = override(Source) __all__.append("Source") class Idle(Source): def __new__(cls, priority=GLib.PRIORITY_DEFAULT): source = GLib.idle_source_new() source.__class__ = cls return source def __init__(self, priority=GLib.PRIORITY_DEFAULT): super(Source, self).__init__() if priority != GLib.PRIORITY_DEFAULT: self.set_priority(priority) __all__.append("Idle") class Timeout(Source): def __new__(cls, interval=0, priority=GLib.PRIORITY_DEFAULT): source = GLib.timeout_source_new(interval) source.__class__ = cls return source def __init__(self, interval=0, priority=GLib.PRIORITY_DEFAULT): if priority != GLib.PRIORITY_DEFAULT: self.set_priority(priority) __all__.append("Timeout") # backwards compatible API def idle_add(function, *user_data, priority=GLib.PRIORITY_DEFAULT_IDLE): return GLib.idle_add(priority, function, *user_data) __all__.append("idle_add") def timeout_add(interval, function, *user_data, priority=GLib.PRIORITY_DEFAULT): return GLib.timeout_add(priority, interval, function, *user_data) __all__.append("timeout_add") def timeout_add_seconds(interval, function, *user_data, priority=GLib.PRIORITY_DEFAULT): return GLib.timeout_add_seconds(priority, interval, function, *user_data) __all__.append("timeout_add_seconds") # The GI GLib API uses g_io_add_watch_full renamed to g_io_add_watch with # a signature of (channel, priority, condition, func, user_data). # Prior to PyGObject 3.8, this function was statically bound with an API closer to the # non-full version with a signature of: (fd, condition, func, *user_data) # We need to support this until we are okay with breaking API in a way which is # not backwards compatible. # # This needs to take into account several historical APIs: # - calling with an fd as first argument # - calling with a Python file object as first argument (we keep this one as # it's really convenient and does not change the number of arguments) # - calling without a priority as second argument def _io_add_watch_get_args(channel, priority_, condition, *cb_and_user_data, **kwargs): if not isinstance(priority_, int) or isinstance(priority_, GLib.IOCondition): warnings.warn( "Calling io_add_watch without priority as second argument is deprecated", PyGIDeprecationWarning, ) # shift the arguments around user_data = cb_and_user_data callback = condition condition = priority_ if not callable(callback): raise TypeError("third argument must be callable") # backwards compatibility: Call with priority kwarg if "priority" in kwargs: warnings.warn( "Calling io_add_watch with priority keyword argument is deprecated, put it as second positional argument", PyGIDeprecationWarning, ) priority_ = kwargs["priority"] else: priority_ = GLib.PRIORITY_DEFAULT else: if len(cb_and_user_data) < 1 or not callable(cb_and_user_data[0]): raise TypeError("expecting callback as fourth argument") callback = cb_and_user_data[0] user_data = cb_and_user_data[1:] # backwards compatibility: Allow calling with fd if isinstance(channel, int): def func_fdtransform(_, cond, *data): return callback(channel, cond, *data) real_channel = GLib.IOChannel.unix_new(channel) elif isinstance(channel, socket.socket) and sys.platform == "win32": def func_fdtransform(_, cond, *data): return callback(channel, cond, *data) real_channel = GLib.IOChannel.win32_new_socket(channel.fileno()) elif hasattr(channel, "fileno"): # backwards compatibility: Allow calling with Python file def func_fdtransform(_, cond, *data): return callback(channel, cond, *data) real_channel = GLib.IOChannel.unix_new(channel.fileno()) else: assert isinstance(channel, GLib.IOChannel) func_fdtransform = callback real_channel = channel return real_channel, priority_, condition, func_fdtransform, user_data __all__.append("_io_add_watch_get_args") def io_add_watch(*args, **kwargs): """io_add_watch(channel, priority, condition, func, *user_data) -> event_source_id.""" channel, priority, condition, func, user_data = _io_add_watch_get_args( *args, **kwargs ) return GLib.io_add_watch(channel, priority, condition, func, *user_data) __all__.append("io_add_watch") # backwards compatible API class IOChannel(GLib.IOChannel): def __new__(cls, filedes=None, filename=None, mode=None, hwnd=None): if filedes is not None: return GLib.IOChannel.unix_new(filedes) if filename is not None: return GLib.IOChannel.new_file(filename, mode or "r") if hwnd is not None: return GLib.IOChannel.win32_new_fd(hwnd) raise TypeError( "either a valid file descriptor, file name, or window handle must be supplied" ) def __init__(self, *args, **kwargs): return super().__init__() def read(self, max_count=-1): """Reads data from a :obj:`~gi.repository.GLib.IOChannel`.""" return io_channel_read(self, max_count) def read_chars(self, max_count=-1): """Alias for GLib.IOChannel.read().""" return self.read(max_count) def readline(self, size_hint=-1): # note, size_hint is just to maintain backwards compatible API; the # old static binding did not actually use it (_status, buf, _length, _terminator_pos) = self.read_line() if buf is None: return "" return buf def readlines(self, size_hint=-1): # note, size_hint is just to maintain backwards compatible API; # the old static binding did not actually use it lines = [] status = GLib.IOStatus.NORMAL while status == GLib.IOStatus.NORMAL: (status, buf, _length, _terminator_pos) = self.read_line() # note, this appends an empty line after EOF; this is # bug-compatible with the old static bindings if buf is None: buf = "" lines.append(buf) return lines def write(self, buf, buflen=-1): if not isinstance(buf, bytes): buf = buf.encode("UTF-8") if buflen == -1: buflen = len(buf) (_status, written) = self.write_chars(buf, buflen) return written def writelines(self, lines): for line in lines: self.write(line) _whence_map = {0: GLib.SeekType.SET, 1: GLib.SeekType.CUR, 2: GLib.SeekType.END} def seek(self, offset, whence=0): try: w = self._whence_map[whence] except KeyError: raise ValueError("invalid 'whence' value") return self.seek_position(offset, w) def add_watch( self, condition, callback, *user_data, priority=GLib.PRIORITY_DEFAULT ): return io_add_watch(self, priority, condition, callback, *user_data) add_watch = deprecated(add_watch, "GLib.io_add_watch()") def __iter__(self): return self def __next__(self): (status, buf, _length, _terminator_pos) = self.read_line() if status == GLib.IOStatus.NORMAL: return buf raise StopIteration IOChannel = override(IOChannel) __all__.append("IOChannel") class PollFD(GLib.PollFD): def __new__(cls, fd, events): pollfd = GLib.PollFD() pollfd.__class__ = cls return pollfd def __init__(self, fd, events): self.fd = fd self.events = events PollFD = override(PollFD) __all__.append("PollFD") # The GI GLib API uses g_child_watch_add_full renamed to g_child_watch_add with # a signature of (priority, pid, callback, data). # Prior to PyGObject 3.8, this function was statically bound with an API closer to the # non-full version with a signature of: (pid, callback, data=None, priority=GLib.PRIORITY_DEFAULT) # We need to support this until we are okay with breaking API in a way which is # not backwards compatible. def _child_watch_add_get_args(priority_or_pid, pid_or_callback, *args, **kwargs): user_data = [] if callable(pid_or_callback): warnings.warn( "Calling child_watch_add without priority as first argument is deprecated", PyGIDeprecationWarning, ) pid = priority_or_pid callback = pid_or_callback if len(args) == 0: priority = kwargs.get("priority", GLib.PRIORITY_DEFAULT) elif len(args) == 1: user_data = args priority = kwargs.get("priority", GLib.PRIORITY_DEFAULT) elif len(args) == 2: user_data = [args[0]] priority = args[1] else: raise TypeError("expected at most 4 positional arguments") else: priority = priority_or_pid pid = pid_or_callback if "function" in kwargs: callback = kwargs["function"] user_data = args elif len(args) > 0 and callable(args[0]): callback = args[0] user_data = args[1:] else: raise TypeError("expected callback as third argument") if "data" in kwargs: if user_data: raise TypeError('got multiple values for "data" argument') user_data = (kwargs["data"],) return priority, pid, callback, user_data # we need this to be accessible for unit testing __all__.append("_child_watch_add_get_args") def child_watch_add(*args, **kwargs): """child_watch_add(priority, pid, function, *data).""" priority, pid, function, data = _child_watch_add_get_args(*args, **kwargs) return GLib.child_watch_add(priority, pid, function, *data) __all__.append("child_watch_add") def get_current_time(): return GLib.get_real_time() * 0.000001 get_current_time = deprecated(get_current_time, "GLib.get_real_time()") __all__.append("get_current_time") # backwards compatible API with default argument, and ignoring bytes_read # output argument def filename_from_utf8(utf8string, len=-1): return GLib.filename_from_utf8(utf8string, len)[0] __all__.append("filename_from_utf8") if hasattr(GLib, "unix_signal_add"): unix_signal_add_full = GLib.unix_signal_add __all__.append("unix_signal_add_full") deprecated_attr("GLib", "unix_signal_add_full", "GLib.unix_signal_add") # obsolete constants for backwards compatibility glib_version = (GLib.MAJOR_VERSION, GLib.MINOR_VERSION, GLib.MICRO_VERSION) __all__.append("glib_version") deprecated_attr( "GLib", "glib_version", "(GLib.MAJOR_VERSION, GLib.MINOR_VERSION, GLib.MICRO_VERSION)", ) pyglib_version = version_info __all__.append("pyglib_version") deprecated_attr("GLib", "pyglib_version", "gi.version_info") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/GObject.py0000664000000000000000000006207415074673150016647 0ustar00rootroot# -*- Mode: Python; py-indent-offset: 4 -*- # vim: tabstop=4 shiftwidth=4 expandtab # # Copyright (C) 2012 Canonical Ltd. # Author: Martin Pitt # Copyright (C) 2012-2013 Simon Feltman # Copyright (C) 2012 Bastian Winkler # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import functools import warnings from collections import namedtuple import gi.module from gi.overrides import override, deprecated_attr from gi.repository import GLib from gi import PyGIDeprecationWarning from gi import _propertyhelper as propertyhelper from gi import _signalhelper as signalhelper from gi import _gi GObjectModule = gi.module.get_introspection_module("GObject") __all__ = [] from gi import _option as option option = option # API aliases for backwards compatibility for name in [ "markup_escape_text", "get_application_name", "set_application_name", "get_prgname", "set_prgname", "main_depth", "filename_display_basename", "filename_display_name", "filename_from_utf8", "uri_list_extract_uris", "MainLoop", "MainContext", "main_context_default", "source_remove", "Source", "Idle", "Timeout", "PollFD", "idle_add", "timeout_add", "timeout_add_seconds", "io_add_watch", "child_watch_add", "get_current_time", "spawn_async", ]: globals()[name] = getattr(GLib, name) deprecated_attr("GObject", name, "GLib." + name) __all__.append(name) # deprecated constants for name in [ "PRIORITY_DEFAULT", "PRIORITY_DEFAULT_IDLE", "PRIORITY_HIGH", "PRIORITY_HIGH_IDLE", "PRIORITY_LOW", "IO_IN", "IO_OUT", "IO_PRI", "IO_ERR", "IO_HUP", "IO_NVAL", "IO_STATUS_ERROR", "IO_STATUS_NORMAL", "IO_STATUS_EOF", "IO_STATUS_AGAIN", "IO_FLAG_APPEND", "IO_FLAG_NONBLOCK", "IO_FLAG_IS_READABLE", "IO_FLAG_IS_WRITEABLE", "IO_FLAG_IS_SEEKABLE", "IO_FLAG_MASK", "IO_FLAG_GET_MASK", "IO_FLAG_SET_MASK", "SPAWN_LEAVE_DESCRIPTORS_OPEN", "SPAWN_DO_NOT_REAP_CHILD", "SPAWN_SEARCH_PATH", "SPAWN_STDOUT_TO_DEV_NULL", "SPAWN_STDERR_TO_DEV_NULL", "SPAWN_CHILD_INHERITS_STDIN", "SPAWN_FILE_AND_ARGV_ZERO", "OPTION_FLAG_HIDDEN", "OPTION_FLAG_IN_MAIN", "OPTION_FLAG_REVERSE", "OPTION_FLAG_NO_ARG", "OPTION_FLAG_FILENAME", "OPTION_FLAG_OPTIONAL_ARG", "OPTION_FLAG_NOALIAS", "OPTION_ERROR_UNKNOWN_OPTION", "OPTION_ERROR_BAD_VALUE", "OPTION_ERROR_FAILED", "OPTION_REMAINING", "glib_version", ]: with warnings.catch_warnings(): # TODO: this uses deprecated Glib attributes, silence for now warnings.simplefilter("ignore", PyGIDeprecationWarning) globals()[name] = getattr(GLib, name) deprecated_attr("GObject", name, "GLib." + name) __all__.append(name) for name in [ "G_MININT8", "G_MAXINT8", "G_MAXUINT8", "G_MININT16", "G_MAXINT16", "G_MAXUINT16", "G_MININT32", "G_MAXINT32", "G_MAXUINT32", "G_MININT64", "G_MAXINT64", "G_MAXUINT64", ]: new_name = name.split("_", 1)[-1] globals()[name] = getattr(GLib, new_name) deprecated_attr("GObject", name, "GLib." + new_name) __all__.append(name) # these are not currently exported in GLib gir, presumably because they are # platform dependent; so get them from our static bindings for name in [ "G_MINFLOAT", "G_MAXFLOAT", "G_MINDOUBLE", "G_MAXDOUBLE", "G_MINSHORT", "G_MAXSHORT", "G_MAXUSHORT", "G_MININT", "G_MAXINT", "G_MAXUINT", "G_MINLONG", "G_MAXLONG", "G_MAXULONG", "G_MAXSIZE", "G_MINSSIZE", "G_MAXSSIZE", "G_MINOFFSET", "G_MAXOFFSET", ]: new_name = name.split("_", 1)[-1] globals()[name] = getattr(GLib, new_name) deprecated_attr("GObject", name, "GLib." + new_name) __all__.append(name) TYPE_INVALID = GObjectModule.type_from_name("invalid") TYPE_NONE = GObjectModule.type_from_name("void") TYPE_INTERFACE = GObjectModule.type_from_name("GInterface") TYPE_CHAR = GObjectModule.type_from_name("gchar") TYPE_UCHAR = GObjectModule.type_from_name("guchar") TYPE_BOOLEAN = GObjectModule.type_from_name("gboolean") TYPE_INT = GObjectModule.type_from_name("gint") TYPE_UINT = GObjectModule.type_from_name("guint") TYPE_LONG = GObjectModule.type_from_name("glong") TYPE_ULONG = GObjectModule.type_from_name("gulong") TYPE_INT64 = GObjectModule.type_from_name("gint64") TYPE_UINT64 = GObjectModule.type_from_name("guint64") TYPE_ENUM = GObjectModule.type_from_name("GEnum") TYPE_FLAGS = GObjectModule.type_from_name("GFlags") TYPE_FLOAT = GObjectModule.type_from_name("gfloat") TYPE_DOUBLE = GObjectModule.type_from_name("gdouble") TYPE_STRING = GObjectModule.type_from_name("gchararray") TYPE_POINTER = GObjectModule.type_from_name("gpointer") TYPE_BOXED = GObjectModule.type_from_name("GBoxed") TYPE_PARAM = GObjectModule.type_from_name("GParam") TYPE_OBJECT = GObjectModule.type_from_name("GObject") TYPE_PYOBJECT = GObjectModule.type_from_name("PyObject") TYPE_GTYPE = GObjectModule.type_from_name("GType") TYPE_STRV = GObjectModule.type_from_name("GStrv") TYPE_VARIANT = GObjectModule.type_from_name("GVariant") TYPE_GSTRING = GObjectModule.type_from_name("GString") TYPE_VALUE = GObjectModule.Value.__gtype__ TYPE_UNICHAR = TYPE_UINT __all__ += [ "TYPE_BOOLEAN", "TYPE_BOXED", "TYPE_CHAR", "TYPE_DOUBLE", "TYPE_ENUM", "TYPE_FLAGS", "TYPE_FLOAT", "TYPE_GSTRING", "TYPE_GTYPE", "TYPE_INT", "TYPE_INT64", "TYPE_INTERFACE", "TYPE_INVALID", "TYPE_LONG", "TYPE_NONE", "TYPE_OBJECT", "TYPE_PARAM", "TYPE_POINTER", "TYPE_PYOBJECT", "TYPE_STRING", "TYPE_STRV", "TYPE_UCHAR", "TYPE_UINT", "TYPE_UINT64", "TYPE_ULONG", "TYPE_UNICHAR", "TYPE_VALUE", "TYPE_VARIANT", ] # Deprecated, use GLib directly for name in ["Pid", "GError", "OptionGroup", "OptionContext"]: globals()[name] = getattr(GLib, name) deprecated_attr("GObject", name, "GLib." + name) __all__.append(name) # Deprecated, use: GObject.ParamFlags.* directly for name in [ "PARAM_CONSTRUCT", "PARAM_CONSTRUCT_ONLY", "PARAM_LAX_VALIDATION", "PARAM_READABLE", "PARAM_WRITABLE", ]: new_name = name.split("_", 1)[-1] globals()[name] = getattr(GObjectModule.ParamFlags, new_name) deprecated_attr("GObject", name, "GObject.ParamFlags." + new_name) __all__.append(name) # PARAM_READWRITE should come from the gi module but cannot due to: # https://gitlab.gnome.org/GNOME/gobject-introspection/issues/75 PARAM_READWRITE = GObjectModule.ParamFlags.READABLE | GObjectModule.ParamFlags.WRITABLE deprecated_attr("GObject", "PARAM_READWRITE", "GObject.ParamFlags.READWRITE") __all__.append("PARAM_READWRITE") # Deprecated, use: GObject.SignalFlags.* directly for name in [ "SIGNAL_ACTION", "SIGNAL_DETAILED", "SIGNAL_NO_HOOKS", "SIGNAL_NO_RECURSE", "SIGNAL_RUN_CLEANUP", "SIGNAL_RUN_FIRST", "SIGNAL_RUN_LAST", ]: new_name = name.split("_", 1)[-1] globals()[name] = getattr(GObjectModule.SignalFlags, new_name) deprecated_attr("GObject", name, "GObject.SignalFlags." + new_name) __all__.append(name) # Static types GBoxed = _gi.GBoxed GEnum = _gi.GEnum GFlags = _gi.GFlags GInterface = _gi.GInterface GObject = _gi.GObject GObjectWeakRef = _gi.GObjectWeakRef GPointer = _gi.GPointer GType = _gi.GType Warning = _gi.Warning __all__ += [ "GBoxed", "GEnum", "GFlags", "GInterface", "GObject", "GObjectWeakRef", "GPointer", "GType", "Warning", ] features = {"generic-c-marshaller": True} list_properties = _gi.list_properties new = _gi.new pygobject_version = _gi.pygobject_version threads_init = GLib.threads_init type_register = _gi.type_register __all__ += [ "features", "list_properties", "new", "pygobject_version", "threads_init", "type_register", ] class Value(GObjectModule.Value): def __init__(self, value_type=None, py_value=None): GObjectModule.Value.__init__(self) if value_type is not None: self.init(value_type) if py_value is not None: self.set_value(py_value) @property def __g_type(self): # XXX: This is the same as self.g_type, but the field marshalling # code is currently very slow. return _gi._gvalue_get_type(self) def set_boxed(self, boxed): if not self.__g_type.is_a(TYPE_BOXED): warnings.warn( "Calling set_boxed() on a non-boxed type deprecated", PyGIDeprecationWarning, stacklevel=2, ) # Workaround the introspection marshalers inability to know # these methods should be marshaling boxed types. This is because # the type information is stored on the GValue. _gi._gvalue_set(self, boxed) def get_boxed(self): if not self.__g_type.is_a(TYPE_BOXED): warnings.warn( "Calling get_boxed() on a non-boxed type deprecated", PyGIDeprecationWarning, stacklevel=2, ) return _gi._gvalue_get(self) def set_value(self, py_value): gtype = self.__g_type if gtype == TYPE_CHAR: self.set_char(py_value) elif gtype == TYPE_UCHAR: self.set_uchar(py_value) elif gtype == TYPE_STRING: if not isinstance(py_value, str) and py_value is not None: raise TypeError(f"Expected string but got {py_value}{type(py_value)}") _gi._gvalue_set(self, py_value) elif gtype == TYPE_PARAM: self.set_param(py_value) elif gtype.is_a(TYPE_FLAGS): self.set_flags(py_value) elif gtype == TYPE_POINTER: self.set_pointer(py_value) elif gtype == TYPE_GTYPE: self.set_gtype(py_value) elif gtype == TYPE_VARIANT: self.set_variant(py_value) else: # Fall back to _gvalue_set which handles some more cases # like fundamentals for which a converter is registered try: _gi._gvalue_set(self, py_value) except TypeError: if gtype == TYPE_INVALID: raise TypeError("GObject.Value needs to be initialized first") raise def get_value(self): gtype = self.__g_type if gtype == TYPE_CHAR: return self.get_char() if gtype == TYPE_UCHAR: return self.get_uchar() if gtype == TYPE_PARAM: return self.get_param() if gtype.is_a(TYPE_ENUM): return self.get_enum() if gtype.is_a(TYPE_FLAGS): return self.get_flags() if gtype == TYPE_POINTER: return self.get_pointer() if gtype == TYPE_GTYPE: return self.get_gtype() if gtype == TYPE_VARIANT: # get_variant was missing annotations # https://gitlab.gnome.org/GNOME/glib/merge_requests/492 return self.dup_variant() try: return _gi._gvalue_get(self) except TypeError: if gtype == TYPE_INVALID: return None raise def __repr__(self): return f"" Value = override(Value) __all__.append("Value") def type_from_name(name): type_ = GObjectModule.type_from_name(name) if type_ == TYPE_INVALID: raise RuntimeError(f"unknown type name: {name}") return type_ __all__.append("type_from_name") def type_parent(type_): parent = GObjectModule.type_parent(type_) if parent == TYPE_INVALID: raise RuntimeError("no parent for type") return parent __all__.append("type_parent") def _validate_type_for_signal_method(type_): if hasattr(type_, "__gtype__"): type_ = type_.__gtype__ if not type_.is_instantiatable() and not type_.is_interface(): raise TypeError(f"type must be instantiable or an interface, got {type_}") def signal_list_ids(type_): _validate_type_for_signal_method(type_) return GObjectModule.signal_list_ids(type_) __all__.append("signal_list_ids") def signal_list_names(type_): ids = signal_list_ids(type_) return tuple(GObjectModule.signal_name(i) for i in ids) __all__.append("signal_list_names") def signal_lookup(name, type_): _validate_type_for_signal_method(type_) return GObjectModule.signal_lookup(name, type_) __all__.append("signal_lookup") SignalQuery = namedtuple( "SignalQuery", [ "signal_id", "signal_name", "itype", "signal_flags", "return_type", # n_params', "param_types", ], ) def signal_query(id_or_name, type_=None): if type_ is not None: id_or_name = signal_lookup(id_or_name, type_) res = GObjectModule.signal_query(id_or_name) assert res is not None if res.signal_id == 0: return None # Return a named tuple to allows indexing which is compatible with the # static bindings along with field like access of the gi struct. # Note however that the n_params was not returned from the static bindings # so we must skip over it. return SignalQuery( res.signal_id, res.signal_name, res.itype, res.signal_flags, res.return_type, tuple(res.param_types), ) __all__.append("signal_query") class _HandlerBlockManager: def __init__(self, obj, handler_id): self.obj = obj self.handler_id = handler_id def __enter__(self): pass def __exit__(self, exc_type, exc_value, traceback): GObjectModule.signal_handler_unblock(self.obj, self.handler_id) def signal_handler_block(obj, handler_id): """Blocks the signal handler from being invoked until handler_unblock() is called. :param GObject.Object obj: Object instance to block handlers for. :param int handler_id: Id of signal to block. :returns: A context manager which optionally can be used to automatically unblock the handler: .. code-block:: python with GObject.signal_handler_block(obj, id): pass """ GObjectModule.signal_handler_block(obj, handler_id) return _HandlerBlockManager(obj, handler_id) __all__.append("signal_handler_block") def signal_parse_name(detailed_signal, itype, force_detail_quark): """Parse a detailed signal name into (signal_id, detail). :param str detailed_signal: Signal name which can include detail. For example: "notify:prop_name" :returns: Tuple of (signal_id, detail) :raises ValueError: If the given signal is unknown. """ res, signal_id, detail = GObjectModule.signal_parse_name( detailed_signal, itype, force_detail_quark ) if res: return signal_id, detail raise ValueError(f"{itype}: unknown signal name: {detailed_signal}") __all__.append("signal_parse_name") def remove_emission_hook(obj, detailed_signal, hook_id): signal_id, _detail = signal_parse_name(detailed_signal, obj, True) GObjectModule.signal_remove_emission_hook(signal_id, hook_id) __all__.append("remove_emission_hook") # GObject accumulators with pure Python implementations # These return a tuple of (continue_emission, accumulation_result) def signal_accumulator_first_wins(ihint, return_accu, handler_return, user_data=None): # Stop emission but return the result of the last handler return (False, handler_return) __all__.append("signal_accumulator_first_wins") def signal_accumulator_true_handled(ihint, return_accu, handler_return, user_data=None): # Stop emission if the last handler returns True return (not handler_return, handler_return) __all__.append("signal_accumulator_true_handled") # Statically bound signal functions which need to clobber GI (for now) add_emission_hook = _gi.add_emission_hook signal_new = _gi.signal_new __all__ += ["add_emission_hook", "signal_new"] class _FreezeNotifyManager: def __init__(self, obj): self.obj = obj def __enter__(self): pass def __exit__(self, exc_type, exc_value, traceback): self.obj.thaw_notify() def _signalmethod(func): # Function wrapper for signal functions used as instance methods. # This is needed when the signal functions come directly from GI. # (they are not already wrapped) @functools.wraps(func) def meth(*args, **kwargs): return func(*args, **kwargs) return meth class Object(GObjectModule.Object): def _unsupported_method(self, *args, **kargs): raise RuntimeError("This method is currently unsupported.") def _unsupported_data_method(self, *args, **kargs): raise RuntimeError( "Data access methods are unsupported. Use normal Python attributes instead" ) # Generic data methods are not needed in python as it can be handled # with standard attribute access: https://bugzilla.gnome.org/show_bug.cgi?id=641944 get_data = _unsupported_data_method get_qdata = _unsupported_data_method set_data = _unsupported_data_method steal_data = _unsupported_data_method steal_qdata = _unsupported_data_method replace_data = _unsupported_data_method replace_qdata = _unsupported_data_method # The following methods as unsupported until we verify # they work as gi methods. bind_property_full = _unsupported_method compat_control = _unsupported_method interface_find_property = _unsupported_method interface_install_property = _unsupported_method interface_list_properties = _unsupported_method notify_by_pspec = _unsupported_method watch_closure = _unsupported_method # Make all reference management methods private but still accessible. def _ref(self): """Deprecated, do not explicitly reference GObjects.""" warnings.warn(self._ref.__doc__, PyGIDeprecationWarning, stacklevel=2) return GObjectModule.Object.ref(self) def _ref_sink(self): """Deprecated, do not explicitly reference GObjects.""" warnings.warn(self._ref_sink.__doc__, PyGIDeprecationWarning, stacklevel=2) return GObjectModule.Object.ref_sink(self) def _unref(self): """Deprecated, do not explicitly reference GObjects.""" warnings.warn(self._unref.__doc__, PyGIDeprecationWarning, stacklevel=2) return GObjectModule.Object.unref(self) def _force_floating(self): """Deprecated, do not explicitly float GObjects.""" warnings.warn( self._force_floating.__doc__, PyGIDeprecationWarning, stacklevel=2 ) return GObjectModule.Object.force_floating(self) ref = _unsupported_method ref_sink = _unsupported_method unref = _unsupported_method force_floating = _unsupported_method # The following methods are static APIs which need to leap frog the # gi methods until we verify the gi methods can replace them. get_property = _gi.GObject.get_property get_properties = _gi.GObject.get_properties set_property = _gi.GObject.set_property set_properties = _gi.GObject.set_properties bind_property = _gi.GObject.bind_property connect = _gi.GObject.connect connect_after = _gi.GObject.connect_after connect_object = _gi.GObject.connect_object connect_object_after = _gi.GObject.connect_object_after disconnect_by_func = _gi.GObject.disconnect_by_func handler_block_by_func = _gi.GObject.handler_block_by_func handler_unblock_by_func = _gi.GObject.handler_unblock_by_func emit = _gi.GObject.emit chain = _gi.GObject.chain weak_ref = _gi.GObject.weak_ref __copy__ = _gi.GObject.__copy__ __deepcopy__ = _gi.GObject.__deepcopy__ def freeze_notify(self): """Freezes the object's property-changed notification queue. :returns: A context manager which optionally can be used to automatically thaw notifications. This will freeze the object so that "notify" signals are blocked until the thaw_notify() method is called. .. code-block:: python with obj.freeze_notify(): pass """ super().freeze_notify() return _FreezeNotifyManager(self) def connect_data(self, detailed_signal, handler, *data, connect_flags=0): """Connect a callback to the given signal with optional user data. :param str detailed_signal: A detailed signal to connect to. :param callable handler: Callback handler to connect to the signal. :param *data: Variable data which is passed through to the signal handler. :param GObject.ConnectFlags connect_flags: Flags used for connection options. :returns: A signal id which can be used with disconnect. """ if connect_flags & GObjectModule.ConnectFlags.AFTER: connect_func = _gi.GObject.connect_after else: connect_func = _gi.GObject.connect if connect_flags & GObjectModule.ConnectFlags.SWAPPED: if len(data) != 1: raise ValueError( "Using GObject.ConnectFlags.SWAPPED requires exactly " "one argument for user data, got: %s" % [data] ) def new_handler(obj, *args): # Swap obj with the last element in args which will be the user # data passed to the connect function. args = list(args) swap = args.pop() args = [*args, obj] return handler(swap, *args) else: new_handler = handler return connect_func(self, detailed_signal, new_handler, *data) # # Aliases # handler_block = signal_handler_block handler_unblock = _signalmethod(GObjectModule.signal_handler_unblock) disconnect = _signalmethod(GObjectModule.signal_handler_disconnect) handler_disconnect = _signalmethod(GObjectModule.signal_handler_disconnect) handler_is_connected = _signalmethod(GObjectModule.signal_handler_is_connected) stop_emission_by_name = _signalmethod(GObjectModule.signal_stop_emission_by_name) # # Deprecated Methods # def stop_emission(self, detailed_signal): """Deprecated, please use stop_emission_by_name.""" warnings.warn(self.stop_emission.__doc__, PyGIDeprecationWarning, stacklevel=2) return self.stop_emission_by_name(detailed_signal) emit_stop_by_name = stop_emission Object = override(Object) GObject = Object __all__ += ["GObject", "Object"] class Binding(GObjectModule.Binding): def __call__(self): warnings.warn( "Using parentheses (binding()) to retrieve the Binding object is no " 'longer needed because the binding is returned directly from "bind_property.', PyGIDeprecationWarning, stacklevel=2, ) return self Binding = override(Binding) __all__.append("Binding") Property = propertyhelper.Property Signal = signalhelper.Signal SignalOverride = signalhelper.SignalOverride # Deprecated naming "property" available for backwards compatibility. # Keep this at the end of the file to avoid clobbering the builtin. property = Property deprecated_attr("GObject", "property", "GObject.Property") __all__ += ["Property", "Signal", "SignalOverride", "property"] @override class ParamSpec(GObjectModule.ParamSpec): @property def nick(self): return self._nick @nick.setter def nick(self, nick): self._nick = nick @property def blurb(self): return self._blurb @blurb.setter def blurb(self, blurb): self._blurb = blurb GParamSpec = ParamSpec deprecated_attr("GObject", "GParamSpec", "GObject.ParamSpec") __all__ += ["GParamSpec", "ParamSpec"] @override class ParamSpecEnum(GObjectModule.ParamSpecEnum): @property def enum_class(self): gtype = super().enum_class.g_type_class.g_type if pytype := gtype.pytype: return pytype return _gi.enum_add(None, gtype.name, gtype, None) __all__.append("ParamSpecEnum") @override class ParamSpecFlags(GObjectModule.ParamSpecFlags): @property def flags_class(self): gtype = super().flags_class.g_type_class.g_type if pytype := gtype.pytype: return pytype return _gi.flags_add(None, gtype.name, gtype, None) __all__.append("ParamSpecFlags") class Float(float): """A wrapper to force conversion to G_TYPE_FLOAT instead of G_TYPE_DOUBLE when used in GValue APIs. """ __gtype__ = TYPE_FLOAT __all__.append("Float") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/Gdk.py0000664000000000000000000003663515074673150016043 0ustar00rootroot# Copyright (C) 2009 Johan Dahlin # 2010 Simon van der Linden # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import sys import warnings from ..overrides import override, strip_boolean_result from ..module import get_introspection_module from gi import PyGIDeprecationWarning, require_version, get_option Gdk = get_introspection_module("Gdk") GDK3 = Gdk._version == "3.0" GDK4 = Gdk._version == "4.0" __all__ = [] # https://bugzilla.gnome.org/show_bug.cgi?id=673396 try: require_version("GdkX11", Gdk._version) from gi.repository import GdkX11 GdkX11 except (ValueError, ImportError): pass if GDK3: # Gdk.Color was deprecated since 3.14 and dropped in Gtk-4.0 class Color(Gdk.Color): MAX_VALUE = 65535 def __init__(self, red, green, blue): Gdk.Color.__init__(self) self.red = red self.green = green self.blue = blue def __eq__(self, other): if not isinstance(other, Gdk.Color): return False return self.equal(other) # This is required (even when __eq__ is defined) in order # for != operator to work as expected def __ne__(self, other): return not self == other def __repr__(self): return f"Gdk.Color(red={self.red}, green={self.green}, blue={self.blue})" red_float = property( fget=lambda self: self.red / float(self.MAX_VALUE), fset=lambda self, v: setattr(self, "red", int(v * self.MAX_VALUE)), ) green_float = property( fget=lambda self: self.green / float(self.MAX_VALUE), fset=lambda self, v: setattr(self, "green", int(v * self.MAX_VALUE)), ) blue_float = property( fget=lambda self: self.blue / float(self.MAX_VALUE), fset=lambda self, v: setattr(self, "blue", int(v * self.MAX_VALUE)), ) def to_floats(self): """Return (red_float, green_float, blue_float) triple.""" return (self.red_float, self.green_float, self.blue_float) @staticmethod def from_floats(red, green, blue): """Return a new Color object from red/green/blue values from 0.0 to 1.0.""" return Color( int(red * Color.MAX_VALUE), int(green * Color.MAX_VALUE), int(blue * Color.MAX_VALUE), ) Color = override(Color) __all__.append("Color") # Introduced since Gtk-3.0 class RGBA(Gdk.RGBA): def __init__(self, red=1.0, green=1.0, blue=1.0, alpha=1.0): Gdk.RGBA.__init__(self) self.red = red self.green = green self.blue = blue self.alpha = alpha def __eq__(self, other): if not isinstance(other, Gdk.RGBA): return False return self.equal(other) # This is required (even when __eq__ is defined) in order # for != operator to work as expected def __ne__(self, other): return not self == other def __repr__(self): return f"Gdk.RGBA(red={self.red:f}, green={self.green:f}, blue={self.blue:f}, alpha={self.alpha:f})" def __iter__(self): """Iterator which allows easy conversion to tuple and list types.""" yield self.red yield self.green yield self.blue yield self.alpha if GDK3: def to_color(self): """Converts this RGBA into a Color instance which excludes alpha.""" return Color( int(self.red * Color.MAX_VALUE), int(self.green * Color.MAX_VALUE), int(self.blue * Color.MAX_VALUE), ) @classmethod def from_color(cls, color): """Returns a new RGBA instance given a Color instance.""" return cls(color.red_float, color.green_float, color.blue_float) RGBA = override(RGBA) __all__.append("RGBA") if GDK3: # Newer GTK/gobject-introspection (3.17.x) include GdkRectangle in the # typelib. See https://bugzilla.gnome.org/show_bug.cgi?id=748832 and # https://bugzilla.gnome.org/show_bug.cgi?id=748833 if not hasattr(Gdk, "Rectangle"): from gi.repository import cairo as _cairo Rectangle = _cairo.RectangleInt __all__.append("Rectangle") else: # https://bugzilla.gnome.org/show_bug.cgi?id=756364 # These methods used to be functions, keep aliases for backwards compat rectangle_intersect = Gdk.Rectangle.intersect rectangle_union = Gdk.Rectangle.union __all__.append("rectangle_intersect") __all__.append("rectangle_union") if GDK3: class Window(Gdk.Window): def __new__(cls, parent, attributes, attributes_mask): # Gdk.Window had to be made abstract, # this override allows using the standard constructor return Gdk.Window.new(parent, attributes, attributes_mask) def __init__(self, parent, attributes, attributes_mask): pass def cairo_create(self): return Gdk.cairo_create(self) Window = override(Window) __all__.append("Window") if GDK3: Gdk.EventType._2BUTTON_PRESS = getattr(Gdk.EventType, "2BUTTON_PRESS") Gdk.EventType._3BUTTON_PRESS = getattr(Gdk.EventType, "3BUTTON_PRESS") class Event(Gdk.Event): _UNION_MEMBERS = { Gdk.EventType.DELETE: "any", Gdk.EventType.DESTROY: "any", Gdk.EventType.MOTION_NOTIFY: "motion", Gdk.EventType.BUTTON_PRESS: "button", Gdk.EventType.BUTTON_RELEASE: "button", Gdk.EventType.KEY_PRESS: "key", Gdk.EventType.KEY_RELEASE: "key", Gdk.EventType.ENTER_NOTIFY: "crossing", Gdk.EventType.LEAVE_NOTIFY: "crossing", Gdk.EventType.FOCUS_CHANGE: "focus_change", Gdk.EventType.CONFIGURE: "configure", Gdk.EventType.PROXIMITY_IN: "proximity", Gdk.EventType.PROXIMITY_OUT: "proximity", Gdk.EventType.DRAG_ENTER: "dnd", Gdk.EventType.DRAG_LEAVE: "dnd", Gdk.EventType.DRAG_MOTION: "dnd", Gdk.EventType.DROP_START: "dnd", Gdk.EventType._2BUTTON_PRESS: "button", Gdk.EventType._3BUTTON_PRESS: "button", Gdk.EventType.PROPERTY_NOTIFY: "property", Gdk.EventType.SELECTION_CLEAR: "selection", Gdk.EventType.SELECTION_REQUEST: "selection", Gdk.EventType.SELECTION_NOTIFY: "selection", Gdk.EventType.DRAG_STATUS: "dnd", Gdk.EventType.DROP_FINISHED: "dnd", Gdk.EventType.CLIENT_EVENT: "client", Gdk.EventType.VISIBILITY_NOTIFY: "visibility", Gdk.EventType.SCROLL: "scroll", Gdk.EventType.EXPOSE: "expose", Gdk.EventType.MAP: "any", Gdk.EventType.UNMAP: "any", } if hasattr(Gdk.EventType, "TOUCH_BEGIN"): _UNION_MEMBERS.update( { Gdk.EventType.TOUCH_BEGIN: "touch", Gdk.EventType.TOUCH_UPDATE: "touch", Gdk.EventType.TOUCH_END: "touch", Gdk.EventType.TOUCH_CANCEL: "touch", } ) def __getattr__(self, name): real_event = getattr(self, "_UNION_MEMBERS").get(self.type) if real_event: return getattr(getattr(self, real_event), name) raise AttributeError( f"'{self.__class__.__name__}' object has no attribute '{name}'" ) def __setattr__(self, name, value): real_event = getattr(self, "_UNION_MEMBERS").get(self.type) if real_event: setattr(getattr(self, real_event), name, value) else: Gdk.Event.__setattr__(self, name, value) def __repr__(self): base_repr = Gdk.Event.__repr__(self).strip("><") return f"<{base_repr} type={self.type!r}>" Event = override(Event) __all__.append("Event") # manually bind GdkEvent members to GdkEvent modname = globals()["__name__"] module = sys.modules[modname] # right now we can't get the type_info from the # field info so manually list the class names event_member_classes = [ "EventAny", "EventExpose", "EventMotion", "EventButton", "EventScroll", "EventKey", "EventCrossing", "EventFocus", "EventConfigure", "EventProximity", "EventDND", "EventSetting", "EventGrabBroken", "EventVisibility", "EventProperty", "EventSelection", "EventOwnerChange", "EventWindowState", "EventVisibility", ] if hasattr(Gdk, "EventTouch"): event_member_classes.append("EventTouch") # whitelist all methods that have a success return we want to mask gsuccess_mask_funcs = ["get_state", "get_axis", "get_coords", "get_root_coords"] for event_class in event_member_classes: override_class = type(event_class, (getattr(Gdk, event_class),), {}) # add the event methods for method_info in Gdk.Event.__info__.get_methods(): name = method_info.get_name() event_method = getattr(Gdk.Event, name) # use the _gsuccess_mask decorator if this method is whitelisted if name in gsuccess_mask_funcs: event_method = strip_boolean_result(event_method) setattr(override_class, name, event_method) setattr(module, event_class, override_class) __all__.append(event_class) # end GdkEvent overrides class DragContext(Gdk.DragContext): def finish(self, success, del_, time): Gtk = get_introspection_module("Gtk") Gtk.drag_finish(self, success, del_, time) DragContext = override(DragContext) __all__.append("DragContext") class Cursor(Gdk.Cursor): def __new__(cls, *args, **kwds): arg_len = len(args) kwd_len = len(kwds) total_len = arg_len + kwd_len if total_len == 1: # Since g_object_newv (super.__new__) does not seem valid for # direct use with GdkCursor, we must assume usage of at least # one of the C constructors to be valid. return cls.new(*args, **kwds) if total_len == 2: warnings.warn( 'Calling "Gdk.Cursor(display, cursor_type)" has been deprecated. ' "Please use Gdk.Cursor.new_for_display(display, cursor_type). " "See: https://pygobject.gnome.org/devguide/initializer_deprecations.html", PyGIDeprecationWarning, ) return cls.new_for_display(*args, **kwds) if total_len == 4: warnings.warn( 'Calling "Gdk.Cursor(display, pixbuf, x, y)" has been deprecated. ' "Please use Gdk.Cursor.new_from_pixbuf(display, pixbuf, x, y). " "See: https://pygobject.gnome.org/devguide/initializer_deprecations.html", PyGIDeprecationWarning, ) return cls.new_from_pixbuf(*args, **kwds) raise ValueError("Wrong number of parameters") Cursor = override(Cursor) __all__.append("Cursor") # Gdk.Color was deprecated since 3.14 and dropped in Gtk-4.0 color_parse = strip_boolean_result(Gdk.color_parse) __all__.append("color_parse") # Note, we cannot override the entire class as Gdk.Atom has no gtype, so just # hack some individual methods def _gdk_atom_str(atom): n = atom.name() if n: return n # fall back to atom index return f"Gdk.Atom<{hash(atom):d}>" def _gdk_atom_repr(atom): n = atom.name() if n: return f'Gdk.Atom.intern("{n}", False)' # fall back to atom index return f"" Gdk.Atom.__str__ = _gdk_atom_str Gdk.Atom.__repr__ = _gdk_atom_repr if GDK4: from gi.repository import Gio class FileList(Gdk.FileList): if hasattr(Gdk.FileList, "new_from_list"): def __new__(cls, files): files_list = [] if isinstance(files, (tuple, list)): for f in files: if isinstance(f, Gio.File): files_list.append(f) else: raise TypeError( "Constructor requires a list or tuple of Gio.File instances" ) else: raise TypeError( "Constructor requires a list or tuple of Gio.File instances" ) return Gdk.FileList.new_from_list(files) def __iter__(self): return iter(self.get_files()) def __len__(self): return len(self.get_files()) def __getitem__(self, index): return self.get_files()[index] FileList = override(FileList) __all__.append("FileList") # constants if GDK3: SELECTION_PRIMARY = Gdk.atom_intern("PRIMARY", True) __all__.append("SELECTION_PRIMARY") SELECTION_SECONDARY = Gdk.atom_intern("SECONDARY", True) __all__.append("SELECTION_SECONDARY") SELECTION_CLIPBOARD = Gdk.atom_intern("CLIPBOARD", True) __all__.append("SELECTION_CLIPBOARD") TARGET_BITMAP = Gdk.atom_intern("BITMAP", True) __all__.append("TARGET_BITMAP") TARGET_COLORMAP = Gdk.atom_intern("COLORMAP", True) __all__.append("TARGET_COLORMAP") TARGET_DRAWABLE = Gdk.atom_intern("DRAWABLE", True) __all__.append("TARGET_DRAWABLE") TARGET_PIXMAP = Gdk.atom_intern("PIXMAP", True) __all__.append("TARGET_PIXMAP") TARGET_STRING = Gdk.atom_intern("STRING", True) __all__.append("TARGET_STRING") SELECTION_TYPE_ATOM = Gdk.atom_intern("ATOM", True) __all__.append("SELECTION_TYPE_ATOM") SELECTION_TYPE_BITMAP = Gdk.atom_intern("BITMAP", True) __all__.append("SELECTION_TYPE_BITMAP") SELECTION_TYPE_COLORMAP = Gdk.atom_intern("COLORMAP", True) __all__.append("SELECTION_TYPE_COLORMAP") SELECTION_TYPE_DRAWABLE = Gdk.atom_intern("DRAWABLE", True) __all__.append("SELECTION_TYPE_DRAWABLE") SELECTION_TYPE_INTEGER = Gdk.atom_intern("INTEGER", True) __all__.append("SELECTION_TYPE_INTEGER") SELECTION_TYPE_PIXMAP = Gdk.atom_intern("PIXMAP", True) __all__.append("SELECTION_TYPE_PIXMAP") SELECTION_TYPE_WINDOW = Gdk.atom_intern("WINDOW", True) __all__.append("SELECTION_TYPE_WINDOW") SELECTION_TYPE_STRING = Gdk.atom_intern("STRING", True) __all__.append("SELECTION_TYPE_STRING") if GDK3 and get_option("legacy_autoinit"): import sys initialized, argv = Gdk.init_check(sys.argv) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/GdkPixbuf.py0000664000000000000000000000340515074673150017206 0ustar00rootroot# Copyright 2018 Christoph Reiter # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import warnings from gi import PyGIDeprecationWarning from gi.repository import GLib from ..overrides import override from ..module import get_introspection_module GdkPixbuf = get_introspection_module("GdkPixbuf") __all__ = [] @override class Pixbuf(GdkPixbuf.Pixbuf): @classmethod def new_from_data( cls, data, colorspace, has_alpha, bits_per_sample, width, height, rowstride, destroy_fn=None, *destroy_fn_data, ): if destroy_fn is not None: w = PyGIDeprecationWarning("destroy_fn argument deprecated") warnings.warn(w, stacklevel=2) if destroy_fn_data: w = PyGIDeprecationWarning("destroy_fn_data argument deprecated") warnings.warn(w, stacklevel=2) data = GLib.Bytes.new(data) return cls.new_from_bytes( data, colorspace, has_alpha, bits_per_sample, width, height, rowstride ) __all__.append("Pixbuf") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/Gio.py0000664000000000000000000005324315074673150016046 0ustar00rootroot# Copyright (C) 2010 Ignacio Casal Quinteiro # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import asyncio import warnings from contextlib import suppress from .._ossighelper import register_sigint_fallback, get_event_loop from ..overrides import ( override, deprecated_attr, deprecated_init, wrap_list_store_equal_func, wrap_list_store_sort_func, ) from .._gi import CallableInfo from ..module import get_introspection_module from gi import PyGIWarning from gi.repository import GLib import sys Gio = get_introspection_module("Gio") __all__ = [] class ActionMap(Gio.ActionMap): def add_action_entries(self, entries, user_data=None): """The ``add_action_entries()`` method is a convenience function for creating multiple :class:`~gi.repository.Gio.SimpleAction` instances and adding them to a :class:`~gi.repository.Gio.ActionMap`. Each action is constructed as per one entry. :param list entries: List of entry tuples for :meth:`add_action` method. The entry tuple can vary in size with the following information: * The name of the action. Must be specified. * The callback to connect to the "activate" signal of the action. Since GLib 2.40, this can be ``None`` for stateful actions, in which case the default handler is used. For boolean-stated actions with no parameter, this is a toggle. For other state types (and parameter type equal to the state type) this will be a function that just calls change_state (which you should provide). * The type of the parameter that must be passed to the activate function for this action, given as a single :class:`~gi.repository.GLib.Variant` type string (or ``None`` for no parameter) * The initial state for this action, given in GLib.Variant text format. The state is parsed with no extra type information, so type tags must be added to the string if they are necessary. Stateless actions should give ``None`` here. * The callback to connect to the "change-state" signal of the action. All stateful actions should provide a handler here; stateless actions should not. :param user_data: The user data for signal connections, or ``None`` """ try: iter(entries) except TypeError: raise TypeError("entries must be iterable") def _process_action( name, activate=None, parameter_type=None, state=None, change_state=None ): if parameter_type: if not GLib.VariantType.string_is_valid(parameter_type): msg = f"The type string '{parameter_type}' given as the parameter type for action '{name}' is not a valid GVariant type string. " raise TypeError(msg) variant_parameter = GLib.VariantType.new(parameter_type) else: variant_parameter = None if state is not None: # stateful action variant_state = GLib.Variant.parse(None, state, None, None) action = Gio.SimpleAction.new_stateful( name, variant_parameter, variant_state ) if change_state is not None: action.connect("change-state", change_state, user_data) else: # stateless action if change_state is not None: msg = f"Stateless action '{name}' should give None for 'change_state', not '{change_state}'." raise ValueError(msg) action = Gio.SimpleAction(name=name, parameter_type=variant_parameter) if activate is not None: action.connect("activate", activate, user_data) self.add_action(action) for entry in entries: # using inner function above since entries can leave out optional arguments _process_action(*entry) ActionMap = override(ActionMap) __all__.append("ActionMap") class Application(Gio.Application): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._asyncio_tasks = set() def run(self, *args, **kwargs): with ( register_sigint_fallback(self.quit), get_event_loop(GLib.MainContext.default()).running(self.quit), ): return Gio.Application.run(self, *args, **kwargs) def create_asyncio_task(self, coro): """Safely create an asyncio task. The application will not quit until the task completes. For potentially longer running tasks, you should add cancellation logic to abort a task when it is not needed anymore (e.g. cancelling it from the Gtk.Window.do_unmap event). Note that python will only log a raised exception if the Task is destroyed without the result having been collected. However, this does also not happen when the task is cancelled. As such, be careful to not cancel tasks that are already finished. You can deal with this by either only storing a weak reference to the Task, by explicitly collecting the result, or by only cancelling it if it is not done already. """ # First create the task (in case it raises an exception) task = asyncio.create_task(coro) self.hold() # Store a reference to the task so that it cannot be garbage collected self._asyncio_tasks.add(task) def done_cb(task): nonlocal self self._asyncio_tasks.discard(task) self.release() task.add_done_callback(done_cb) return task Application = override(Application) __all__.append("Application") def _warn_init(cls, instead=None): def new_init(self, *args, **kwargs): super(cls, self).__init__(*args, **kwargs) name = cls.__module__.rsplit(".", 1)[-1] + "." + cls.__name__ if instead: warnings.warn( (f"{name} shouldn't be instantiated directly, use {instead} instead."), PyGIWarning, stacklevel=2, ) else: warnings.warn( f"{name} shouldn't be instantiated directly.", PyGIWarning, stacklevel=2, ) return new_init @override class VolumeMonitor(Gio.VolumeMonitor): # https://bugzilla.gnome.org/show_bug.cgi?id=744690 __init__ = _warn_init(Gio.VolumeMonitor, "Gio.VolumeMonitor.get()") __all__.append("VolumeMonitor") @override class DBusAnnotationInfo(Gio.DBusAnnotationInfo): __init__ = _warn_init(Gio.DBusAnnotationInfo) __all__.append("DBusAnnotationInfo") @override class DBusArgInfo(Gio.DBusArgInfo): __init__ = _warn_init(Gio.DBusArgInfo) __all__.append("DBusArgInfo") @override class DBusMethodInfo(Gio.DBusMethodInfo): __init__ = _warn_init(Gio.DBusMethodInfo) __all__.append("DBusMethodInfo") @override class DBusSignalInfo(Gio.DBusSignalInfo): __init__ = _warn_init(Gio.DBusSignalInfo) __all__.append("DBusSignalInfo") @override class DBusInterfaceInfo(Gio.DBusInterfaceInfo): __init__ = _warn_init(Gio.DBusInterfaceInfo) __all__.append("DBusInterfaceInfo") @override class DBusNodeInfo(Gio.DBusNodeInfo): __init__ = _warn_init(Gio.DBusNodeInfo) __all__.append("DBusNodeInfo") class FileEnumerator(Gio.FileEnumerator): def __iter__(self): return self def __next__(self): file_info = self.next_file(None) if file_info is not None: return file_info raise StopIteration FileEnumerator = override(FileEnumerator) __all__.append("FileEnumerator") class MenuItem(Gio.MenuItem): def set_attribute(self, attributes): for name, format_string, value in attributes: self.set_attribute_value(name, GLib.Variant(format_string, value)) MenuItem = override(MenuItem) __all__.append("MenuItem") class Settings(Gio.Settings): """Provide dictionary-like access to GLib.Settings.""" __init__ = deprecated_init( Gio.Settings.__init__, arg_names=("schema", "path", "backend") ) def __contains__(self, key): return key in self.list_keys() def __len__(self): return len(self.list_keys()) def __iter__(self): yield from self.list_keys() def __bool__(self): # for "if mysettings" we don't want a dictionary-like test here, just # if the object isn't None return True def __getitem__(self, key): # get_value() aborts the program on an unknown key if key not in self: raise KeyError(f"unknown key: {key!r}") return self.get_value(key).unpack() def __setitem__(self, key, value): # set_value() aborts the program on an unknown key if key not in self: raise KeyError(f"unknown key: {key!r}") # determine type string of this key range = self.get_range(key) type_ = range.get_child_value(0).get_string() v = range.get_child_value(1) if type_ == "type": # v is boxed empty array, type of its elements is the allowed value type type_str = v.get_child_value(0).get_type_string() assert type_str.startswith("a") type_str = type_str[1:] elif type_ == "enum": # v is an array with the allowed values assert v.get_child_value(0).get_type_string().startswith("a") type_str = v.get_child_value(0).get_child_value(0).get_type_string() allowed = v.unpack() if value not in allowed: raise ValueError(f"value {value} is not an allowed enum ({allowed})") elif type_ == "range": tuple_ = v.get_child_value(0) type_str = tuple_.get_child_value(0).get_type_string() min_, max_ = tuple_.unpack() if value < min_ or value > max_: raise ValueError(f"value {value} not in range ({min_} - {max_})") else: raise NotImplementedError( "Cannot handle allowed type range class " + str(type_) ) self.set_value(key, GLib.Variant(type_str, value)) def keys(self): return self.list_keys() Settings = override(Settings) __all__.append("Settings") class _DBusProxyMethodCall: """Helper class to implement DBusProxy method calls.""" def __init__(self, dbus_proxy, method_name): self.dbus_proxy = dbus_proxy self.method_name = method_name def __async_result_handler(self, obj, result, user_data): (result_callback, error_callback, real_user_data) = user_data try: ret = obj.call_finish(result) except Exception: _etype, e = sys.exc_info()[:2] # return exception as value if error_callback: error_callback(obj, e, real_user_data) else: result_callback(obj, e, real_user_data) return result_callback(obj, self._unpack_result(ret), real_user_data) def __call__( self, *args, result_handler=None, error_handler=None, user_data=None, flags=0, timeout=-1, ): # the first positional argument is the signature, unless we are calling # a method without arguments; then signature is implied to be '()'. if args: signature = args[0] args = args[1:] if not isinstance(signature, str): raise TypeError( f"first argument must be the method signature string: {signature!r}" ) else: signature = "()" arg_variant = GLib.Variant(signature, tuple(args)) if result_handler is not None: # asynchronous call user_data = (result_handler, error_handler, user_data) self.dbus_proxy.call( self.method_name, arg_variant, flags, timeout, None, self.__async_result_handler, user_data, ) else: # synchronous call result = self.dbus_proxy.call_sync( self.method_name, arg_variant, flags, timeout, None ) return self._unpack_result(result) return None @classmethod def _unpack_result(klass, result): """Convert a D-BUS return variant into an appropriate return value.""" result = result.unpack() # to be compatible with standard Python behaviour, unbox # single-element tuples and return None for empty result tuples if len(result) == 1: result = result[0] elif len(result) == 0: result = None return result class DBusProxy(Gio.DBusProxy): """Provide comfortable and pythonic method calls. This marshalls the method arguments into a GVariant, invokes the call_sync() method on the DBusProxy object, and unmarshalls the result GVariant back into a Python tuple. The first argument always needs to be the D-Bus signature tuple of the method call. Example: proxy = Gio.DBusProxy.new_sync(...) result = proxy.MyMethod('(is)', 42, 'hello') The exception are methods which take no arguments, like proxy.MyMethod('()'). For these you can omit the signature and just write proxy.MyMethod(). Optional keyword arguments: - timeout: timeout for the call in milliseconds (default to D-Bus timeout) - flags: Combination of Gio.DBusCallFlags.* - result_handler: Do an asynchronous method call and invoke result_handler(proxy_object, result, user_data) when it finishes. - error_handler: If the asynchronous call raises an exception, error_handler(proxy_object, exception, user_data) is called when it finishes. If error_handler is not given, result_handler is called with the exception object as result instead. - user_data: Optional user data to pass to result_handler for asynchronous calls. Example for asynchronous calls: def mymethod_done(proxy, result, user_data): if isinstance(result, Exception): # handle error else: # do something with result proxy.MyMethod('(is)', 42, 'hello', result_handler=mymethod_done, user_data='data') """ def __getattr__(self, name): if name.startswith("do_"): return self[name] return _DBusProxyMethodCall(self, name) DBusProxy = override(DBusProxy) __all__.append("DBusProxy") class ListModel(Gio.ListModel): def __getitem__(self, key): if isinstance(key, slice): return [self.get_item(i) for i in range(*key.indices(len(self)))] if isinstance(key, int): if key < 0: key += len(self) if key < 0: raise IndexError ret = self.get_item(key) if ret is None: raise IndexError return ret raise TypeError def __contains__(self, item): pytype = self.get_item_type().pytype if not isinstance(item, pytype): raise TypeError(f"Expected type {pytype.__module__}.{pytype.__name__}") return any(i == item for i in self) def __len__(self): return self.get_n_items() def __iter__(self): for i in range(len(self)): yield self.get_item(i) ListModel = override(ListModel) __all__.append("ListModel") class ListStore(Gio.ListStore): def sort(self, compare_func, *user_data): compare_func = wrap_list_store_sort_func(compare_func) return super().sort(compare_func, *user_data) def insert_sorted(self, item, compare_func, *user_data): compare_func = wrap_list_store_sort_func(compare_func) return super().insert_sorted(item, compare_func, *user_data) def __delitem__(self, key): if isinstance(key, slice): start, stop, step = key.indices(len(self)) if step == 1: self.splice(start, max(stop - start, 0), []) elif step == -1: self.splice(stop + 1, max(start - stop, 0), []) else: for i in sorted(range(start, stop, step), reverse=True): self.remove(i) elif isinstance(key, int): if key < 0: key += len(self) if key < 0 or key >= len(self): raise IndexError self.remove(key) else: raise TypeError def __setitem__(self, key, value): if isinstance(key, slice): pytype = self.get_item_type().pytype valuelist = [] for v in value: if not isinstance(v, pytype): raise TypeError( f"Expected type {pytype.__module__}.{pytype.__name__}" ) valuelist.append(v) start, stop, step = key.indices(len(self)) if step == 1: self.splice(start, max(stop - start, 0), valuelist) else: indices = list(range(start, stop, step)) if len(indices) != len(valuelist): raise ValueError if step == -1: self.splice(stop + 1, max(start - stop, 0), valuelist[::-1]) else: for i, v in zip(indices, valuelist): self.splice(i, 1, [v]) elif isinstance(key, int): if key < 0: key += len(self) if key < 0 or key >= len(self): raise IndexError pytype = self.get_item_type().pytype if not isinstance(value, pytype): raise TypeError(f"Expected type {pytype.__module__}.{pytype.__name__}") self.splice(key, 1, [value]) else: raise TypeError def find_with_equal_func(self, item, equal_func, *user_data): # find_with_equal_func() is not suited for language bindings, # see: https://gitlab.gnome.org/GNOME/glib/-/issues/2447. # Use find_with_equal_func_full() instead. equal_func = wrap_list_store_equal_func(equal_func) return self.find_with_equal_func_full(item, equal_func, *user_data) ListStore = override(ListStore) __all__.append("ListStore") class DataInputStream(Gio.DataInputStream): def __iter__(self): return self def __next__(self): line = self.read_line_utf8(None)[0] if line is not None: return line raise StopIteration DataInputStream = override(DataInputStream) __all__.append("DataInputStream") class File(Gio.File): def __fspath__(self): path = self.peek_path() # A file isn't guaranteed to have a path associated and returning # `None` here will result in a `TypeError` trying to subscribe to it. if path is None or path == "": raise TypeError("File has no associated path.") return path File = override(File) __all__.append("File") GioPlatform = None with suppress(ImportError): from gi.repository import GioUnix as GioPlatform if not GioPlatform: with suppress(ImportError): from gi.repository import GioWin32 as GioPlatform if GioPlatform: # Add support for using platform-specific Gio symbols. gio_globals = globals() platform_name = f"{GioPlatform._namespace[len(Gio._namespace) :]}" platform_name_lower = platform_name.lower() for attr in dir(GioPlatform): if attr.startswith("_"): continue original_attr = getattr(GioPlatform, attr) wrapper_attr = attr if isinstance( original_attr, CallableInfo ) and original_attr.get_symbol().startswith(f"g_{platform_name_lower}_"): wrapper_attr = f"{platform_name_lower}_{attr}" else: try: gtype = getattr(original_attr, "__gtype__") if gtype.name.startswith(f"G{platform_name}"): wrapper_attr = f"{platform_name}{attr}" except AttributeError: pass if wrapper_attr == attr and hasattr(Gio, wrapper_attr): try: name = original_attr.__name__[0] except (AttributeError, IndexError): name = original_attr # Fallback if we don't have the original name. if name.islower(): wrapper_attr = f"{platform_name_lower}_{attr}" elif "_" in name: wrapper_attr = f"{platform_name.upper()}_{attr}" elif name: wrapper_attr = f"{platform_name}{attr}" if ( wrapper_attr in __all__ or wrapper_attr in gio_globals or hasattr(Gio, wrapper_attr) ): continue gio_globals[wrapper_attr] = original_attr deprecated_attr( Gio._namespace, wrapper_attr, f"{GioPlatform._namespace}.{attr}" ) __all__.append(wrapper_attr) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/GioUnix.py0000664000000000000000000001223215074673150016703 0ustar00rootroot# Copyright 2025 Simon McVittie # SPDX-License-Identifier: LGPL-2.1-or-later from ..module import get_introspection_module from ..overrides import override from gi.repository import GLib GioUnix = get_introspection_module("GioUnix") __all__ = [] if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) < (2, 86): # In older versions of GLib there was some confusion between the # platform-specific classes in GioUnix and their equivalents in Gio, # resulting in functions like g_desktop_app_info_get_action_name() # being assumed to be a global function that happened to take a # Gio.DesktopAppInfo first parameter, instead of being a method on a # GioUnix.DesktopAppInfo instance. There are not very many classes and # methods in GioUnix, so we can wrap them and provide the intended API. @override class DesktopAppInfo(GioUnix.DesktopAppInfo): def get_action_name(self, action_name): return GioUnix.DesktopAppInfo.get_action_name(self, action_name) def get_boolean(self, key): return GioUnix.DesktopAppInfo.get_boolean(self, key) def get_categories(self): return GioUnix.DesktopAppInfo.get_categories(self) def get_filename(self): return GioUnix.DesktopAppInfo.get_filename(self) def get_generic_name(self): return GioUnix.DesktopAppInfo.get_generic_name(self) def get_is_hidden(self): return GioUnix.DesktopAppInfo.get_is_hidden(self) def get_keywords(self): return GioUnix.DesktopAppInfo.get_keywords(self) def get_locale_string(self, key): return GioUnix.DesktopAppInfo.get_locale_string(self, key) def get_nodisplay(self): return GioUnix.DesktopAppInfo.get_nodisplay(self) def get_show_in(self, desktop_env=None): return GioUnix.DesktopAppInfo.get_show_in(self, desktop_env) def get_startup_wm_class(self): return GioUnix.DesktopAppInfo.get_startup_wm_class(self) def get_string(self, key): return GioUnix.DesktopAppInfo.get_string(self, key) def get_string_list(self, key): return GioUnix.DesktopAppInfo.get_string_list(self, key) def has_key(self, key): return GioUnix.DesktopAppInfo.has_key(self, key) def launch_action(self, action_name, launch_context=None): GioUnix.DesktopAppInfo.launch_action( self, action_name, launch_context, ) def launch_uris_as_manager( self, uris, launch_context, spawn_flags, user_setup=None, user_setup_data=None, pid_callback=None, pid_callback_data=None, ): return GioUnix.DesktopAppInfo.launch_uris_as_manager( self, uris, launch_context, spawn_flags, user_setup, user_setup_data, pid_callback, pid_callback_data, ) def launch_uris_as_manager_with_fds( self, uris, launch_context, spawn_flags, user_setup, user_setup_data, pid_callback, pid_callback_data, stdin_fd, stdout_fd, stderr_fd, ): return GioUnix.DesktopAppInfo.launch_uris_as_manager_with_fds( self, uris, launch_context, spawn_flags, user_setup, user_setup_data, pid_callback, pid_callback_data, stdin_fd, stdout_fd, stderr_fd, ) def list_actions(self): return GioUnix.DesktopAppInfo.list_actions(self) __all__.append("DesktopAppInfo") @override class FDMessage(GioUnix.FDMessage): def append_fd(self, fd): return GioUnix.FDMessage.append_fd(self, fd) def get_fd_list(self): return GioUnix.FDMessage.get_fd_list(self) def steal_fds(self): return GioUnix.FDMessage.steal_fds(self) __all__.append("FDMessage") @override class InputStream(GioUnix.InputStream): def get_close_fd(self): return GioUnix.InputStream.get_close_fd(self) def get_fd(self): return GioUnix.InputStream.get_fd(self) def set_close_fd(self, close_fd): GioUnix.InputStream.set_close_fd(self, close_fd) __all__.append("InputStream") @override class MountMonitor(GioUnix.MountMonitor): def set_rate_limit(self, limit_msec): GioUnix.MountMonitor.set_rate_limit(limit_msec) __all__.append("MountMonitor") @override class OutputStream(GioUnix.OutputStream): def get_close_fd(self): return GioUnix.OutputStream.get_close_fd(self) def get_fd(self): return GioUnix.OutputStream.get_fd(self) def set_close_fd(self, close_fd): GioUnix.OutputStream.set_close_fd(self, close_fd) __all__.append("OutputStream") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/Gtk.py0000664000000000000000000017245415074673150016063 0ustar00rootroot# Copyright (C) 2009 Johan Dahlin # 2010 Simon van der Linden # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import sys import warnings from gi.repository import GObject, GLib from .._ossighelper import register_sigint_fallback, get_event_loop from .._gtktemplate import Template, _extract_handler_and_args from ..overrides import ( override, strip_boolean_result, deprecated_init, wrap_list_store_sort_func, ) from ..module import get_introspection_module from gi import PyGIDeprecationWarning, get_option Gtk = get_introspection_module("Gtk") GTK3 = Gtk._version == "3.0" GTK4 = Gtk._version == "4.0" __all__ = [] Template = Template __all__.append("Template") # Exposed for unit-testing. _extract_handler_and_args = _extract_handler_and_args __all__.append("_extract_handler_and_args") class PyGTKDeprecationWarning(PyGIDeprecationWarning): pass __all__.append("PyGTKDeprecationWarning") if GTK3: def _construct_target_list(targets): """Create a list of TargetEntry items from a list of tuples in the form (target, flags, info). The list can also contain existing TargetEntry items in which case the existing entry is re-used in the return list. """ target_entries = [] for entry in targets: if not isinstance(entry, Gtk.TargetEntry): entry = Gtk.TargetEntry.new(*entry) target_entries.append(entry) return target_entries __all__.append("_construct_target_list") def _builder_connect_callback( builder, gobj, signal_name, handler_name, connect_obj, flags, obj_or_map ): handler, args = _extract_handler_and_args(obj_or_map, handler_name) after = flags & GObject.ConnectFlags.AFTER if connect_obj is not None: if after: gobj.connect_object_after(signal_name, handler, connect_obj, *args) else: gobj.connect_object(signal_name, handler, connect_obj, *args) else: if after: gobj.connect_after(signal_name, handler, *args) else: gobj.connect(signal_name, handler, *args) class _FreezeNotifyManager: def __init__(self, obj): self.obj = obj def __enter__(self): pass def __exit__(self, exc_type, exc_value, traceback): self.obj.thaw_child_notify() class Widget(Gtk.Widget): translate_coordinates = strip_boolean_result(Gtk.Widget.translate_coordinates) if GTK4: def __contains__(self, child): return child in list(self) def __iter__(self): child = self.get_first_child() while child: yield child child = child.get_next_sibling() if GTK3: def freeze_child_notify(self): super().freeze_child_notify() return _FreezeNotifyManager(self) if GTK3: def drag_dest_set_target_list(self, target_list): if (target_list is not None) and ( not isinstance(target_list, Gtk.TargetList) ): target_list = Gtk.TargetList.new(_construct_target_list(target_list)) super().drag_dest_set_target_list(target_list) if GTK3: def drag_source_set_target_list(self, target_list): if (target_list is not None) and ( not isinstance(target_list, Gtk.TargetList) ): target_list = Gtk.TargetList.new(_construct_target_list(target_list)) super().drag_source_set_target_list(target_list) if GTK3: def style_get_property(self, property_name, value=None): if value is None: prop = self.find_style_property(property_name) if prop is None: raise ValueError( f'Class "{self}" does not contain style property "{property_name}"' ) value = GObject.Value(prop.value_type) Gtk.Widget.style_get_property(self, property_name, value) return value.get_value() Widget = override(Widget) __all__.append("Widget") if GTK3: class Container(Gtk.Container, Widget): def __len__(self): return len(self.get_children()) def __contains__(self, child): return child in self.get_children() def __iter__(self): return iter(self.get_children()) def __bool__(self): return True def child_get_property(self, child, property_name, value=None): if value is None: prop = self.find_child_property(property_name) if prop is None: raise ValueError( f'Class "{self}" does not contain child property "{property_name}"' ) value = GObject.Value(prop.value_type) Gtk.Container.child_get_property(self, child, property_name, value) return value.get_value() def child_get(self, child, *prop_names): """Returns a list of child property values for the given names.""" return [self.child_get_property(child, name) for name in prop_names] def child_set(self, child, **kwargs): """Set a child properties on the given child to key/value pairs.""" for name, value in kwargs.items(): name = name.replace("_", "-") self.child_set_property(child, name, value) get_focus_chain = strip_boolean_result(Gtk.Container.get_focus_chain) Container = override(Container) __all__.append("Container") else: Container = object class Editable(Gtk.Editable): def insert_text(self, text, position): return super().insert_text(text, -1, position) get_selection_bounds = strip_boolean_result( Gtk.Editable.get_selection_bounds, fail_ret=() ) Editable = override(Editable) __all__.append("Editable") if GTK3: class Action(Gtk.Action): __init__ = deprecated_init( Gtk.Action.__init__, arg_names=("name", "label", "tooltip", "stock_id"), category=PyGTKDeprecationWarning, ) Action = override(Action) __all__.append("Action") class RadioAction(Gtk.RadioAction): __init__ = deprecated_init( Gtk.RadioAction.__init__, arg_names=("name", "label", "tooltip", "stock_id", "value"), category=PyGTKDeprecationWarning, ) RadioAction = override(RadioAction) __all__.append("RadioAction") class ActionGroup(Gtk.ActionGroup): __init__ = deprecated_init( Gtk.ActionGroup.__init__, arg_names=("name",), category=PyGTKDeprecationWarning, ) def add_actions(self, entries, user_data=None): """The add_actions() method is a convenience method that creates a number of gtk.Action objects based on the information in the list of action entry tuples contained in entries and adds them to the action group. The entry tuples can vary in size from one to six items with the following information: * The name of the action. Must be specified. * The stock id for the action. Optional with a default value of None if a label is specified. * The label for the action. This field should typically be marked for translation, see the set_translation_domain() method. Optional with a default value of None if a stock id is specified. * The accelerator for the action, in the format understood by the gtk.accelerator_parse() function. Optional with a default value of None. * The tooltip for the action. This field should typically be marked for translation, see the set_translation_domain() method. Optional with a default value of None. * The callback function invoked when the action is activated. Optional with a default value of None. The "activate" signals of the actions are connected to the callbacks and their accel paths are set to /group-name/action-name. """ try: iter(entries) except TypeError: raise TypeError("entries must be iterable") def _process_action( name, stock_id=None, label=None, accelerator=None, tooltip=None, callback=None, ): action = Action( name=name, label=label, tooltip=tooltip, stock_id=stock_id ) if callback is not None: if user_data is None: action.connect("activate", callback) else: action.connect("activate", callback, user_data) self.add_action_with_accel(action, accelerator) for e in entries: # using inner function above since entries can leave out optional arguments _process_action(*e) def add_toggle_actions(self, entries, user_data=None): """The add_toggle_actions() method is a convenience method that creates a number of gtk.ToggleAction objects based on the information in the list of action entry tuples contained in entries and adds them to the action group. The toggle action entry tuples can vary in size from one to seven items with the following information: * The name of the action. Must be specified. * The stock id for the action. Optional with a default value of None if a label is specified. * The label for the action. This field should typically be marked for translation, see the set_translation_domain() method. Optional with a default value of None if a stock id is specified. * The accelerator for the action, in the format understood by the gtk.accelerator_parse() function. Optional with a default value of None. * The tooltip for the action. This field should typically be marked for translation, see the set_translation_domain() method. Optional with a default value of None. * The callback function invoked when the action is activated. Optional with a default value of None. * A flag indicating whether the toggle action is active. Optional with a default value of False. The "activate" signals of the actions are connected to the callbacks and their accel paths are set to /group-name/action-name. """ try: iter(entries) except TypeError: raise TypeError("entries must be iterable") def _process_action( name, stock_id=None, label=None, accelerator=None, tooltip=None, callback=None, is_active=False, ): action = Gtk.ToggleAction( name=name, label=label, tooltip=tooltip, stock_id=stock_id ) action.set_active(is_active) if callback is not None: if user_data is None: action.connect("activate", callback) else: action.connect("activate", callback, user_data) self.add_action_with_accel(action, accelerator) for e in entries: # using inner function above since entries can leave out optional arguments _process_action(*e) def add_radio_actions( self, entries, value=None, on_change=None, user_data=None ): """The add_radio_actions() method is a convenience method that creates a number of gtk.RadioAction objects based on the information in the list of action entry tuples contained in entries and adds them to the action group. The entry tuples can vary in size from one to six items with the following information: * The name of the action. Must be specified. * The stock id for the action. Optional with a default value of None if a label is specified. * The label for the action. This field should typically be marked for translation, see the set_translation_domain() method. Optional with a default value of None if a stock id is specified. * The accelerator for the action, in the format understood by the gtk.accelerator_parse() function. Optional with a default value of None. * The tooltip for the action. This field should typically be marked for translation, see the set_translation_domain() method. Optional with a default value of None. * The value to set on the radio action. Optional with a default value of 0. Should be specified in applications. The value parameter specifies the radio action that should be set active. The "changed" signal of the first radio action is connected to the on_change callback (if specified and not None) and the accel paths of the actions are set to /group-name/action-name. """ try: iter(entries) except TypeError: raise TypeError("entries must be iterable") first_action = None def _process_action( group_source, name, stock_id=None, label=None, accelerator=None, tooltip=None, entry_value=0, ): action = RadioAction( name=name, label=label, tooltip=tooltip, stock_id=stock_id, value=entry_value, ) if GTK3: action.join_group(group_source) if value == entry_value: action.set_active(True) self.add_action_with_accel(action, accelerator) return action for e in entries: # using inner function above since entries can leave out optional arguments action = _process_action(first_action, *e) if first_action is None: first_action = action if first_action is not None and on_change is not None: if user_data is None: first_action.connect("changed", on_change) else: first_action.connect("changed", on_change, user_data) ActionGroup = override(ActionGroup) __all__.append("ActionGroup") class UIManager(Gtk.UIManager): def add_ui_from_string(self, buffer): if not isinstance(buffer, str): raise TypeError("buffer must be a string") length = _get_utf8_length(buffer) return Gtk.UIManager.add_ui_from_string(self, buffer, length) def insert_action_group(self, buffer, length=-1): return Gtk.UIManager.insert_action_group(self, buffer, length) UIManager = override(UIManager) __all__.append("UIManager") class ComboBox(Gtk.ComboBox, Container): get_active_iter = strip_boolean_result(Gtk.ComboBox.get_active_iter) ComboBox = override(ComboBox) __all__.append("ComboBox") if GTK3: class Box(Gtk.Box): __init__ = deprecated_init( Gtk.Box.__init__, arg_names=("homogeneous", "spacing"), category=PyGTKDeprecationWarning, ) Box = override(Box) __all__.append("Box") if GTK3: class SizeGroup(Gtk.SizeGroup): __init__ = deprecated_init( Gtk.SizeGroup.__init__, arg_names=("mode",), deprecated_defaults={"mode": Gtk.SizeGroupMode.VERTICAL}, category=PyGTKDeprecationWarning, ) SizeGroup = override(SizeGroup) __all__.append("SizeGroup") if GTK3: class MenuItem(Gtk.MenuItem): __init__ = deprecated_init( Gtk.MenuItem.__init__, arg_names=("label",), category=PyGTKDeprecationWarning, ) MenuItem = override(MenuItem) __all__.append("MenuItem") def _get_utf8_length(string): assert isinstance(string, str) if not isinstance(string, bytes): string = string.encode("utf-8") return len(string) class Builder(Gtk.Builder): if GTK4: from .._gtktemplate import define_builder_scope BuilderScope = define_builder_scope() def __init__(self, scope_object_or_map=None): super().__init__() if scope_object_or_map: self.set_scope(Builder.BuilderScope(scope_object_or_map)) else: def connect_signals(self, obj_or_map): """Connect signals specified by this builder to a name, handler mapping. Connect signal, name, and handler sets specified in the builder with the given mapping "obj_or_map". The handler/value aspect of the mapping can also contain a tuple in the form of (handler [,arg1 [,argN]]) allowing for extra arguments to be passed to the handler. For example: .. code-block:: python builder.connect_signals({"on_clicked": (on_clicked, arg1, arg2)}) """ self.connect_signals_full(_builder_connect_callback, obj_or_map) def add_from_string(self, buffer): if not isinstance(buffer, str): raise TypeError("buffer must be a string") length = _get_utf8_length(buffer) return Gtk.Builder.add_from_string(self, buffer, length) def add_objects_from_string(self, buffer, object_ids): if not isinstance(buffer, str): raise TypeError("buffer must be a string") length = _get_utf8_length(buffer) return Gtk.Builder.add_objects_from_string(self, buffer, length, object_ids) Builder = override(Builder) __all__.append("Builder") # NOTE: This must come before any other Window/Dialog subclassing, to ensure # that we have a correct inheritance hierarchy. if GTK4: _window_init = Gtk.Window.__init__ else: _window_init = deprecated_init( Gtk.Window.__init__, arg_names=("type",), category=PyGTKDeprecationWarning, stacklevel=3, ) class Window(Gtk.Window): def __init__(self, *args, **kwargs): if not initialized and get_option("legacy_autoinit"): # TODO: and not GTK5 raise RuntimeError( "Gtk couldn't be initialized. " "Use Gtk.init_check() if you want to handle this case." ) _window_init(self, *args, **kwargs) Window = override(Window) __all__.append("Window") class Dialog(Gtk.Dialog, Container): if GTK3: _old_arg_names = ("title", "parent", "flags", "buttons", "_buttons_property") _init = deprecated_init( Gtk.Dialog.__init__, arg_names=("title", "transient_for", "flags", "add_buttons", "buttons"), ignore=("flags", "add_buttons"), deprecated_aliases={ "transient_for": "parent", "buttons": "_buttons_property", }, category=PyGTKDeprecationWarning, ) def __init__(self, *args, **kwargs): new_kwargs = kwargs.copy() old_kwargs = dict(zip(self._old_arg_names, args)) old_kwargs.update(kwargs) # Increment the warning stacklevel for sub-classes which implement their own __init__. stacklevel = 2 if self.__class__ != Dialog and self.__class__.__init__ != Dialog.__init__: stacklevel += 1 # buttons was overloaded by PyGtk but is needed for Gtk.MessageDialog # as a pass through, so type check the argument and give a deprecation # when it is not of type Gtk.ButtonsType add_buttons = old_kwargs.get("buttons") if add_buttons is not None and not isinstance(add_buttons, Gtk.ButtonsType): warnings.warn( 'The "buttons" argument must be a Gtk.ButtonsType enum value. ' 'Please use the "add_buttons" method for adding buttons. ' "See: https://wiki.gnome.org/Projects/PyGObject/InitializerDeprecations", PyGTKDeprecationWarning, stacklevel=stacklevel, ) new_kwargs.pop("buttons", None) else: add_buttons = None flags = old_kwargs.get("flags", 0) if flags: warnings.warn( 'The "flags" argument for dialog construction is deprecated. ' "Please use initializer keywords: modal=True and/or destroy_with_parent=True. " "See: https://wiki.gnome.org/Projects/PyGObject/InitializerDeprecations", PyGTKDeprecationWarning, stacklevel=stacklevel, ) if flags & Gtk.DialogFlags.MODAL: new_kwargs["modal"] = True if flags & Gtk.DialogFlags.DESTROY_WITH_PARENT: new_kwargs["destroy_with_parent"] = True self._init(*args, **new_kwargs) if add_buttons: self.add_buttons(*add_buttons) def run(self, *args, **kwargs): with ( register_sigint_fallback(self.destroy), get_event_loop(GLib.MainContext.default()).running(self.destroy), ): return Gtk.Dialog.run(self, *args, **kwargs) action_area = property(lambda dialog: dialog.get_action_area()) vbox = property(lambda dialog: dialog.get_content_area()) def add_buttons(self, *args): """The add_buttons() method adds several buttons to the Gtk.Dialog using the button data passed as arguments to the method. This method is the same as calling the Gtk.Dialog.add_button() repeatedly. The button data pairs - button text (or stock ID) and a response ID integer are passed individually. For example: .. code-block:: python dialog.add_buttons(Gtk.STOCK_OPEN, 42, "Close", Gtk.ResponseType.CLOSE) will add "Open" and "Close" buttons to dialog. """ def _button(b): while b: try: t, r = b[0:2] except ValueError: raise ValueError("Must pass an even number of arguments") b = b[2:] yield t, r for text, response in _button(args): self.add_button(text, response) Dialog = override(Dialog) __all__.append("Dialog") if GTK3: class MessageDialog(Gtk.MessageDialog, Dialog): __init__ = deprecated_init( Gtk.MessageDialog.__init__, arg_names=("parent", "flags", "message_type", "buttons", "message_format"), deprecated_aliases={"text": "message_format", "message_type": "type"}, category=PyGTKDeprecationWarning, ) def format_secondary_text(self, message_format): self.set_property("secondary-use-markup", False) self.set_property("secondary-text", message_format) def format_secondary_markup(self, message_format): self.set_property("secondary-use-markup", True) self.set_property("secondary-text", message_format) MessageDialog = override(MessageDialog) __all__.append("MessageDialog") if GTK3: class ColorSelectionDialog(Gtk.ColorSelectionDialog): __init__ = deprecated_init( Gtk.ColorSelectionDialog.__init__, arg_names=("title",), category=PyGTKDeprecationWarning, ) ColorSelectionDialog = override(ColorSelectionDialog) __all__.append("ColorSelectionDialog") class FileChooserDialog(Gtk.FileChooserDialog): __init__ = deprecated_init( Gtk.FileChooserDialog.__init__, arg_names=("title", "parent", "action", "buttons"), category=PyGTKDeprecationWarning, ) FileChooserDialog = override(FileChooserDialog) __all__.append("FileChooserDialog") if GTK3: class FontSelectionDialog(Gtk.FontSelectionDialog): __init__ = deprecated_init( Gtk.FontSelectionDialog.__init__, arg_names=("title",), category=PyGTKDeprecationWarning, ) FontSelectionDialog = override(FontSelectionDialog) __all__.append("FontSelectionDialog") if GTK3: class RecentChooserDialog(Gtk.RecentChooserDialog): # Note, the "manager" keyword must work across the entire 3.x series because # "recent_manager" is not backwards compatible with PyGObject versions prior to 3.10. __init__ = deprecated_init( Gtk.RecentChooserDialog.__init__, arg_names=("title", "parent", "recent_manager", "buttons"), deprecated_aliases={"recent_manager": "manager"}, category=PyGTKDeprecationWarning, ) RecentChooserDialog = override(RecentChooserDialog) __all__.append("RecentChooserDialog") class IconView(Gtk.IconView): if GTK3: __init__ = deprecated_init( Gtk.IconView.__init__, arg_names=("model",), category=PyGTKDeprecationWarning, ) get_item_at_pos = strip_boolean_result(Gtk.IconView.get_item_at_pos) get_visible_range = strip_boolean_result(Gtk.IconView.get_visible_range) get_dest_item_at_pos = strip_boolean_result(Gtk.IconView.get_dest_item_at_pos) IconView = override(IconView) __all__.append("IconView") if GTK3: class ToolButton(Gtk.ToolButton): __init__ = deprecated_init( Gtk.ToolButton.__init__, arg_names=("stock_id",), category=PyGTKDeprecationWarning, ) ToolButton = override(ToolButton) __all__.append("ToolButton") class IMContext(Gtk.IMContext): get_surrounding = strip_boolean_result(Gtk.IMContext.get_surrounding) IMContext = override(IMContext) __all__.append("IMContext") class RecentInfo(Gtk.RecentInfo): get_application_info = strip_boolean_result(Gtk.RecentInfo.get_application_info) RecentInfo = override(RecentInfo) __all__.append("RecentInfo") class TextBuffer(Gtk.TextBuffer): def create_tag(self, tag_name=None, **properties): """Creates a tag and adds it to the tag table of the TextBuffer. :param str tag_name: Name of the new tag, or None :param **properties: Keyword list of properties and their values This is equivalent to creating a Gtk.TextTag and then adding the tag to the buffer's tag table. The returned tag is owned by the buffer's tag table. If ``tag_name`` is None, the tag is anonymous. If ``tag_name`` is not None, a tag called ``tag_name`` must not already exist in the tag table for this buffer. Properties are passed as a keyword list of names and values (e.g. foreground='DodgerBlue', weight=Pango.Weight.BOLD) :returns: A new tag. """ tag = Gtk.TextTag(name=tag_name, **properties) self.get_tag_table().add(tag) return tag def create_mark(self, mark_name, where, left_gravity=False): return Gtk.TextBuffer.create_mark(self, mark_name, where, left_gravity) def set_text(self, text, length=-1): Gtk.TextBuffer.set_text(self, text, length) def insert(self, iter, text, length=-1): if not isinstance(text, str): raise TypeError(f"text must be a string, not {type(text)}") Gtk.TextBuffer.insert(self, iter, text, length) def insert_with_tags(self, iter, text, *tags): start_offset = iter.get_offset() self.insert(iter, text) if not tags: return start = self.get_iter_at_offset(start_offset) for tag in tags: self.apply_tag(tag, start, iter) def insert_with_tags_by_name(self, iter, text, *tags): tag_objs = [] for tag in tags: tag_obj = self.get_tag_table().lookup(tag) if not tag_obj: raise ValueError(f"unknown text tag: {tag}") tag_objs.append(tag_obj) self.insert_with_tags(iter, text, *tag_objs) def insert_at_cursor(self, text, length=-1): if not isinstance(text, str): raise TypeError(f"text must be a string, not {type(text)}") Gtk.TextBuffer.insert_at_cursor(self, text, length) get_selection_bounds = strip_boolean_result( Gtk.TextBuffer.get_selection_bounds, fail_ret=() ) TextBuffer = override(TextBuffer) __all__.append("TextBuffer") class TextIter(Gtk.TextIter): forward_search = strip_boolean_result(Gtk.TextIter.forward_search) backward_search = strip_boolean_result(Gtk.TextIter.backward_search) TextIter = override(TextIter) __all__.append("TextIter") class TreeModel(Gtk.TreeModel): def __len__(self): return self.iter_n_children(None) def __bool__(self): return True def _getiter(self, key): if isinstance(key, Gtk.TreeIter): return key if isinstance(key, int) and key < 0: index = len(self) + key if index < 0: msg = f"row index is out of bounds: {key:d}" raise IndexError(msg) return self.get_iter(index) try: aiter = self.get_iter(key) except ValueError: raise IndexError(f"could not find tree path '{key}'") return aiter def sort_new_with_model(self): super_object = super() if hasattr(super_object, "sort_new_with_model"): return super_object.sort_new_with_model() return TreeModelSort.new_with_model(self) def _coerce_path(self, path): if isinstance(path, Gtk.TreePath): return path return TreePath(path) def __getitem__(self, key): aiter = self._getiter(key) return TreeModelRow(self, aiter) def __setitem__(self, key, value): row = self[key] self.set_row(row.iter, value) def __delitem__(self, key): aiter = self._getiter(key) self.remove(aiter) def __iter__(self): return TreeModelRowIter(self, self.get_iter_first()) get_iter_first = strip_boolean_result(Gtk.TreeModel.get_iter_first) iter_children = strip_boolean_result(Gtk.TreeModel.iter_children) iter_nth_child = strip_boolean_result(Gtk.TreeModel.iter_nth_child) iter_parent = strip_boolean_result(Gtk.TreeModel.iter_parent) get_iter_from_string = strip_boolean_result( Gtk.TreeModel.get_iter_from_string, ValueError, "invalid tree path" ) def get_iter(self, path): path = self._coerce_path(path) success, aiter = super().get_iter(path) if not success: raise ValueError(f"invalid tree path '{path}'") return aiter def iter_next(self, aiter): next_iter = aiter.copy() success = super().iter_next(next_iter) if success: return next_iter return None def iter_previous(self, aiter): prev_iter = aiter.copy() success = super().iter_previous(prev_iter) if success: return prev_iter return None def _convert_row(self, row): # TODO: Accept a dictionary for row # model.append(None,{COLUMN_ICON: icon, COLUMN_NAME: name}) if isinstance(row, str): raise TypeError("Expected a list or tuple, but got str") n_columns = self.get_n_columns() if len(row) != n_columns: raise ValueError("row sequence has the incorrect number of elements") result = [] columns = [] for cur_col, value in enumerate(row): # do not try to set None values, they are causing warnings if value is None: continue result.append(self._convert_value(cur_col, value)) columns.append(cur_col) return (result, columns) def set_row(self, treeiter, row): _converted_row, columns = self._convert_row(row) for column in columns: self.set_value(treeiter, column, row[column]) def _convert_value(self, column, value): """Convert value to a GObject.Value of the expected type.""" if isinstance(value, GObject.Value): return value return GObject.Value(self.get_column_type(column), value) def get(self, treeiter, *columns): n_columns = self.get_n_columns() values = [] for col in columns: if not isinstance(col, int): raise TypeError("column numbers must be ints") if col < 0 or col >= n_columns: raise ValueError("column number is out of range") values.append(self.get_value(treeiter, col)) return tuple(values) # # Signals supporting python iterables as tree paths # def row_changed(self, path, iter): return super().row_changed(self._coerce_path(path), iter) def row_inserted(self, path, iter): return super().row_inserted(self._coerce_path(path), iter) def row_has_child_toggled(self, path, iter): return super().row_has_child_toggled(self._coerce_path(path), iter) def row_deleted(self, path): return super().row_deleted(self._coerce_path(path)) def rows_reordered(self, path, iter, new_order): return super().rows_reordered(self._coerce_path(path), iter, new_order) TreeModel = override(TreeModel) __all__.append("TreeModel") class TreeSortable( Gtk.TreeSortable, ): get_sort_column_id = strip_boolean_result( Gtk.TreeSortable.get_sort_column_id, fail_ret=(None, None) ) def set_sort_func(self, sort_column_id, sort_func, user_data=None): super().set_sort_func(sort_column_id, sort_func, user_data) def set_default_sort_func(self, sort_func, user_data=None): super().set_default_sort_func(sort_func, user_data) TreeSortable = override(TreeSortable) __all__.append("TreeSortable") if GTK3: class TreeModelSort(Gtk.TreeModelSort): __init__ = deprecated_init( Gtk.TreeModelSort.__init__, arg_names=("model",), category=PyGTKDeprecationWarning, ) if not hasattr(Gtk.TreeModelSort, "new_with_model"): @classmethod def new_with_model(self, child_model): return TreeModel.sort_new_with_model(child_model) TreeModelSort = override(TreeModelSort) __all__.append("TreeModelSort") class ListStore(Gtk.ListStore, TreeModel, TreeSortable): def __init__(self, *column_types): Gtk.ListStore.__init__(self) self.set_column_types(column_types) # insert_with_valuesv got renamed to insert_with_values with 4.1.0 # https://gitlab.gnome.org/GNOME/gtk/-/commit/a1216599ff6b39bca3e9 if not hasattr(Gtk.ListStore, "insert_with_valuesv"): insert_with_valuesv = Gtk.ListStore.insert_with_values elif not hasattr(Gtk.ListStore, "insert_with_values"): insert_with_values = Gtk.ListStore.insert_with_valuesv def _do_insert(self, position, row): if row is not None: row, columns = self._convert_row(row) treeiter = self.insert_with_values(position, columns, row) else: treeiter = Gtk.ListStore.insert(self, position) return treeiter def append(self, row=None): if row: return self._do_insert(-1, row) # gtk_list_store_insert() does not know about the "position == -1" # case, so use append() here return Gtk.ListStore.append(self) def prepend(self, row=None): return self._do_insert(0, row) def insert(self, position, row=None): return self._do_insert(position, row) def insert_before(self, sibling, row=None): if row is not None: if sibling is None: position = -1 else: position = self.get_path(sibling).get_indices()[-1] return self._do_insert(position, row) return Gtk.ListStore.insert_before(self, sibling) def insert_after(self, sibling, row=None): if row is not None: if sibling is None: position = 0 else: position = self.get_path(sibling).get_indices()[-1] + 1 return self._do_insert(position, row) return Gtk.ListStore.insert_after(self, sibling) def set_value(self, treeiter, column, value): value = self._convert_value(column, value) Gtk.ListStore.set_value(self, treeiter, column, value) def set(self, treeiter, *args): def _set_lists(cols, vals): if len(cols) != len(vals): raise TypeError( "The number of columns do not match the number of values" ) columns = [] values = [] for col_num, value in zip(cols, vals): if not isinstance(col_num, int): raise TypeError("TypeError: Expected integer argument for column.") columns.append(col_num) values.append(self._convert_value(col_num, value)) Gtk.ListStore.set(self, treeiter, columns, values) if args: if isinstance(args[0], int): _set_lists(args[::2], args[1::2]) elif isinstance(args[0], (tuple, list)): if len(args) != 2: raise TypeError("Too many arguments") _set_lists(args[0], args[1]) elif isinstance(args[0], dict): _set_lists(list(args[0]), args[0].values()) else: raise TypeError( "Argument list must be in the form of (column, value, ...), ((columns,...), (values, ...)) or {column: value}. No -1 termination is needed." ) ListStore = override(ListStore) __all__.append("ListStore") class TreeModelRow: def __init__(self, model, iter_or_path): if not isinstance(model, Gtk.TreeModel): raise TypeError(f"expected Gtk.TreeModel, {type(model).__name__} found") self.model = model if isinstance(iter_or_path, Gtk.TreePath): self.iter = model.get_iter(iter_or_path) elif isinstance(iter_or_path, Gtk.TreeIter): self.iter = iter_or_path else: raise TypeError( "expected Gtk.TreeIter or Gtk.TreePath, " f"{type(iter_or_path).__name__} found" ) @property def path(self): return self.model.get_path(self.iter) @property def next(self): return self.get_next() @property def previous(self): return self.get_previous() @property def parent(self): return self.get_parent() def get_next(self): next_iter = self.model.iter_next(self.iter) if next_iter: return TreeModelRow(self.model, next_iter) return None def get_previous(self): prev_iter = self.model.iter_previous(self.iter) if prev_iter: return TreeModelRow(self.model, prev_iter) return None def get_parent(self): parent_iter = self.model.iter_parent(self.iter) if parent_iter: return TreeModelRow(self.model, parent_iter) return None def __getitem__(self, key): if isinstance(key, int): if key >= self.model.get_n_columns(): msg = f"column index is out of bounds: {key:d}" raise IndexError(msg) if key < 0: key = self._convert_negative_index(key) return self.model.get_value(self.iter, key) if isinstance(key, slice): start, stop, step = key.indices(self.model.get_n_columns()) return [ self.model.get_value(self.iter, i) for i in range(start, stop, step) ] if isinstance(key, tuple): return [self[k] for k in key] raise TypeError( f"indices must be integers, slice or tuple, not {type(key).__name__}" ) def __setitem__(self, key, value): if isinstance(key, int): if key >= self.model.get_n_columns(): msg = f"column index is out of bounds: {key:d}" raise IndexError(msg) if key < 0: key = self._convert_negative_index(key) self.model.set_value(self.iter, key, value) elif isinstance(key, slice): start, stop, step = key.indices(self.model.get_n_columns()) indexList = range(start, stop, step) if len(indexList) != len(value): msg = f"attempt to assign sequence of size {len(value):d} to slice of size {len(indexList):d}d" raise ValueError(msg) for i, v in enumerate(indexList): self.model.set_value(self.iter, v, value[i]) elif isinstance(key, tuple): if len(key) != len(value): msg = f"attempt to assign sequence of size {len(value):d} to sequence of size {len(key):d}" raise ValueError(msg) for k, v in zip(key, value): self[k] = v else: raise TypeError( f"indices must be an integer, slice or tuple, not {type(key).__name__}" ) def _convert_negative_index(self, index): new_index = self.model.get_n_columns() + index if new_index < 0: msg = f"column index is out of bounds: {index:d}" raise IndexError(msg) return new_index def iterchildren(self): child_iter = self.model.iter_children(self.iter) return TreeModelRowIter(self.model, child_iter) __all__.append("TreeModelRow") class TreeModelRowIter: def __init__(self, model, aiter): self.model = model self.iter = aiter def __next__(self): if not self.iter: raise StopIteration row = TreeModelRow(self.model, self.iter) self.iter = self.model.iter_next(self.iter) return row def __iter__(self): return self __all__.append("TreeModelRowIter") class TreePath(Gtk.TreePath): def __new__(cls, path=0): if isinstance(path, int): path = str(path) elif not isinstance(path, str): path = ":".join(str(val) for val in path) if len(path) == 0: raise TypeError(f"could not parse subscript '{path}' as a tree path") try: return TreePath.new_from_string(path) except TypeError: raise TypeError(f"could not parse subscript '{path}' as a tree path") def __init__(self, *args, **kwargs): super().__init__() def __str__(self): return self.to_string() or "" def __lt__(self, other): return other is not None and self.compare(other) < 0 def __le__(self, other): return other is not None and self.compare(other) <= 0 def __eq__(self, other): return other is not None and self.compare(other) == 0 def __ne__(self, other): return other is None or self.compare(other) != 0 def __gt__(self, other): return other is None or self.compare(other) > 0 def __ge__(self, other): return other is None or self.compare(other) >= 0 def __iter__(self): return iter(self.get_indices()) def __len__(self): return self.get_depth() def __getitem__(self, index): return self.get_indices()[index] TreePath = override(TreePath) __all__.append("TreePath") class TreeStore(Gtk.TreeStore, TreeModel, TreeSortable): def __init__(self, *column_types): Gtk.TreeStore.__init__(self) self.set_column_types(column_types) def _do_insert(self, parent, position, row): if row is not None: row, columns = self._convert_row(row) treeiter = self.insert_with_values(parent, position, columns, row) else: treeiter = Gtk.TreeStore.insert(self, parent, position) return treeiter def append(self, parent, row=None): return self._do_insert(parent, -1, row) def prepend(self, parent, row=None): return self._do_insert(parent, 0, row) def insert(self, parent, position, row=None): return self._do_insert(parent, position, row) def insert_before(self, parent, sibling, row=None): if row is not None: if sibling is None: position = -1 else: if parent is None: parent = self.iter_parent(sibling) position = self.get_path(sibling).get_indices()[-1] return self._do_insert(parent, position, row) return Gtk.TreeStore.insert_before(self, parent, sibling) def insert_after(self, parent, sibling, row=None): if row is not None: if sibling is None: position = 0 else: if parent is None: parent = self.iter_parent(sibling) position = self.get_path(sibling).get_indices()[-1] + 1 return self._do_insert(parent, position, row) return Gtk.TreeStore.insert_after(self, parent, sibling) def set_value(self, treeiter, column, value): value = self._convert_value(column, value) Gtk.TreeStore.set_value(self, treeiter, column, value) def set(self, treeiter, *args): def _set_lists(cols, vals): if len(cols) != len(vals): raise TypeError( "The number of columns do not match the number of values" ) columns = [] values = [] for col_num, value in zip(cols, vals): if not isinstance(col_num, int): raise TypeError("TypeError: Expected integer argument for column.") columns.append(col_num) values.append(self._convert_value(col_num, value)) Gtk.TreeStore.set(self, treeiter, columns, values) if args: if isinstance(args[0], int): _set_lists(args[::2], args[1::2]) elif isinstance(args[0], (tuple, list)): if len(args) != 2: raise TypeError("Too many arguments") _set_lists(args[0], args[1]) elif isinstance(args[0], dict): _set_lists(args[0].keys(), args[0].values()) else: raise TypeError( "Argument list must be in the form of (column, value, ...), ((columns,...), (values, ...)) or {column: value}. No -1 termination is needed." ) TreeStore = override(TreeStore) __all__.append("TreeStore") class TreeView(Gtk.TreeView, Container): if GTK3: __init__ = deprecated_init( Gtk.TreeView.__init__, arg_names=("model",), category=PyGTKDeprecationWarning, ) get_path_at_pos = strip_boolean_result(Gtk.TreeView.get_path_at_pos) get_visible_range = strip_boolean_result(Gtk.TreeView.get_visible_range) get_dest_row_at_pos = strip_boolean_result(Gtk.TreeView.get_dest_row_at_pos) if GTK3: def enable_model_drag_source(self, start_button_mask, targets, actions): target_entries = _construct_target_list(targets) super().enable_model_drag_source(start_button_mask, target_entries, actions) if GTK3: def enable_model_drag_dest(self, targets, actions): target_entries = _construct_target_list(targets) super().enable_model_drag_dest(target_entries, actions) def scroll_to_cell( self, path, column=None, use_align=False, row_align=0.0, col_align=0.0 ): if not isinstance(path, Gtk.TreePath): path = TreePath(path) super().scroll_to_cell(path, column, use_align, row_align, col_align) def set_cursor(self, path, column=None, start_editing=False): if not isinstance(path, Gtk.TreePath): path = TreePath(path) super().set_cursor(path, column, start_editing) def get_cell_area(self, path, column=None): if not isinstance(path, Gtk.TreePath): path = TreePath(path) return super().get_cell_area(path, column) def insert_column_with_attributes(self, position, title, cell, **kwargs): column = TreeViewColumn() column.set_title(title) column.pack_start(cell, False) self.insert_column(column, position) column.set_attributes(cell, **kwargs) TreeView = override(TreeView) __all__.append("TreeView") class TreeViewColumn(Gtk.TreeViewColumn): def __init__(self, title="", cell_renderer=None, **attributes): Gtk.TreeViewColumn.__init__(self, title=title) if cell_renderer: self.pack_start(cell_renderer, True) for name, value in attributes.items(): self.add_attribute(cell_renderer, name, value) cell_get_position = strip_boolean_result(Gtk.TreeViewColumn.cell_get_position) def set_cell_data_func(self, cell_renderer, func, func_data=None): super().set_cell_data_func(cell_renderer, func, func_data) def set_attributes(self, cell_renderer, **attributes): Gtk.CellLayout.clear_attributes(self, cell_renderer) for name, value in attributes.items(): Gtk.CellLayout.add_attribute(self, cell_renderer, name, value) TreeViewColumn = override(TreeViewColumn) __all__.append("TreeViewColumn") class TreeSelection(Gtk.TreeSelection): def select_path(self, path): if not isinstance(path, Gtk.TreePath): path = TreePath(path) super().select_path(path) def get_selected(self): success, model, aiter = super().get_selected() if success: return (model, aiter) return (model, None) # for compatibility with PyGtk def get_selected_rows(self): rows, model = super().get_selected_rows() return (model, rows) TreeSelection = override(TreeSelection) __all__.append("TreeSelection") if GTK3: class Button(Gtk.Button, Container): _init = deprecated_init( Gtk.Button.__init__, arg_names=("label", "stock", "use_stock", "use_underline"), ignore=("stock",), category=PyGTKDeprecationWarning, stacklevel=3, ) def __init__(self, *args, **kwargs): # Doubly deprecated initializer, the stock keyword is non-standard. # Simply give a warning that stock items are deprecated even though # we want to deprecate the non-standard keyword as well here from # the overrides. if kwargs.get("stock"): warnings.warn( "Stock items are deprecated. " "Please use: Gtk.Button.new_with_mnemonic(label)", PyGTKDeprecationWarning, stacklevel=2, ) new_kwargs = kwargs.copy() new_kwargs["label"] = new_kwargs["stock"] new_kwargs["use_stock"] = True new_kwargs["use_underline"] = True del new_kwargs["stock"] Gtk.Button.__init__(self, **new_kwargs) else: self._init(*args, **kwargs) if hasattr(Gtk.Widget, "set_focus_on_click"): def set_focus_on_click(self, *args, **kwargs): # Gtk.Widget.set_focus_on_click should be used instead but it's # no obvious how because of the shadowed method, so override here return Gtk.Widget.set_focus_on_click(self, *args, **kwargs) if hasattr(Gtk.Widget, "get_focus_on_click"): def get_focus_on_click(self, *args, **kwargs): # Gtk.Widget.get_focus_on_click should be used instead but it's # no obvious how because of the shadowed method, so override here return Gtk.Widget.get_focus_on_click(self, *args, **kwargs) Button = override(Button) __all__.append("Button") class LinkButton(Gtk.LinkButton): __init__ = deprecated_init( Gtk.LinkButton.__init__, arg_names=("uri", "label"), category=PyGTKDeprecationWarning, ) LinkButton = override(LinkButton) __all__.append("LinkButton") class Label(Gtk.Label): __init__ = deprecated_init( Gtk.Label.__init__, arg_names=("label",), category=PyGTKDeprecationWarning ) Label = override(Label) __all__.append("Label") class Adjustment(Gtk.Adjustment): if GTK3: _init = deprecated_init( Gtk.Adjustment.__init__, arg_names=( "value", "lower", "upper", "step_increment", "page_increment", "page_size", ), deprecated_aliases={ "page_increment": "page_incr", "step_increment": "step_incr", }, category=PyGTKDeprecationWarning, stacklevel=3, ) def __init__(self, *args, **kwargs): if GTK3: self._init(*args, **kwargs) # The value property is set between lower and (upper - page_size). # Just in case lower, upper or page_size was still 0 when value # was set, we set it again here. if "value" in kwargs: self.set_value(kwargs["value"]) elif len(args) >= 1: self.set_value(args[0]) else: Gtk.Adjustment.__init__(self, *args, **kwargs) # The value property is set between lower and (upper - page_size). # Just in case lower, upper or page_size was still 0 when value # was set, we set it again here. if "value" in kwargs: self.set_value(kwargs["value"]) Adjustment = override(Adjustment) __all__.append("Adjustment") if GTK3: class Table(Gtk.Table, Container): __init__ = deprecated_init( Gtk.Table.__init__, arg_names=("n_rows", "n_columns", "homogeneous"), deprecated_aliases={"n_rows": "rows", "n_columns": "columns"}, category=PyGTKDeprecationWarning, ) def attach( self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions=Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, xpadding=0, ypadding=0, ): Gtk.Table.attach( self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions, yoptions, xpadding, ypadding, ) Table = override(Table) __all__.append("Table") class ScrolledWindow(Gtk.ScrolledWindow): __init__ = deprecated_init( Gtk.ScrolledWindow.__init__, arg_names=("hadjustment", "vadjustment"), category=PyGTKDeprecationWarning, ) ScrolledWindow = override(ScrolledWindow) __all__.append("ScrolledWindow") if GTK3: class HScrollbar(Gtk.HScrollbar): __init__ = deprecated_init( Gtk.HScrollbar.__init__, arg_names=("adjustment",), category=PyGTKDeprecationWarning, ) HScrollbar = override(HScrollbar) __all__.append("HScrollbar") class VScrollbar(Gtk.VScrollbar): __init__ = deprecated_init( Gtk.VScrollbar.__init__, arg_names=("adjustment",), category=PyGTKDeprecationWarning, ) VScrollbar = override(VScrollbar) __all__.append("VScrollbar") if GTK3: class Paned(Gtk.Paned): def pack1(self, child, resize=False, shrink=True): super().pack1(child, resize, shrink) def pack2(self, child, resize=True, shrink=True): super().pack2(child, resize, shrink) Paned = override(Paned) __all__.append("Paned") if GTK3: class Arrow(Gtk.Arrow): __init__ = deprecated_init( Gtk.Arrow.__init__, arg_names=("arrow_type", "shadow_type"), category=PyGTKDeprecationWarning, ) Arrow = override(Arrow) __all__.append("Arrow") class IconSet(Gtk.IconSet): def __new__(cls, pixbuf=None): if pixbuf is not None: warnings.warn( "Gtk.IconSet(pixbuf) has been deprecated. Please use: " "Gtk.IconSet.new_from_pixbuf(pixbuf)", PyGTKDeprecationWarning, stacklevel=2, ) iconset = Gtk.IconSet.new_from_pixbuf(pixbuf) else: iconset = Gtk.IconSet.__new__(cls) return iconset def __init__(self, *args, **kwargs): return super().__init__() IconSet = override(IconSet) __all__.append("IconSet") class Viewport(Gtk.Viewport): __init__ = deprecated_init( Gtk.Viewport.__init__, arg_names=("hadjustment", "vadjustment"), category=PyGTKDeprecationWarning, ) Viewport = override(Viewport) __all__.append("Viewport") class TreeModelFilter(Gtk.TreeModelFilter): def set_visible_func(self, func, data=None): super().set_visible_func(func, data) def set_value(self, iter, column, value): # Delegate to child model iter = self.convert_iter_to_child_iter(iter) self.get_model().set_value(iter, column, value) TreeModelFilter = override(TreeModelFilter) __all__.append("TreeModelFilter") if GTK3 or GTK4: class CssProvider(Gtk.CssProvider): def load_from_data(self, text, length=-1): if (Gtk.get_major_version(), Gtk.get_minor_version()) >= (4, 9): if isinstance(text, bytes): text = text.decode("utf-8") super().load_from_data(text, length) else: if isinstance(text, str): text = text.encode("utf-8") super().load_from_data(text) CssProvider = override(CssProvider) __all__.append("CssProvider") if GTK4: class CustomSorter(Gtk.CustomSorter): @classmethod def new(cls, sort_func, user_data=None): if sort_func is not None: compare_func = wrap_list_store_sort_func(sort_func) else: compare_func = None return Gtk.CustomSorter.new(compare_func, user_data) def set_sort_func(self, sort_func, user_data=None): if sort_func is not None: compare_func = wrap_list_store_sort_func(sort_func) else: compare_func = None return super().set_sort_func(compare_func, user_data) CustomSorter = override(CustomSorter) __all__.append("CustomSorter") if GTK3: class Menu(Gtk.Menu): def popup( self, parent_menu_shell, parent_menu_item, func, data, button, activate_time ): self.popup_for_device( None, parent_menu_shell, parent_menu_item, func, data, button, activate_time, ) Menu = override(Menu) __all__.append("Menu") if GTK3: _Gtk_main_quit = Gtk.main_quit @override(Gtk.main_quit) def main_quit(*args): _Gtk_main_quit() _Gtk_main = Gtk.main @override(Gtk.main) def main(*args, **kwargs): with ( register_sigint_fallback(Gtk.main_quit), get_event_loop(GLib.MainContext.default()).running(Gtk.main_quit), ): return _Gtk_main(*args, **kwargs) _Gtk_main_iteration = Gtk.main_iteration _Gtk_main_iteration_do = Gtk.main_iteration_do @override(Gtk.main_iteration) def main_iteration(): with get_event_loop(GLib.MainContext.default()).paused(): return _Gtk_main_iteration() @override(Gtk.main_iteration) def main_iteration_do(blocking): with get_event_loop(GLib.MainContext.default()).paused(): return _Gtk_main_iteration_do(blocking) if GTK3: stock_lookup = strip_boolean_result(Gtk.stock_lookup) __all__.append("stock_lookup") if not get_option("legacy_autoinit"): # TODO: or GTK5 initialized = False elif GTK4: initialized = Gtk.init_check() else: initialized, argv = Gtk.init_check(sys.argv) sys.argv = list(argv) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/Pango.py0000664000000000000000000000312715074673150016370 0ustar00rootroot# Copyright (C) 2010 Paolo Borelli # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA from ..overrides import override from ..module import get_introspection_module Pango = get_introspection_module("Pango") __all__ = [] class FontDescription(Pango.FontDescription): def __new__(cls, string=None): if string is not None: return Pango.font_description_from_string(string) return Pango.FontDescription.__new__(cls) def __init__(self, *args, **kwargs): return super().__init__() FontDescription = override(FontDescription) __all__.append("FontDescription") class Layout(Pango.Layout): def __new__(cls, context): return Pango.Layout.new(context) def set_markup(self, text, length=-1): super().set_markup(text, length) def set_text(self, text, length=-1): super().set_text(text, length) Layout = override(Layout) __all__.append("Layout") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/__init__.py0000664000000000000000000003227615074673150017072 0ustar00rootrootimport functools import types import warnings import importlib import sys from gi import PyGIDeprecationWarning from gi._gi import CallableInfo, pygobject_new_full from gi._constants import TYPE_NONE, TYPE_INVALID # support overrides in different directories than our gi module from pkgutil import extend_path __path__ = extend_path(__path__, __name__) # namespace -> (attr, replacement) _deprecated_attrs = {} class OverridesProxyModule(types.ModuleType): """Wraps a introspection module and contains all overrides""" __slots__ = ("_deprecations", "_introspection_module") def __init__(self, introspection_module): super().__init__(introspection_module.__name__) self._introspection_module = introspection_module self._deprecations = {} def __getattr__(self, name): if name in self._deprecations: value, warning = self._deprecations[name] warnings.warn(warning, stacklevel=2) return value return getattr(self._introspection_module, name) def __delattr__(self, name): found = False if name in self.__dict__: del self.__dict__[name] found = True if name in self._deprecations: del self._deprecations[name] found = True try: delattr(self._introspection_module, name) except AttributeError: # Silence the exception if the attribute was previously found. if not found: raise def __dir__(self): result = set(super().__dir__()) result.update(self._deprecations.keys()) result.update(dir(self._introspection_module)) return sorted(result) def __repr__(self): return f"<{type(self).__name__} {self._introspection_module!r}>" class _DeprecatedAttribute: """A deprecation descriptor for OverridesProxyModule subclasses. Emits a PyGIDeprecationWarning on every access and tries to act as a normal instance attribute (can be replaced and deleted). """ def __init__(self, namespace, attr, value, replacement): self._attr = attr self._value = value self._warning = PyGIDeprecationWarning( f"{namespace}.{attr} is deprecated; use {replacement} instead" ) def __get__(self, instance, owner): if instance is None: raise AttributeError(self._attr) warnings.warn(self._warning, stacklevel=2) return self._value def __set__(self, instance, value): attr = self._attr # delete the descriptor, then set the instance value delattr(type(instance), attr) setattr(instance, attr, value) def __delete__(self, instance): # delete the descriptor delattr(type(instance), self._attr) def load_overrides(introspection_module): """Loads overrides for an introspection module. Either returns the same module again in case there are no overrides or a proxy module including overrides. Doesn't cache the result. """ namespace = introspection_module.__name__.rsplit(".", 1)[-1] module_key = "gi.repository." + namespace # We use sys.modules so overrides can import from gi.repository # but restore everything at the end so this doesn't have any side effects has_old = module_key in sys.modules old_module = sys.modules.get(module_key) proxy = OverridesProxyModule(introspection_module) sys.modules[module_key] = proxy # backwards compat: # gedit uses gi.importer.modules['Gedit']._introspection_module from ..importer import modules assert hasattr(proxy, "_introspection_module") modules[namespace] = proxy try: override_package_name = "gi.overrides." + namespace spec = importlib.util.find_spec(override_package_name) override_loader = spec.loader if spec is not None else None # Avoid checking for an ImportError, an override might # depend on a missing module thus causing an ImportError if override_loader is None: return introspection_module override_mod = importlib.import_module(override_package_name) finally: del modules[namespace] del sys.modules[module_key] if has_old: sys.modules[module_key] = old_module # backwards compat: for gst-python/gstmodule.c, # which tries to access Gst.Fraction through # Gst._overrides_module.Fraction. We assign the proxy instead as that # contains all overridden classes like Fraction during import anyway and # there is no need to keep the real override module alive. proxy._overrides_module = proxy override_all = [] if hasattr(override_mod, "__all__"): override_all = override_mod.__all__ for var in override_all: try: item = getattr(override_mod, var) except (AttributeError, TypeError): # Gedit puts a non-string in __all__, so catch TypeError here continue setattr(proxy, var, item) # Replace deprecated module level attributes with a descriptor # which emits a warning when accessed. for attr, replacement in _deprecated_attrs.pop(namespace, []): try: value = getattr(proxy, attr) except AttributeError: raise AssertionError( f"{attr} was set deprecated but wasn't added to __all__" ) delattr(proxy, attr) proxy._deprecations[attr] = ( value, PyGIDeprecationWarning( f"{namespace}.{attr} is deprecated; use {replacement} instead" ), ) return proxy def override(type_): """Decorator for registering an override. Other than objects added to __all__, these can get referenced in the same override module via the gi.repository module (get_parent_for_object() does for example), so they have to be added to the module immediately. """ if isinstance(type_, CallableInfo): func = type_ namespace = func.__module__.rsplit(".", 1)[-1] module = sys.modules["gi.repository." + namespace] def wrapper(func): setattr(module, func.__name__, func) return func return wrapper if isinstance(type_, types.FunctionType): raise TypeError(f"func must be a gi function, got {type_}") try: info = getattr(type_, "__info__") except AttributeError: raise TypeError( f"Can not override a type {type_.__name__}, which is not in a gobject " "introspection typelib" ) if not type_.__module__.startswith("gi.overrides"): raise KeyError( "You have tried override outside of the overrides module. " f"This is not allowed ({type_}, {type_.__module__})" ) g_type = info.get_g_type() assert g_type != TYPE_NONE if g_type != TYPE_INVALID: g_type.pytype = type_ namespace = type_.__module__.rsplit(".", 1)[-1] module = sys.modules["gi.repository." + namespace] setattr(module, type_.__name__, type_) return type_ overridefunc = override """Deprecated""" def deprecated(fn, replacement): """Decorator for marking methods and classes as deprecated.""" @functools.wraps(fn) def wrapped(*args, **kwargs): warnings.warn( f"{fn.__name__} is deprecated; use {replacement} instead", PyGIDeprecationWarning, stacklevel=2, ) return fn(*args, **kwargs) return wrapped def deprecated_attr(namespace, attr, replacement): """Marks a module level attribute as deprecated. Accessing it will emit a PyGIDeprecationWarning warning. e.g. for ``deprecated_attr("GObject", "STATUS_FOO", "GLib.Status.FOO")`` accessing GObject.STATUS_FOO will emit: "GObject.STATUS_FOO is deprecated; use GLib.Status.FOO instead" :param str namespace: The namespace of the override this is called in. :param str namespace: The attribute name (which gets added to __all__). :param str replacement: The replacement text which will be included in the warning. """ _deprecated_attrs.setdefault(namespace, []).append((attr, replacement)) def deprecated_init( super_init_func, arg_names, ignore=(), deprecated_aliases={}, deprecated_defaults={}, category=PyGIDeprecationWarning, stacklevel=2, ): """Wrapper for deprecating GObject based __init__ methods which specify defaults already available or non-standard defaults. :param callable super_init_func: Initializer to wrap. :param list arg_names: Ordered argument name list. :param list ignore: List of argument names to ignore when calling the wrapped function. This is useful for function which take a non-standard keyword that is munged elsewhere. :param dict deprecated_aliases: Dictionary mapping a keyword alias to the actual g_object_newv keyword. :param dict deprecated_defaults: Dictionary of non-standard defaults that will be used when the keyword is not explicitly passed. :param Exception category: Exception category of the error. :param int stacklevel: Stack level for the deprecation passed on to warnings.warn :returns: Wrapped version of ``super_init_func`` which gives a deprecation warning when non-keyword args or aliases are used. :rtype: callable """ # We use a list of argument names to maintain order of the arguments # being deprecated. This allows calls with positional arguments to # continue working but with a deprecation message. def new_init(self, *args, **kwargs): """Initializer for a GObject based classes with support for property sets through the use of explicit keyword arguments. """ # Print warnings for calls with positional arguments. if args: warnings.warn( "Using positional arguments with the GObject constructor has been deprecated. " 'Please specify keyword(s) for "{}" or use a class specific constructor. ' "See: https://wiki.gnome.org/Projects/PyGObject/InitializerDeprecations".format( ", ".join(arg_names[: len(args)]) ), category, stacklevel=stacklevel, ) new_kwargs = dict(zip(arg_names, args)) else: new_kwargs = {} new_kwargs.update(kwargs) # Print warnings for alias usage and transfer them into the new key. aliases_used = [] for key, alias in deprecated_aliases.items(): if alias in new_kwargs: new_kwargs[key] = new_kwargs.pop(alias) aliases_used.append(key) if aliases_used: warnings.warn( 'The keyword(s) "{}" have been deprecated in favor of "{}" respectively. ' "See: https://wiki.gnome.org/Projects/PyGObject/InitializerDeprecations".format( ", ".join(deprecated_aliases[k] for k in sorted(aliases_used)), ", ".join(sorted(aliases_used)), ), category, stacklevel=stacklevel, ) # Print warnings for defaults different than what is already provided by the property defaults_used = [] for key in deprecated_defaults: if key not in new_kwargs: new_kwargs[key] = deprecated_defaults[key] defaults_used.append(key) if defaults_used: warnings.warn( "Initializer is relying on deprecated non-standard " "defaults. Please update to explicitly use: {} " "See: https://wiki.gnome.org/Projects/PyGObject/InitializerDeprecations".format( ", ".join( f"{k}={deprecated_defaults[k]}" for k in sorted(defaults_used) ) ), category, stacklevel=stacklevel, ) # Remove keywords that should be ignored. for key in ignore: if key in new_kwargs: new_kwargs.pop(key) return super_init_func(self, **new_kwargs) return new_init def strip_boolean_result(method, exc_type=None, exc_str=None, fail_ret=None): """Translate method's return value for stripping off success flag. There are a lot of methods which return a "success" boolean and have several out arguments. Translate such a method to return the out arguments on success and None on failure. """ @functools.wraps(method) def wrapped(*args, **kwargs): ret = method(*args, **kwargs) if ret[0]: if len(ret) == 2: return ret[1] return ret[1:] if exc_type: raise exc_type(exc_str or "call failed") return fail_ret return wrapped def wrap_list_store_sort_func(func): def wrap(a, b, *user_data): a = pygobject_new_full(a, False) b = pygobject_new_full(b, False) return func(a, b, *user_data) return wrap def wrap_list_store_equal_func(func): def wrap(a, b, *user_data): a = pygobject_new_full(a, False) b = pygobject_new_full(b, False) return func(a, b, *user_data) return wrap ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/overrides/meson.build0000664000000000000000000000040315074673150017106 0ustar00rootrootpython_sources = [ 'GLib.py', 'Gtk.py', 'Gdk.py', 'GdkPixbuf.py', 'GObject.py', 'Gio.py', 'GioUnix.py', 'GIMarshallingTests.py', 'Pango.py', '__init__.py'] python.install_sources(python_sources, subdir : join_paths('gi', 'overrides') ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygboxed.c0000664000000000000000000001663215074673150014742 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * * pygboxed.c: wrapper for GBoxed * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include #include "pygboxed.h" #include "pygi-type.h" #include "pygi-util.h" GQuark pygboxed_type_key; PYGI_DEFINE_TYPE ("gobject.GBoxed", PyGBoxed_Type, PyGBoxed); static void gboxed_dealloc (PyGBoxed *self) { if (self->free_on_dealloc && pyg_boxed_get_ptr (self)) { PyGILState_STATE state = PyGILState_Ensure (); g_boxed_free (self->gtype, pyg_boxed_get_ptr (self)); PyGILState_Release (state); } Py_TYPE (self)->tp_free ((PyObject *)self); } static PyObject * gboxed_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE (self) == Py_TYPE (other) && PyObject_IsInstance (self, (PyObject *)&PyGBoxed_Type)) return pyg_ptr_richcompare (pyg_boxed_get_ptr (self), pyg_boxed_get_ptr (other), op); else { Py_RETURN_NOTIMPLEMENTED; } } static Py_hash_t gboxed_hash (PyGBoxed *self) { return (Py_hash_t)(gintptr)(pyg_boxed_get_ptr (self)); } static PyObject * gboxed_repr (PyGBoxed *boxed) { PyObject *module, *repr, *self = (PyObject *)boxed; gchar *module_str, *namespace; module = PyObject_GetAttrString (self, "__module__"); if (module == NULL) return NULL; if (!PyUnicode_Check (module)) { Py_DECREF (module); return NULL; } module_str = PyUnicode_AsUTF8 (module); namespace = g_strrstr (module_str, "."); if (namespace == NULL) { namespace = module_str; } else { namespace += 1; } repr = PyUnicode_FromFormat ( "<%s.%s object at %p (%s at %p)>", namespace, Py_TYPE (self)->tp_name, self, g_type_name (boxed->gtype), pyg_boxed_get_ptr (boxed)); Py_DECREF (module); return repr; } static int gboxed_init (PyGBoxed *self, PyObject *args, PyObject *kwargs) { gchar buf[512]; if (!PyArg_ParseTuple (args, ":GBoxed.__init__")) return -1; pyg_boxed_set_ptr (self, NULL); self->gtype = 0; self->free_on_dealloc = FALSE; g_snprintf (buf, sizeof (buf), "%s can not be constructed", Py_TYPE (self)->tp_name); PyErr_SetString (PyExc_NotImplementedError, buf); return -1; } static void gboxed_free (PyObject *op) { PyObject_Free (op); } static PyObject * gboxed_copy (PyGBoxed *self) { return pygi_gboxed_new (self->gtype, pyg_boxed_get_ptr (self), TRUE, TRUE); } static PyMethodDef pygboxed_methods[] = { { "copy", (PyCFunction)gboxed_copy, METH_NOARGS }, { NULL, NULL, 0 }, }; /** * pygi_register_gboxed: * @dict: the module dictionary to store the wrapper class. * @class_name: the Python name for the wrapper class. * @boxed_type: the GType of the boxed type being wrapped. * @type: the wrapper class. * * Registers a wrapper for a boxed type. The wrapper class will be a * subclass of gobject.GBoxed, and a reference to the wrapper class * will be stored in the provided module dictionary. */ void pygi_register_gboxed (PyObject *dict, const gchar *class_name, GType boxed_type, PyTypeObject *type) { PyObject *o; g_return_if_fail (dict != NULL); g_return_if_fail (class_name != NULL); g_return_if_fail (boxed_type != 0); if (!type->tp_dealloc) type->tp_dealloc = (destructor)gboxed_dealloc; Py_SET_TYPE (type, &PyType_Type); g_assert (Py_TYPE (&PyGBoxed_Type) != NULL); type->tp_base = &PyGBoxed_Type; if (PyType_Ready (type) < 0) { g_warning ("could not get type `%s' ready", type->tp_name); return; } PyDict_SetItemString (type->tp_dict, "__gtype__", o = pyg_type_wrapper_new (boxed_type)); Py_DECREF (o); g_type_set_qdata (boxed_type, pygboxed_type_key, type); PyDict_SetItemString (dict, (char *)class_name, (PyObject *)type); } /** * pygi_gboxed_new: * @boxed_type: the GType of the boxed value. * @boxed: the boxed value. * @copy_boxed: whether the new boxed wrapper should hold a copy of the value. * @own_ref: whether the boxed wrapper should own the boxed value. * * Creates a wrapper for a boxed value. If @copy_boxed is set to * True, the wrapper will hold a copy of the value, instead of the * value itself. If @own_ref is True, then the value held by the * wrapper will be freed when the wrapper is deallocated. If * @copy_boxed is True, then @own_ref must also be True. * * Returns: the boxed wrapper or %NULL and sets an exception. */ PyObject * pygi_gboxed_new (GType boxed_type, gpointer boxed, gboolean copy_boxed, gboolean own_ref) { PyGILState_STATE state; PyGBoxed *self; PyTypeObject *tp; g_return_val_if_fail (boxed_type != 0, NULL); g_return_val_if_fail (!copy_boxed || (copy_boxed && own_ref), NULL); state = PyGILState_Ensure (); if (!boxed) { Py_INCREF (Py_None); PyGILState_Release (state); return Py_None; } tp = g_type_get_qdata (boxed_type, pygboxed_type_key); if (!tp) tp = (PyTypeObject *)pygi_type_import_by_g_type (boxed_type); if (!tp) tp = (PyTypeObject *)&PyGBoxed_Type; /* fallback */ if (!PyType_IsSubtype (tp, &PyGBoxed_Type)) { PyErr_Format (PyExc_RuntimeError, "%s isn't a GBoxed", tp->tp_name); PyGILState_Release (state); return NULL; } self = (PyGBoxed *)tp->tp_alloc (tp, 0); if (self == NULL) { PyGILState_Release (state); return NULL; } if (copy_boxed) boxed = g_boxed_copy (boxed_type, boxed); pyg_boxed_set_ptr (self, boxed); self->gtype = boxed_type; self->free_on_dealloc = own_ref; PyGILState_Release (state); return (PyObject *)self; } /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_gboxed_register_types (PyObject *d) { PyObject *pygtype; pygboxed_type_key = g_quark_from_static_string ("PyGBoxed::class"); PyGBoxed_Type.tp_dealloc = (destructor)gboxed_dealloc; PyGBoxed_Type.tp_richcompare = gboxed_richcompare; PyGBoxed_Type.tp_repr = (reprfunc)gboxed_repr; PyGBoxed_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; PyGBoxed_Type.tp_methods = pygboxed_methods; PyGBoxed_Type.tp_init = (initproc)gboxed_init; PyGBoxed_Type.tp_free = (freefunc)gboxed_free; PyGBoxed_Type.tp_hash = (hashfunc)gboxed_hash; PyGBoxed_Type.tp_alloc = PyType_GenericAlloc; PyGBoxed_Type.tp_new = PyType_GenericNew; if (PyType_Ready (&PyGBoxed_Type)) return -1; pygtype = pyg_type_wrapper_new (G_TYPE_POINTER); PyDict_SetItemString (PyGBoxed_Type.tp_dict, "__gtype__", pygtype); Py_DECREF (pygtype); PyDict_SetItemString (d, "GBoxed", (PyObject *)&PyGBoxed_Type); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygboxed.h0000664000000000000000000000245315074673150014743 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGOBJECT_BOXED_H__ #define __PYGOBJECT_BOXED_H__ extern GQuark pygboxed_type_key; extern PyTypeObject PyGBoxed_Type; void pygi_register_gboxed (PyObject *dict, const gchar *class_name, GType boxed_type, PyTypeObject *type); PyObject *pygi_gboxed_new (GType boxed_type, gpointer boxed, gboolean copy_boxed, gboolean own_ref); int pygi_gboxed_register_types (PyObject *d); #endif /* __PYGOBJECT_BOXED_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygenum.c0000664000000000000000000003460115074673150014601 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * Copyright (C) 2004 Johan Dahlin * * pygenum.c: GEnum wrapper * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-type.h" #include "pygenum.h" #include "pygi-basictype.h" #include "pygi-util.h" GQuark pygenum_class_key; PyTypeObject *PyGEnum_Type; static PyObject *IntEnum_Type; PyObject * pyg_enum_val_new (PyObject *pyclass, int value) { PyObject *retval, *intvalue; PyObject *args[2] = { NULL }; intvalue = PyLong_FromLong (value); if (!intvalue) return NULL; args[1] = intvalue; retval = PyObject_Vectorcall (pyclass, &args[1], 1 + PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); if (!retval && PyErr_ExceptionMatches (PyExc_ValueError)) { PyErr_Clear (); return intvalue; } Py_DECREF (intvalue); return retval; } PyObject * pyg_enum_from_gtype (GType gtype, int value) { PyObject *pyclass; g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL); /* Get a wrapper class by: * 1. check for one attached to the gtype * 2. lookup one in a typelib * 3. creating a new one */ pyclass = (PyObject *)g_type_get_qdata (gtype, pygenum_class_key); if (!pyclass) pyclass = pygi_type_import_by_g_type (gtype); if (!pyclass) pyclass = pyg_enum_add (NULL, g_type_name (gtype), NULL, gtype); if (!pyclass) return PyLong_FromLong (value); return pyg_enum_val_new (pyclass, value); } static void add_value (PyObject *dict, const char *value_nick, int value) { char *upper = g_ascii_strup (value_nick, -1); char *c; PyObject *v; for (c = upper; *c != '\0'; c++) { if (*c == '-') *c = '_'; } /* skip if the name already exists in the dictionary */ if (PyMapping_HasKeyString (dict, upper)) { g_free (upper); return; } v = PyLong_FromLong (value); PyMapping_SetItemString (dict, upper, v); Py_DECREF (v); g_free (upper); } PyObject * pyg_enum_add_full (PyObject *module, const char *typename, GType gtype, GIEnumInfo *info) { PyObject *stub; PyObject *base_class, *method_name, *enum_name, *bases, *values; PyObject *args[4] = { NULL }; if (gtype == G_TYPE_NONE && info == NULL) { PyErr_SetString (PyExc_ValueError, "cannot create enum without a GType or EnumInfo"); return NULL; } if (gtype != G_TYPE_NONE && !g_type_is_a (gtype, G_TYPE_ENUM)) { PyErr_Format (PyExc_TypeError, "Trying to register gtype '%s' as enum when in fact it " "is of type '%s'", g_type_name (gtype), g_type_name (G_TYPE_FUNDAMENTAL (gtype))); return NULL; } if (info != NULL) { GType info_gtype = gi_registered_type_info_get_g_type ( GI_REGISTERED_TYPE_INFO (info)); if (info_gtype != gtype) { PyErr_Format (PyExc_ValueError, "gtype '%s' does not match EnumInfo '%s'", g_type_name (gtype), gi_base_info_get_name (GI_BASE_INFO (info))); return NULL; } } if (gtype == G_TYPE_NONE) base_class = IntEnum_Type; else base_class = (PyObject *)PyGEnum_Type; enum_name = PyUnicode_FromString (typename); bases = PyTuple_New (1); PyTuple_SET_ITEM (bases, 0, Py_NewRef (base_class)); args[0] = (PyObject *)Py_TYPE (base_class); args[1] = enum_name; args[2] = bases; method_name = PyUnicode_FromString ("__prepare__"); values = PyObject_VectorcallMethod ( method_name, args, 3 + PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); Py_DECREF (method_name); if (!values) { Py_DECREF (enum_name); Py_DECREF (bases); return NULL; } /* Collect values from registered GType */ if (gtype != G_TYPE_NONE) { GEnumClass *eclass; unsigned int i; eclass = G_ENUM_CLASS (g_type_class_ref (gtype)); for (i = 0; i < eclass->n_values; i++) { add_value (values, eclass->values[i].value_nick, eclass->values[i].value); } g_type_class_unref (eclass); } /* Collect values from GIEnumInfo (which may include additional aliases) */ if (info != NULL) { unsigned int i, length; length = gi_enum_info_get_n_values (info); for (i = 0; i < length; i++) { GIValueInfo *v = gi_enum_info_get_value (info, i); add_value (values, gi_base_info_get_name (GI_BASE_INFO (v)), gi_value_info_get_value (v)); } } if (module && !Py_IsNone (module)) { PyObject *module_name = PyModule_GetNameObject (module); PyMapping_SetItemString (values, "__module__", module_name); Py_DECREF (module_name); } if (gtype != G_TYPE_NONE) { PyObject *o = pyg_type_wrapper_new (gtype); PyMapping_SetItemString (values, "__gtype__", o); Py_DECREF (o); } args[3] = values; stub = PyObject_Vectorcall ((PyObject *)Py_TYPE (base_class), &args[1], 3 + PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); Py_DECREF (values); Py_DECREF (bases); Py_DECREF (enum_name); if (!stub) return NULL; ((PyTypeObject *)stub)->tp_flags &= ~Py_TPFLAGS_BASETYPE; if (gtype != G_TYPE_NONE) { g_type_set_qdata (gtype, pygenum_class_key, stub); } return stub; } /* * pyg_enum_add * Dynamically create a class derived from PyGEnum based on the given GType. */ PyObject * pyg_enum_add (PyObject *module, const char *typename, const char *strip_prefix, GType gtype) { PyGILState_STATE state; PyObject *stub; g_return_val_if_fail (typename != NULL, NULL); if (!g_type_is_a (gtype, G_TYPE_ENUM)) { PyErr_Format (PyExc_TypeError, "Trying to register gtype '%s' as enum when in fact it " "is of type '%s'", g_type_name (gtype), g_type_name (G_TYPE_FUNDAMENTAL (gtype))); return NULL; } state = PyGILState_Ensure (); stub = pyg_enum_add_full (module, typename, gtype, NULL); if (!stub) { PyGILState_Release (state); return NULL; } if (module) { GEnumClass *eclass; guint i; /* Add it to the module name space */ PyModule_AddObject (module, (char *)typename, stub); Py_INCREF (stub); /* Register enum values */ eclass = G_ENUM_CLASS (g_type_class_ref (gtype)); for (i = 0; i < eclass->n_values; i++) { PyObject *item, *intval; PyObject *args[2] = { NULL }; char *prefix; intval = PyLong_FromLong (eclass->values[i].value); args[1] = intval; item = PyObject_Vectorcall ( stub, &args[1], 1 + PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); Py_DECREF (intval); prefix = g_strdup (pyg_constant_strip_prefix ( eclass->values[i].value_name, strip_prefix)); PyModule_AddObject (module, prefix, item); g_free (prefix); } g_type_class_unref (eclass); } PyGILState_Release (state); return stub; } gboolean pyg_enum_register (PyTypeObject *enum_class, char *type_name) { gboolean result = FALSE; GType gtype = G_TYPE_INVALID; GEnumValue *enum_values = NULL; PyObject *values = NULL, *pygtype = NULL; Py_ssize_t length, i; values = PySequence_List ((PyObject *)enum_class); if (!values) goto out; length = PyList_Size (values); enum_values = g_new0 (GEnumValue, length + 1); for (i = 0; i < length; i++) { PyObject *value = PyList_GetItem (values, i); PyObject *name = PyObject_GetAttrString (value, "name"); char *c; if (!name) { goto out; } if (!PyUnicode_Check (name)) { PyErr_SetString (PyExc_TypeError, "enum value names should be strings"); Py_DECREF (name); goto out; } enum_values[i].value = PyLong_AsLong (value); enum_values[i].value_name = g_strdup (PyUnicode_AsUTF8AndSize (name, NULL)); c = g_ascii_strdown (enum_values[i].value_name, -1); enum_values[i].value_nick = c; while (*c != '\0') { if (*c == '_') *c = '-'; c++; } Py_DECREF (name); } gtype = g_enum_register_static (type_name, enum_values); if (gtype == G_TYPE_INVALID) { PyErr_Format (PyExc_RuntimeError, "Unable to register enum '%s'", type_name); goto out; } g_type_set_qdata (gtype, pygenum_class_key, enum_class); pygtype = pyg_type_wrapper_new (gtype); if (!pygtype) goto out; PyObject_SetAttrString ((PyObject *)enum_class, "__gtype__", pygtype); result = TRUE; out: Py_XDECREF (pygtype); Py_XDECREF (values); /* If type registration succeeded, this data should not be freed */ if (gtype == G_TYPE_INVALID) { g_free (type_name); if (enum_values != NULL) { GEnumValue *v; for (v = enum_values; v->value_name != NULL; v++) { g_free ((char *)v->value_name); g_free ((char *)v->value_nick); } g_free (enum_values); } } return result; } static GType get_enum_gtype (PyTypeObject *type) { PyObject *pytc; GType gtype; pytc = PyObject_GetAttrString ((PyObject *)type, "__gtype__"); if (!pytc) return G_TYPE_INVALID; if (!PyObject_TypeCheck (pytc, &PyGTypeWrapper_Type)) { Py_DECREF (pytc); PyErr_SetString (PyExc_TypeError, "__gtype__ attribute not a typecode"); return G_TYPE_INVALID; } gtype = pyg_type_from_object (pytc); Py_DECREF (pytc); if (!G_TYPE_IS_ENUM (gtype)) { PyErr_SetString (PyExc_TypeError, "__gtype__ attribute not an enum typecode"); return G_TYPE_INVALID; } return gtype; } static PyObject * pyg_enum_get_value_name (PyObject *self, void *closure) { GType gtype; GEnumClass *enum_class; GEnumValue *enum_value; PyObject *retval; gint intvalue; if (!pygi_gint_from_py ((PyObject *)self, &intvalue)) return NULL; gtype = get_enum_gtype (Py_TYPE (self)); if (gtype == G_TYPE_INVALID) return NULL; enum_class = g_type_class_ref (gtype); g_assert (G_IS_ENUM_CLASS (enum_class)); enum_value = g_enum_get_value (enum_class, intvalue); if (enum_value == NULL) { PyErr_Format (PyExc_ValueError, "no GEnumValue found for %d", intvalue); g_type_class_unref (enum_class); return NULL; } retval = pygi_utf8_to_py (enum_value->value_name); g_type_class_unref (enum_class); return retval; } static PyObject * pyg_enum_get_value_nick (PyObject *self, void *closure) { GType gtype; GEnumClass *enum_class; GEnumValue *enum_value; PyObject *retval; gint intvalue; if (!pygi_gint_from_py ((PyObject *)self, &intvalue)) return NULL; gtype = get_enum_gtype (Py_TYPE (self)); if (gtype == G_TYPE_INVALID) return NULL; enum_class = g_type_class_ref (gtype); g_assert (G_IS_ENUM_CLASS (enum_class)); enum_value = g_enum_get_value (enum_class, intvalue); if (enum_value == NULL) { PyErr_Format (PyExc_ValueError, "no GEnumValue found for %d", intvalue); g_type_class_unref (enum_class); return NULL; } retval = pygi_utf8_to_py (enum_value->value_nick); g_type_class_unref (enum_class); return retval; } int pyg_enum_check_type (PyObject *obj, GType expected_type) { GType gtype; if (expected_type == G_TYPE_NONE) return 0; /* Only match the GType if this is a PyGEnum_Type subclass */ if (!PyObject_TypeCheck (obj, PyGEnum_Type)) return 0; gtype = get_enum_gtype (Py_TYPE (obj)); if (gtype == G_TYPE_INVALID) return -1; if (gtype != expected_type) { PyErr_Format (PyExc_TypeError, "expected enumeration type %s, but got %s instead", g_type_name (expected_type), g_type_name (gtype)); return -1; } return 0; } static PyGetSetDef pyg_enum_getsets[] = { { "value_name", (getter)pyg_enum_get_value_name, (setter)0 }, { "value_nick", (getter)pyg_enum_get_value_nick, (setter)0 }, { NULL, 0, 0 }, }; /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_enum_register_types (PyObject *mod) { PyObject *enum_module, *item; int i; pygenum_class_key = g_quark_from_static_string ("PyGEnum::class"); enum_module = PyImport_ImportModule ("enum"); if (!enum_module) return -1; IntEnum_Type = PyObject_GetAttrString (enum_module, "IntEnum"); Py_DECREF (enum_module); if (!IntEnum_Type) return -1; enum_module = PyImport_ImportModule ("gi._enum"); if (!enum_module) return -1; PyGEnum_Type = (PyTypeObject *)PyObject_GetAttrString (enum_module, "GEnum"); Py_DECREF (enum_module); if (!PyGEnum_Type) return -1; item = pyg_type_wrapper_new (G_TYPE_ENUM); PyObject_SetAttrString ((PyObject *)PyGEnum_Type, "__gtype__", item); Py_DECREF (item); for (i = 0; pyg_enum_getsets[i].name != NULL; i++) { item = PyDescr_NewGetSet (PyGEnum_Type, &pyg_enum_getsets[i]); PyObject_SetAttrString ((PyObject *)PyGEnum_Type, pyg_enum_getsets[i].name, item); Py_DECREF (item); } PyModule_AddObject (mod, "GEnum", Py_NewRef ((PyObject *)PyGEnum_Type)); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygenum.h0000664000000000000000000000331115074673150014600 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGOBJECT_ENUM_H__ #define __PYGOBJECT_ENUM_H__ #include #include #include extern GQuark pygenum_class_key; extern PyTypeObject *PyGEnum_Type; PyObject *pyg_enum_add (PyObject *module, const char *type_name, const char *strip_prefix, GType gtype); PyObject *pyg_enum_add_full (PyObject *module, const char *typename, GType gtype, GIEnumInfo *info); gboolean pyg_enum_register (PyTypeObject *enum_class, char *type_name); PyObject *pyg_enum_val_new (PyObject *pyclass, int value); PyObject *pyg_enum_from_gtype (GType gtype, int value); int pyg_enum_check_type (PyObject *obj, GType expected_type); gint pyg_enum_get_value (GType enum_type, PyObject *obj, gint *val); int pygi_enum_register_types (PyObject *mod); #endif /* __PYGOBJECT_ENUM_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygflags.c0000664000000000000000000003663715074673150014744 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * Copyright (C) 2004 Johan Dahlin * * pygflags.c: GFlags wrapper * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-type.h" #include "pygflags.h" #include "pygi-util.h" GQuark pygflags_class_key; PyTypeObject *PyGFlags_Type; static PyObject *IntFlag_Type; PyObject * pyg_flags_val_new (PyObject *pyclass, guint value) { PyObject *retval, *intvalue; PyObject *args[2] = { NULL }; intvalue = PyLong_FromUnsignedLong (value); if (!intvalue) return NULL; args[1] = intvalue; retval = PyObject_Vectorcall (pyclass, &args[1], 1 + PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); if (!retval && PyErr_ExceptionMatches (PyExc_ValueError)) { PyErr_Clear (); return intvalue; } Py_DECREF (intvalue); return retval; } PyObject * pyg_flags_from_gtype (GType gtype, guint value) { PyObject *pyclass; g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL); /* Get a wrapper class by: * 1. check for one attached to the gtype * 2. lookup one in a typelib * 3. creating a new one */ pyclass = (PyObject *)g_type_get_qdata (gtype, pygflags_class_key); if (!pyclass) pyclass = pygi_type_import_by_g_type (gtype); if (!pyclass) pyclass = pyg_flags_add (NULL, g_type_name (gtype), NULL, gtype); if (!pyclass) return PyLong_FromUnsignedLong (value); return pyg_flags_val_new (pyclass, value); } static void add_value (PyObject *dict, const char *value_nick, unsigned int value) { char *upper = g_ascii_strup (value_nick, -1); char *c; PyObject *v; for (c = upper; *c != '\0'; c++) { if (*c == '-') *c = '_'; } /* skip if the name already exists in the dictionary */ if (PyMapping_HasKeyString (dict, upper)) { g_free (upper); return; } v = PyLong_FromUnsignedLong (value); PyMapping_SetItemString (dict, upper, v); Py_DECREF (v); g_free (upper); } PyObject * pyg_flags_add_full (PyObject *module, const char *typename, GType gtype, GIFlagsInfo *info) { PyObject *stub; PyObject *base_class, *method_name, *flags_name, *bases, *values; PyObject *args[4] = { NULL }; if (gtype == G_TYPE_NONE && info == NULL) { PyErr_SetString (PyExc_ValueError, "cannot create enum without a GType or EnumInfo"); return NULL; } if (gtype != G_TYPE_NONE && !g_type_is_a (gtype, G_TYPE_FLAGS)) { PyErr_Format (PyExc_TypeError, "Trying to register gtype '%s' as flags when in fact it " "is of type '%s'", g_type_name (gtype), g_type_name (G_TYPE_FUNDAMENTAL (gtype))); return NULL; } if (info != NULL) { GType info_gtype = gi_registered_type_info_get_g_type ( GI_REGISTERED_TYPE_INFO (info)); if (info_gtype != gtype) { PyErr_Format (PyExc_ValueError, "gtype '%s' does not match FlagsInfo '%s'", g_type_name (gtype), gi_base_info_get_name (GI_BASE_INFO (info))); return NULL; } } if (gtype == G_TYPE_NONE) base_class = IntFlag_Type; else base_class = (PyObject *)PyGFlags_Type; flags_name = PyUnicode_FromString (typename); bases = PyTuple_New (1); PyTuple_SET_ITEM (bases, 0, Py_NewRef (base_class)); args[0] = (PyObject *)Py_TYPE (base_class); args[1] = flags_name; args[2] = bases; method_name = PyUnicode_FromString ("__prepare__"); values = PyObject_VectorcallMethod ( method_name, args, 3 + PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); Py_DECREF (method_name); if (!values) { Py_DECREF (flags_name); Py_DECREF (bases); return NULL; } /* Collect values from registered GType */ if (gtype != G_TYPE_NONE) { GFlagsClass *fclass; unsigned int i; fclass = G_FLAGS_CLASS (g_type_class_ref (gtype)); for (i = 0; i < fclass->n_values; i++) { add_value (values, fclass->values[i].value_nick, fclass->values[i].value); } g_type_class_unref (fclass); } /* Collect values from GIFlagsInfo (which may include additional aliases) */ if (info != NULL) { unsigned int i, length; length = gi_enum_info_get_n_values (GI_ENUM_INFO (info)); for (i = 0; i < length; i++) { GIValueInfo *v = gi_enum_info_get_value (GI_ENUM_INFO (info), i); add_value (values, gi_base_info_get_name (GI_BASE_INFO (v)), gi_value_info_get_value (v)); } } if (module && !Py_IsNone (module)) { PyObject *module_name = PyModule_GetNameObject (module); PyMapping_SetItemString (values, "__module__", module_name); Py_DECREF (module_name); } if (gtype != G_TYPE_NONE) { PyObject *o = pyg_type_wrapper_new (gtype); PyMapping_SetItemString (values, "__gtype__", o); Py_DECREF (o); } args[3] = values; stub = PyObject_Vectorcall ((PyObject *)Py_TYPE (base_class), &args[1], 3 + PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); Py_DECREF (values); Py_DECREF (bases); Py_DECREF (flags_name); if (!stub) return NULL; ((PyTypeObject *)stub)->tp_flags &= ~Py_TPFLAGS_BASETYPE; if (gtype != G_TYPE_NONE) { g_type_set_qdata (gtype, pygflags_class_key, stub); } return stub; } /* * pyg_flags_add * Dynamically create a class derived from PyGFlags based on the given GType. */ PyObject * pyg_flags_add (PyObject *module, const char *typename, const char *strip_prefix, GType gtype) { PyGILState_STATE state; PyObject *stub; g_return_val_if_fail (typename != NULL, NULL); if (!g_type_is_a (gtype, G_TYPE_FLAGS)) { g_warning ( "Trying to register gtype '%s' as flags when in fact it is of " "type '%s'", g_type_name (gtype), g_type_name (G_TYPE_FUNDAMENTAL (gtype))); return NULL; } state = PyGILState_Ensure (); stub = pyg_flags_add_full (module, typename, gtype, NULL); if (!stub) { PyGILState_Release (state); return NULL; } if (module) { GFlagsClass *fclass; guint i; /* Add it to the module name space */ PyModule_AddObject (module, (char *)typename, stub); Py_INCREF (stub); /* Register flags values */ fclass = G_FLAGS_CLASS (g_type_class_ref (gtype)); for (i = 0; i < fclass->n_values; i++) { PyObject *item, *intval; PyObject *args[2] = { NULL }; char *prefix; intval = PyLong_FromUnsignedLong (fclass->values[i].value); args[1] = intval; item = PyObject_Vectorcall ( stub, &args[1], 1 + PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); Py_DECREF (intval); prefix = g_strdup (pyg_constant_strip_prefix ( fclass->values[i].value_name, strip_prefix)); PyModule_AddObject (module, prefix, item); g_free (prefix); } g_type_class_unref (fclass); } PyGILState_Release (state); return stub; } gboolean pyg_flags_register (PyTypeObject *flags_class, char *type_name) { gboolean result = FALSE; GType gtype = G_TYPE_INVALID; GFlagsValue *flags_values = NULL; PyObject *values = NULL, *pygtype = NULL; Py_ssize_t length, i; values = PySequence_List ((PyObject *)flags_class); if (!values) goto out; length = PyList_Size (values); flags_values = g_new0 (GFlagsValue, length + 1); for (i = 0; i < length; i++) { PyObject *value = PyList_GetItem (values, i); PyObject *name = PyObject_GetAttrString (value, "name"); char *c; if (!name) { goto out; } if (!PyUnicode_Check (name)) { PyErr_SetString (PyExc_TypeError, "flags value names should be strings"); Py_DECREF (name); goto out; } flags_values[i].value = PyLong_AsUnsignedLongMask (value); flags_values[i].value_name = g_strdup (PyUnicode_AsUTF8AndSize (name, NULL)); c = g_ascii_strdown (flags_values[i].value_name, -1); flags_values[i].value_nick = c; while (*c != '\0') { if (*c == '_') *c = '-'; c++; } Py_DECREF (name); } gtype = g_flags_register_static (type_name, flags_values); if (gtype == G_TYPE_INVALID) { PyErr_Format (PyExc_RuntimeError, "Unable to register flags '%s'", type_name); goto out; } g_type_set_qdata (gtype, pygflags_class_key, flags_class); pygtype = pyg_type_wrapper_new (gtype); if (!pygtype) goto out; PyObject_SetAttrString ((PyObject *)flags_class, "__gtype__", pygtype); result = TRUE; out: Py_XDECREF (values); Py_XDECREF (pygtype); /* If type registration succeeded, this data should not be freed */ if (gtype == G_TYPE_INVALID) { g_free (type_name); if (flags_values != NULL) { GFlagsValue *v; for (v = flags_values; v->value_name != NULL; v++) { g_free ((char *)v->value_name); g_free ((char *)v->value_nick); } g_free (flags_values); } } return result; } static GType get_flags_gtype (PyTypeObject *type) { PyObject *pytc; GType gtype; pytc = PyObject_GetAttrString ((PyObject *)type, "__gtype__"); if (!pytc) return G_TYPE_INVALID; if (!PyObject_TypeCheck (pytc, &PyGTypeWrapper_Type)) { Py_DECREF (pytc); PyErr_SetString (PyExc_TypeError, "__gtype__ attribute not a typecode"); return G_TYPE_INVALID; } gtype = pyg_type_from_object (pytc); Py_DECREF (pytc); if (!G_TYPE_IS_FLAGS (gtype)) { PyErr_SetString (PyExc_TypeError, "__gtype__ attribute not a flags typecode"); return G_TYPE_INVALID; } return gtype; } static PyObject * pyg_flags_get_first_value_name (PyObject *self, void *closure) { GType gtype; GFlagsClass *flags_class; GFlagsValue *flags_value; PyObject *retval; gtype = get_flags_gtype (Py_TYPE (self)); if (gtype == G_TYPE_INVALID) return NULL; flags_class = g_type_class_ref (gtype); g_assert (G_IS_FLAGS_CLASS (flags_class)); flags_value = g_flags_get_first_value ( flags_class, (guint)PyLong_AsUnsignedLongMask ((PyObject *)self)); if (flags_value) retval = PyUnicode_FromString (flags_value->value_name); else { retval = Py_NewRef (Py_None); } g_type_class_unref (flags_class); return retval; } static PyObject * pyg_flags_get_first_value_nick (PyObject *self, void *closure) { GType gtype; GFlagsClass *flags_class; GFlagsValue *flags_value; PyObject *retval; gtype = get_flags_gtype (Py_TYPE (self)); if (gtype == G_TYPE_INVALID) return NULL; flags_class = g_type_class_ref (gtype); g_assert (G_IS_FLAGS_CLASS (flags_class)); flags_value = g_flags_get_first_value ( flags_class, (guint)PyLong_AsUnsignedLongMask ((PyObject *)self)); if (flags_value) retval = PyUnicode_FromString (flags_value->value_nick); else { retval = Py_NewRef (Py_None); } g_type_class_unref (flags_class); return retval; } static PyObject * pyg_flags_get_value_names (PyObject *self, void *closure) { GType gtype; GFlagsClass *flags_class; PyObject *retval; guint i; gtype = get_flags_gtype (Py_TYPE (self)); if (gtype == G_TYPE_INVALID) return NULL; flags_class = g_type_class_ref (gtype); g_assert (G_IS_FLAGS_CLASS (flags_class)); retval = PyList_New (0); for (i = 0; i < flags_class->n_values; i++) { PyObject *value_name; if ((PyLong_AsUnsignedLongMask ((PyObject *)self) & flags_class->values[i].value) == flags_class->values[i].value) { value_name = PyUnicode_FromString (flags_class->values[i].value_name); PyList_Append (retval, value_name); Py_DECREF (value_name); } } g_type_class_unref (flags_class); return retval; } static PyObject * pyg_flags_get_value_nicks (PyObject *self, void *closure) { GType gtype; GFlagsClass *flags_class; PyObject *retval; guint i; gtype = get_flags_gtype (Py_TYPE (self)); if (gtype == G_TYPE_INVALID) return NULL; flags_class = g_type_class_ref (gtype); g_assert (G_IS_FLAGS_CLASS (flags_class)); retval = PyList_New (0); for (i = 0; i < flags_class->n_values; i++) if ((PyLong_AsUnsignedLongMask ((PyObject *)self) & flags_class->values[i].value) == flags_class->values[i].value) { PyObject *py_nick = PyUnicode_FromString (flags_class->values[i].value_nick); PyList_Append (retval, py_nick); Py_DECREF (py_nick); } g_type_class_unref (flags_class); return retval; } static PyGetSetDef pyg_flags_getsets[] = { { "first_value_name", (getter)pyg_flags_get_first_value_name, (setter)0 }, { "first_value_nick", (getter)pyg_flags_get_first_value_nick, (setter)0 }, { "value_names", (getter)pyg_flags_get_value_names, (setter)0 }, { "value_nicks", (getter)pyg_flags_get_value_nicks, (setter)0 }, { NULL, 0, 0 }, }; /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_flags_register_types (PyObject *mod) { PyObject *enum_module, *item; int i; pygflags_class_key = g_quark_from_static_string ("PyGFlags::class"); enum_module = PyImport_ImportModule ("enum"); if (!enum_module) return -1; IntFlag_Type = PyObject_GetAttrString (enum_module, "IntFlag"); Py_DECREF (enum_module); if (!IntFlag_Type) return -1; enum_module = PyImport_ImportModule ("gi._enum"); if (!enum_module) return -1; PyGFlags_Type = (PyTypeObject *)PyObject_GetAttrString (enum_module, "GFlags"); Py_DECREF (enum_module); if (!PyGFlags_Type) return -1; item = pyg_type_wrapper_new (G_TYPE_FLAGS); PyObject_SetAttrString ((PyObject *)PyGFlags_Type, "__gtype__", item); Py_DECREF (item); for (i = 0; pyg_flags_getsets[i].name != NULL; i++) { item = PyDescr_NewGetSet (PyGFlags_Type, &pyg_flags_getsets[i]); PyObject_SetAttrString ((PyObject *)PyGFlags_Type, pyg_flags_getsets[i].name, item); Py_DECREF (item); } PyModule_AddObject (mod, "GFlags", Py_NewRef ((PyObject *)PyGFlags_Type)); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygflags.h0000664000000000000000000000323115074673150014731 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGOBJECT_FLAGS_H__ #define __PYGOBJECT_FLAGS_H__ #include #include #include extern GQuark pygflags_class_key; extern PyTypeObject *PyGFlags_Type; PyObject *pyg_flags_add (PyObject *module, const char *type_name, const char *strip_prefix, GType gtype); PyObject *pyg_flags_add_full (PyObject *module, const char *typename, GType gtype, GIFlagsInfo *info); gboolean pyg_flags_register (PyTypeObject *flags_class, char *type_name); PyObject *pyg_flags_val_new (PyObject *pyclass, guint value); PyObject *pyg_flags_from_gtype (GType gtype, guint value); gint pyg_flags_get_value (GType flag_type, PyObject *obj, guint *val); int pygi_flags_register_types (PyObject *d); #endif /* __PYGOBJECT_FLAGS_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-argument.c0000664000000000000000000012023415074673150015703 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2005-2009 Johan Dahlin * * pygi-argument.c: GIArgument - PyObject conversion functions. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygobject-internal.h" #include #include #include #include "pygi-type.h" #include "pygi-argument.h" #include "pygi-basictype.h" #include "pygi-error.h" #include "pygi-foreign.h" #include "pygi-info.h" #include "pygi-object.h" #include "pygi-struct-marshal.h" #include "pygi-util.h" #include "pygi-value.h" gboolean pygi_argument_to_gssize (GIArgument *arg_in, GITypeTag type_tag, gssize *gssize_out) { switch (type_tag) { case GI_TYPE_TAG_INT8: *gssize_out = arg_in->v_int8; return TRUE; case GI_TYPE_TAG_UINT8: *gssize_out = arg_in->v_uint8; return TRUE; case GI_TYPE_TAG_INT16: *gssize_out = arg_in->v_int16; return TRUE; case GI_TYPE_TAG_UINT16: *gssize_out = arg_in->v_uint16; return TRUE; case GI_TYPE_TAG_INT32: *gssize_out = arg_in->v_int32; return TRUE; case GI_TYPE_TAG_UINT32: *gssize_out = arg_in->v_uint32; return TRUE; case GI_TYPE_TAG_INT64: if (arg_in->v_int64 > G_MAXSSIZE || arg_in->v_int64 < G_MINSSIZE) { PyErr_Format (PyExc_TypeError, "Unable to marshal %s to gssize", gi_type_tag_to_string (type_tag)); return FALSE; } *gssize_out = (gssize)arg_in->v_int64; return TRUE; case GI_TYPE_TAG_UINT64: if (arg_in->v_uint64 > G_MAXSSIZE) { PyErr_Format (PyExc_TypeError, "Unable to marshal %s to gssize", gi_type_tag_to_string (type_tag)); return FALSE; } *gssize_out = (gssize)arg_in->v_uint64; return TRUE; default: PyErr_Format (PyExc_TypeError, "Unable to marshal %s to gssize", gi_type_tag_to_string (type_tag)); return FALSE; } } static GITypeTag _pygi_get_storage_type (GITypeInfo *type_info) { GITypeTag type_tag = gi_type_info_get_tag (type_info); if (type_tag == GI_TYPE_TAG_INTERFACE) { GIBaseInfo *interface = gi_type_info_get_interface (type_info); if (GI_IS_ENUM_INFO (interface)) type_tag = gi_enum_info_get_storage_type ((GIEnumInfo *)interface); else /* FIXME: we might have something to do for other types */ gi_base_info_unref (interface); } return type_tag; } void _pygi_hash_pointer_to_arg (GIArgument *arg, GITypeInfo *type_info) { GITypeTag type_tag = _pygi_get_storage_type (type_info); switch (type_tag) { case GI_TYPE_TAG_INT8: arg->v_int8 = (gint8)GPOINTER_TO_INT (arg->v_pointer); break; case GI_TYPE_TAG_INT16: arg->v_int16 = (gint16)GPOINTER_TO_INT (arg->v_pointer); break; case GI_TYPE_TAG_INT32: arg->v_int32 = (gint32)GPOINTER_TO_INT (arg->v_pointer); break; case GI_TYPE_TAG_UINT8: arg->v_uint8 = (guint8)GPOINTER_TO_UINT (arg->v_pointer); break; case GI_TYPE_TAG_UINT16: arg->v_uint16 = (guint16)GPOINTER_TO_UINT (arg->v_pointer); break; case GI_TYPE_TAG_UINT32: arg->v_uint32 = (guint32)GPOINTER_TO_UINT (arg->v_pointer); break; case GI_TYPE_TAG_GTYPE: arg->v_size = GPOINTER_TO_SIZE (arg->v_pointer); break; case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_INTERFACE: case GI_TYPE_TAG_ARRAY: break; default: g_critical ("Unsupported type %s", gi_type_tag_to_string (type_tag)); } } gpointer _pygi_arg_to_hash_pointer (const GIArgument *arg, GITypeInfo *type_info) { GITypeTag type_tag = _pygi_get_storage_type (type_info); switch (type_tag) { case GI_TYPE_TAG_INT8: return GINT_TO_POINTER (arg->v_int8); case GI_TYPE_TAG_UINT8: return GINT_TO_POINTER (arg->v_uint8); case GI_TYPE_TAG_INT16: return GINT_TO_POINTER (arg->v_int16); case GI_TYPE_TAG_UINT16: return GINT_TO_POINTER (arg->v_uint16); case GI_TYPE_TAG_INT32: return GINT_TO_POINTER (arg->v_int32); case GI_TYPE_TAG_UINT32: return GINT_TO_POINTER (arg->v_uint32); case GI_TYPE_TAG_GTYPE: return GSIZE_TO_POINTER (arg->v_size); case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_INTERFACE: case GI_TYPE_TAG_ARRAY: return arg->v_pointer; default: g_critical ("Unsupported type %s", gi_type_tag_to_string (type_tag)); return arg->v_pointer; } } /** * _pygi_argument_array_length_marshal: * @length_arg_index: Index of length argument in the callables args list. * @user_data1: (type Array(GValue)): Array of GValue arguments to retrieve length * @user_data2: (type GICallableInfo): Callable info to get the argument from. * * Generic marshalling policy for array length arguments in callables. * * Returns: The length of the array or -1 on failure. */ gssize _pygi_argument_array_length_marshal (gsize length_arg_index, void *user_data1, void *user_data2) { GIArgInfo length_arg_info; GITypeInfo length_type_info; GIArgument length_arg; gssize array_len = -1; GValue *values = (GValue *)user_data1; GICallableInfo *callable_info = (GICallableInfo *)user_data2; gi_callable_info_load_arg (callable_info, (gint)length_arg_index, &length_arg_info); gi_arg_info_load_type_info (&length_arg_info, &length_type_info); length_arg = _pygi_argument_from_g_value (&(values[length_arg_index]), &length_type_info); if (!pygi_argument_to_gssize (&length_arg, gi_type_info_get_tag (&length_type_info), &array_len)) { return -1; } return array_len; } /** * _pygi_argument_to_array * @arg: The argument to convert * @array_length_policy: Closure for marshalling the array length argument when needed. * @user_data1: Generic user data passed to the array_length_policy. * @user_data2: Generic user data passed to the array_length_policy. * @type_info: The type info for @arg * @out_free_array: A return location for a gboolean that indicates whether * or not the wrapped GArray should be freed * * Make sure an array type argument is wrapped in a GArray. * * Note: This method can *not* be folded into _pygi_argument_to_object() because * arrays are special in the sense that they might require access to @args in * order to get the length. * * Returns: A GArray wrapping @arg. If @out_free_array has been set to TRUE then * free the array with g_array_free() without freeing the data members. * Otherwise don't free the array. */ GArray * _pygi_argument_to_array (GIArgument *arg, PyGIArgArrayLengthPolicy array_length_policy, void *user_data1, void *user_data2, GITypeInfo *type_info, gboolean *out_free_array) { GITypeInfo *item_type_info; gboolean is_zero_terminated; gsize item_size; size_t length; gssize length_policy; GArray *g_array; g_return_val_if_fail ( gi_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY, NULL); if (arg->v_pointer == NULL) { return NULL; } switch (gi_type_info_get_array_type (type_info)) { case GI_ARRAY_TYPE_C: is_zero_terminated = gi_type_info_is_zero_terminated (type_info); item_type_info = gi_type_info_get_param_type (type_info, 0); item_size = _pygi_gi_type_info_size (item_type_info); gi_base_info_unref ((GIBaseInfo *)item_type_info); if (is_zero_terminated) { if (item_size == sizeof (gpointer)) length = g_strv_length ((gchar **)arg->v_pointer); else if (item_size == 1) length = strlen ((gchar *)arg->v_pointer); else if (item_size == sizeof (int)) for (length = 0; *(((int *)arg->v_pointer) + length); length++); else if (item_size == sizeof (short)) for (length = 0; *(((short *)arg->v_pointer) + length); length++); else g_assert_not_reached (); } else { if (!gi_type_info_get_array_fixed_size (type_info, &length)) { unsigned int length_arg_pos; gboolean has_array_length; if (G_UNLIKELY (array_length_policy == NULL)) { g_critical ("Unable to determine array length for %p", arg->v_pointer); g_array = g_array_new (is_zero_terminated, FALSE, (guint)item_size); *out_free_array = TRUE; return g_array; } has_array_length = gi_type_info_get_array_length_index ( type_info, &length_arg_pos); g_assert (has_array_length); length_policy = array_length_policy (length_arg_pos, user_data1, user_data2); if (length_policy < 0) { return NULL; } length = (size_t)length_policy; } } g_array = g_array_new (is_zero_terminated, FALSE, (guint)item_size); g_free (g_array->data); g_array->data = arg->v_pointer; g_array->len = (guint)length; *out_free_array = TRUE; break; case GI_ARRAY_TYPE_ARRAY: case GI_ARRAY_TYPE_BYTE_ARRAY: /* Note: GByteArray is really just a GArray */ g_array = arg->v_pointer; *out_free_array = FALSE; break; case GI_ARRAY_TYPE_PTR_ARRAY: { GPtrArray *ptr_array = (GPtrArray *)arg->v_pointer; g_array = g_array_sized_new (FALSE, FALSE, sizeof (gpointer), ptr_array->len); g_array->data = (char *)ptr_array->pdata; g_array->len = ptr_array->len; *out_free_array = TRUE; break; } default: g_critical ("Unexpected array type %u", gi_type_info_get_array_type (type_info)); g_array = NULL; break; } return g_array; } GIArgument _pygi_argument_from_object (PyObject *object, GITypeInfo *type_info, GITransfer transfer) { GIArgument arg; GITypeTag type_tag; gpointer cleanup_data = NULL; memset (&arg, 0, sizeof (GIArgument)); type_tag = gi_type_info_get_tag (type_info); switch (type_tag) { case GI_TYPE_TAG_ARRAY: { Py_ssize_t py_length; guint length, i; gboolean is_zero_terminated; GITypeInfo *item_type_info; gsize item_size; GArray *array; GITransfer item_transfer; if (Py_IsNone (object)) { arg.v_pointer = NULL; break; } /* Note, strings are sequences, but we cannot accept them here */ if (!PySequence_Check (object) || PyUnicode_Check (object)) { PyErr_SetString (PyExc_TypeError, "expected sequence"); break; } py_length = PySequence_Length (object); if (py_length < 0) break; if (!pygi_guint_from_pyssize (py_length, &length)) break; is_zero_terminated = gi_type_info_is_zero_terminated (type_info); item_type_info = gi_type_info_get_param_type (type_info, 0); /* we handle arrays that are really strings specially, see below */ if (gi_type_info_get_tag (item_type_info) == GI_TYPE_TAG_UINT8) item_size = 1; else item_size = sizeof (GIArgument); array = g_array_sized_new (is_zero_terminated, FALSE, (guint)item_size, length); if (array == NULL) { gi_base_info_unref ((GIBaseInfo *)item_type_info); PyErr_NoMemory (); break; } if (gi_type_info_get_tag (item_type_info) == GI_TYPE_TAG_UINT8 && PyBytes_Check (object)) { memcpy (array->data, PyBytes_AsString (object), length); array->len = length; goto array_success; } item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; for (i = 0; i < length; i++) { PyObject *py_item; GIArgument item; py_item = PySequence_GetItem (object, i); if (py_item == NULL) { goto array_item_error; } item = _pygi_argument_from_object (py_item, item_type_info, item_transfer); Py_DECREF (py_item); if (PyErr_Occurred ()) { goto array_item_error; } g_array_insert_val (array, i, item); continue; array_item_error: /* Free everything we have converted so far. */ _pygi_argument_release ((GIArgument *)&array, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); array = NULL; _PyGI_ERROR_PREFIX ("Item %u: ", i); break; } array_success: arg.v_pointer = array; gi_base_info_unref ((GIBaseInfo *)item_type_info); break; } case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *info; info = gi_type_info_get_interface (type_info); if (GI_IS_CALLBACK_INFO (info)) { PyErr_SetString ( PyExc_TypeError, "Cannot translate Python object to callback type"); } else if (GI_IS_STRUCT_INFO (info) || GI_IS_UNION_INFO (info)) { GType g_type; PyObject *py_type; gboolean is_foreign = (GI_IS_STRUCT_INFO (info)) && (gi_struct_info_is_foreign ((GIStructInfo *)info)); g_type = gi_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)info); py_type = pygi_type_import_by_gi_info ((GIBaseInfo *)info); /* Note for G_TYPE_VALUE g_type: * This will currently leak the GValue that is allocated and * stashed in arg.v_pointer. Out argument marshaling for caller * allocated GValues already pass in memory for the GValue. * Further re-factoring is needed to fix this leak. * See: https://bugzilla.gnome.org/show_bug.cgi?id=693405 */ pygi_arg_struct_from_py_marshal ( object, &arg, NULL, /*arg_name*/ GI_REGISTERED_TYPE_INFO (info), g_type, py_type, transfer, FALSE, /*copy_reference*/ is_foreign, gi_type_info_is_pointer (type_info)); Py_DECREF (py_type); } else if (GI_IS_FLAGS_INFO (info)) { /* Check flags before enums: flags are a subtype of enum. */ GType g_type; g_type = gi_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)info); if (pyg_flags_get_value (g_type, object, &arg.v_uint) < 0) break; } else if (GI_IS_ENUM_INFO (info)) { GType g_type; g_type = gi_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)info); if (pyg_enum_get_value (g_type, object, &arg.v_int) < 0) break; } else if (GI_IS_INTERFACE_INFO (info) || GI_IS_OBJECT_INFO (info)) { /* An error within this call will result in a NULL arg */ pygi_marshal_from_py_object (object, &arg, transfer); } else { g_assert_not_reached (); } gi_base_info_unref (info); break; } case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: { Py_ssize_t length; GITypeInfo *item_type_info; GSList *list = NULL; GITransfer item_transfer; Py_ssize_t i; if (Py_IsNone (object)) { arg.v_pointer = NULL; break; } length = PySequence_Length (object); if (length < 0) { break; } item_type_info = gi_type_info_get_param_type (type_info, 0); g_assert (item_type_info != NULL); item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; for (i = length - 1; i >= 0; i--) { PyObject *py_item; GIArgument item; py_item = PySequence_GetItem (object, i); if (py_item == NULL) { goto list_item_error; } item = _pygi_argument_from_object (py_item, item_type_info, item_transfer); Py_DECREF (py_item); if (PyErr_Occurred ()) { goto list_item_error; } if (type_tag == GI_TYPE_TAG_GLIST) { list = (GSList *)g_list_prepend ((GList *)list, item.v_pointer); } else { list = g_slist_prepend (list, item.v_pointer); } continue; list_item_error: /* Free everything we have converted so far. */ _pygi_argument_release ((GIArgument *)&list, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); list = NULL; _PyGI_ERROR_PREFIX ("Item %zd: ", i); break; } arg.v_pointer = list; gi_base_info_unref ((GIBaseInfo *)item_type_info); break; } case GI_TYPE_TAG_GHASH: { Py_ssize_t length; PyObject *keys; PyObject *values; GITypeInfo *key_type_info; GITypeInfo *value_type_info; GITypeTag key_type_tag; GHashFunc hash_func; GEqualFunc equal_func; GHashTable *hash_table; GITransfer item_transfer; Py_ssize_t i; if (Py_IsNone (object)) { arg.v_pointer = NULL; break; } length = PyMapping_Length (object); if (length < 0) { break; } keys = PyMapping_Keys (object); if (keys == NULL) { break; } values = PyMapping_Values (object); if (values == NULL) { Py_DECREF (keys); break; } key_type_info = gi_type_info_get_param_type (type_info, 0); g_assert (key_type_info != NULL); value_type_info = gi_type_info_get_param_type (type_info, 1); g_assert (value_type_info != NULL); key_type_tag = gi_type_info_get_tag (key_type_info); switch (key_type_tag) { case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: hash_func = g_str_hash; equal_func = g_str_equal; break; default: hash_func = NULL; equal_func = NULL; } hash_table = g_hash_table_new (hash_func, equal_func); if (hash_table == NULL) { PyErr_NoMemory (); goto hash_table_release; } item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; for (i = 0; i < length; i++) { PyObject *py_key; PyObject *py_value; GIArgument key; GIArgument value; py_key = PyList_GET_ITEM (keys, i); py_value = PyList_GET_ITEM (values, i); key = _pygi_argument_from_object (py_key, key_type_info, item_transfer); if (PyErr_Occurred ()) { goto hash_table_item_error; } value = _pygi_argument_from_object (py_value, value_type_info, item_transfer); if (PyErr_Occurred ()) { _pygi_argument_release (&key, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); goto hash_table_item_error; } g_hash_table_insert ( hash_table, key.v_pointer, _pygi_arg_to_hash_pointer (&value, value_type_info)); continue; hash_table_item_error: /* Free everything we have converted so far. */ _pygi_argument_release ((GIArgument *)&hash_table, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); hash_table = NULL; _PyGI_ERROR_PREFIX ("Item %zd: ", i); break; } arg.v_pointer = hash_table; hash_table_release: gi_base_info_unref ((GIBaseInfo *)key_type_info); gi_base_info_unref ((GIBaseInfo *)value_type_info); Py_DECREF (keys); Py_DECREF (values); break; } case GI_TYPE_TAG_ERROR: PyErr_SetString (PyExc_NotImplementedError, "error marshalling is not supported yet"); /* TODO */ break; default: /* Ignores cleanup data for now. */ pygi_marshal_from_py_basic_type (object, &arg, type_tag, transfer, &cleanup_data); break; } return arg; } /** * _pygi_argument_to_object: * @arg: The argument to convert to an object. * @type_info: Type info for @arg * @transfer: * * If the argument is of type array, it must be encoded in a GArray, by calling * _pygi_argument_to_array(). This logic can not be folded into this method * as determining array lengths may require access to method call arguments. * * Returns: A PyObject representing @arg */ PyObject * _pygi_argument_to_object (GIArgument *arg, GITypeInfo *type_info, GITransfer transfer) { GITypeTag type_tag; PyObject *object = NULL; type_tag = gi_type_info_get_tag (type_info); switch (type_tag) { case GI_TYPE_TAG_VOID: { if (gi_type_info_is_pointer (type_info)) { g_warn_if_fail (transfer == GI_TRANSFER_NOTHING); object = PyLong_FromVoidPtr (arg->v_pointer); } break; } case GI_TYPE_TAG_ARRAY: { /* Arrays are assumed to be packed in a GArray */ GArray *array; GITypeInfo *item_type_info; GITypeTag item_type_tag; GITransfer item_transfer; gsize i, item_size; if (arg->v_pointer == NULL) return PyList_New (0); item_type_info = gi_type_info_get_param_type (type_info, 0); g_assert (item_type_info != NULL); item_type_tag = gi_type_info_get_tag (item_type_info); item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; array = arg->v_pointer; item_size = g_array_get_element_size (array); if (G_UNLIKELY (item_size > sizeof (GIArgument))) { g_critical ( "Stack overflow protection. " "Can't copy array element into GIArgument."); return PyList_New (0); } if (item_type_tag == GI_TYPE_TAG_UINT8) { /* Return as a byte array */ object = PyBytes_FromStringAndSize (array->data, array->len); } else { object = PyList_New (array->len); if (object == NULL) { g_critical ("Failure to allocate array for %u items", array->len); gi_base_info_unref ((GIBaseInfo *)item_type_info); break; } for (i = 0; i < array->len; i++) { GIArgument item = { 0 }; PyObject *py_item; memcpy (&item, array->data + i * item_size, item_size); py_item = _pygi_argument_to_object (&item, item_type_info, item_transfer); if (py_item == NULL) { Py_CLEAR (object); _PyGI_ERROR_PREFIX ("Item %zu: ", i); break; } PyList_SET_ITEM (object, i, py_item); } } gi_base_info_unref ((GIBaseInfo *)item_type_info); break; } case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *info; info = gi_type_info_get_interface (type_info); if (GI_IS_CALLBACK_INFO (info)) { PyErr_SetString ( PyExc_TypeError, "Cannot translate callback type to Python object"); } else if (GI_IS_STRUCT_INFO (info) || GI_IS_UNION_INFO (info)) { PyObject *py_type; GType g_type = gi_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)info); gboolean is_foreign = (GI_IS_STRUCT_INFO (info)) && (gi_struct_info_is_foreign ((GIStructInfo *)info)); /* Special case variant and none to force loading from py module. */ if (g_type == G_TYPE_VARIANT || g_type == G_TYPE_NONE) { py_type = pygi_type_import_by_gi_info (info); } else { py_type = pygi_type_get_from_g_type (g_type); } object = pygi_arg_struct_to_py_marshal ( arg, GI_REGISTERED_TYPE_INFO (info), g_type, py_type, transfer, FALSE, /*is_allocated*/ is_foreign); Py_XDECREF (py_type); } else if (GI_IS_ENUM_INFO (info)) { PyObject *py_type; py_type = pygi_type_import_by_gi_info (info); if (!py_type) return NULL; if (GI_IS_FLAGS_INFO (info)) { object = pyg_flags_val_new (py_type, arg->v_uint); } else { object = pyg_enum_val_new (py_type, arg->v_int); } } else if (GI_IS_INTERFACE_INFO (info) || GI_IS_OBJECT_INFO (info)) { object = pygi_arg_object_to_py_called_from_c (arg, transfer); } else { g_assert_not_reached (); } gi_base_info_unref (info); break; } case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: { GSList *list; gsize length; GITypeInfo *item_type_info; GITransfer item_transfer; gsize i; list = arg->v_pointer; length = g_slist_length (list); object = PyList_New (length); if (object == NULL) { break; } item_type_info = gi_type_info_get_param_type (type_info, 0); g_assert (item_type_info != NULL); item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; for (i = 0; list != NULL; list = g_slist_next (list), i++) { GIArgument item; PyObject *py_item; item.v_pointer = list->data; py_item = _pygi_argument_to_object (&item, item_type_info, item_transfer); if (py_item == NULL) { Py_CLEAR (object); _PyGI_ERROR_PREFIX ("Item %zu: ", i); break; } PyList_SET_ITEM (object, i, py_item); } gi_base_info_unref ((GIBaseInfo *)item_type_info); break; } case GI_TYPE_TAG_GHASH: { GITypeInfo *key_type_info; GITypeInfo *value_type_info; GITransfer item_transfer; GHashTableIter hash_table_iter; GIArgument key; GIArgument value; if (arg->v_pointer == NULL) { object = Py_None; Py_INCREF (object); break; } object = PyDict_New (); if (object == NULL) { break; } key_type_info = gi_type_info_get_param_type (type_info, 0); g_assert (key_type_info != NULL); g_assert (gi_type_info_get_tag (key_type_info) != GI_TYPE_TAG_VOID); value_type_info = gi_type_info_get_param_type (type_info, 1); g_assert (value_type_info != NULL); g_assert (gi_type_info_get_tag (value_type_info) != GI_TYPE_TAG_VOID); item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; g_hash_table_iter_init (&hash_table_iter, (GHashTable *)arg->v_pointer); while (g_hash_table_iter_next (&hash_table_iter, &key.v_pointer, &value.v_pointer)) { PyObject *py_key; PyObject *py_value; int retval; py_key = _pygi_argument_to_object (&key, key_type_info, item_transfer); if (py_key == NULL) { break; } _pygi_hash_pointer_to_arg (&value, value_type_info); py_value = _pygi_argument_to_object (&value, value_type_info, item_transfer); if (py_value == NULL) { Py_DECREF (py_key); break; } retval = PyDict_SetItem (object, py_key, py_value); Py_DECREF (py_key); Py_DECREF (py_value); if (retval < 0) { Py_CLEAR (object); break; } } gi_base_info_unref ((GIBaseInfo *)key_type_info); gi_base_info_unref ((GIBaseInfo *)value_type_info); break; } case GI_TYPE_TAG_ERROR: { GError *error = (GError *)arg->v_pointer; if (error != NULL && transfer == GI_TRANSFER_NOTHING) { /* If we have not been transferred the ownership we must copy * the error, because pygi_error_check() is going to free it. */ error = g_error_copy (error); } if (pygi_error_check (&error)) { PyObject *err_type; PyObject *err_value; PyObject *err_trace; PyErr_Fetch (&err_type, &err_value, &err_trace); Py_XDECREF (err_type); Py_XDECREF (err_trace); object = err_value; } else { object = Py_None; Py_INCREF (object); break; } break; } default: { object = pygi_marshal_to_py_basic_type (arg, type_tag, transfer); } } return object; } void _pygi_argument_release (GIArgument *arg, GITypeInfo *type_info, GITransfer transfer, GIDirection direction) { GITypeTag type_tag; gboolean is_out = (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT); type_tag = gi_type_info_get_tag (type_info); switch (type_tag) { case GI_TYPE_TAG_VOID: /* Don't do anything, it's transparent to the C side */ break; case GI_TYPE_TAG_BOOLEAN: case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_UINT8: case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_INT32: case GI_TYPE_TAG_UINT32: case GI_TYPE_TAG_INT64: case GI_TYPE_TAG_UINT64: case GI_TYPE_TAG_FLOAT: case GI_TYPE_TAG_DOUBLE: case GI_TYPE_TAG_GTYPE: case GI_TYPE_TAG_UNICHAR: break; case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_UTF8: /* With allow-none support the string could be NULL */ if ((arg->v_string != NULL && (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)) || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { g_free (arg->v_string); } break; case GI_TYPE_TAG_ARRAY: { GArray *array; gsize i; if (arg->v_pointer == NULL) { return; } array = arg->v_pointer; if ((direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { GITypeInfo *item_type_info; GITransfer item_transfer; item_type_info = gi_type_info_get_param_type (type_info, 0); item_transfer = direction == GI_DIRECTION_IN ? GI_TRANSFER_NOTHING : GI_TRANSFER_EVERYTHING; /* Free the items */ for (i = 0; i < array->len; i++) { GIArgument item; memcpy (&item, array->data + (g_array_get_element_size (array) * i), sizeof (GIArgument)); _pygi_argument_release (&item, item_type_info, item_transfer, direction); } gi_base_info_unref ((GIBaseInfo *)item_type_info); } if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { g_array_free (array, TRUE); } break; } case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *info; info = gi_type_info_get_interface (type_info); if (GI_IS_CALLBACK_INFO (info)) { /* TODO */ } else if (GI_IS_STRUCT_INFO (info) || GI_IS_UNION_INFO (info)) { GType type; if (arg->v_pointer == NULL) { return; } type = gi_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)info); if (g_type_is_a (type, G_TYPE_VALUE)) { GValue *value; value = arg->v_pointer; if ((direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { g_value_unset (value); } if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { g_slice_free (GValue, value); } } else if (g_type_is_a (type, G_TYPE_CLOSURE)) { if (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) { g_closure_unref (arg->v_pointer); } } else if (GI_IS_STRUCT_INFO (info) && gi_struct_info_is_foreign ((GIStructInfo *)info)) { if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING) { pygi_struct_foreign_release (GI_BASE_INFO (info), arg->v_pointer); } } else if (g_type_is_a (type, G_TYPE_BOXED)) { } else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) { g_warn_if_fail (!gi_type_info_is_pointer (type_info) || transfer == GI_TRANSFER_NOTHING); } } else if (GI_IS_ENUM_INFO (info)) { /* nothing */ } else if (GI_IS_INTERFACE_INFO (info) || GI_IS_OBJECT_INFO (info)) { if (arg->v_pointer == NULL) { return; } if (is_out && transfer == GI_TRANSFER_EVERYTHING) { g_object_unref (arg->v_pointer); } } else { g_assert_not_reached (); } gi_base_info_unref (info); break; } case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: { GSList *list; if (arg->v_pointer == NULL) { return; } list = arg->v_pointer; if ((direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { GITypeInfo *item_type_info; GITransfer item_transfer; GSList *item; item_type_info = gi_type_info_get_param_type (type_info, 0); g_assert (item_type_info != NULL); item_transfer = direction == GI_DIRECTION_IN ? GI_TRANSFER_NOTHING : GI_TRANSFER_EVERYTHING; /* Free the items */ for (item = list; item != NULL; item = g_slist_next (item)) { _pygi_argument_release ((GIArgument *)&item->data, item_type_info, item_transfer, direction); } gi_base_info_unref ((GIBaseInfo *)item_type_info); } if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { if (type_tag == GI_TYPE_TAG_GLIST) { g_list_free ((GList *)list); } else { /* type_tag == GI_TYPE_TAG_GSLIST */ g_slist_free (list); } } break; } case GI_TYPE_TAG_GHASH: { GHashTable *hash_table; if (arg->v_pointer == NULL) { return; } hash_table = arg->v_pointer; if (direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) { /* We created the table without a destroy function, so keys and * values need to be released. */ GITypeInfo *key_type_info; GITypeInfo *value_type_info; GITransfer item_transfer; GHashTableIter hash_table_iter; gpointer key; gpointer value; key_type_info = gi_type_info_get_param_type (type_info, 0); g_assert (key_type_info != NULL); value_type_info = gi_type_info_get_param_type (type_info, 1); g_assert (value_type_info != NULL); if (direction == GI_DIRECTION_IN) { item_transfer = GI_TRANSFER_NOTHING; } else { item_transfer = GI_TRANSFER_EVERYTHING; } g_hash_table_iter_init (&hash_table_iter, hash_table); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { _pygi_argument_release ((GIArgument *)&key, key_type_info, item_transfer, direction); _pygi_argument_release ((GIArgument *)&value, value_type_info, item_transfer, direction); } gi_base_info_unref ((GIBaseInfo *)key_type_info); gi_base_info_unref ((GIBaseInfo *)value_type_info); } else if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_CONTAINER) { /* Be careful to avoid keys and values being freed if the * callee gave a destroy function. */ g_hash_table_steal_all (hash_table); } if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { g_hash_table_unref (hash_table); } break; } case GI_TYPE_TAG_ERROR: { GError *error; if (arg->v_pointer == NULL) { return; } error = *(GError **)arg->v_pointer; if (error != NULL) { g_error_free (error); } g_slice_free (GError *, arg->v_pointer); break; } default: break; } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-argument.h0000664000000000000000000000460615074673150015714 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2005-2009 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_ARGUMENT_H__ #define __PYGI_ARGUMENT_H__ #include G_BEGIN_DECLS /* Private */ /* TODO: change signature: length as arg, return boolean */ typedef gssize (*PyGIArgArrayLengthPolicy) (gsize item_index, void *user_data1, void *user_data2); gssize _pygi_argument_array_length_marshal (gsize length_arg_index, void *user_data1, void *user_data2); gpointer _pygi_arg_to_hash_pointer (const GIArgument *arg, GITypeInfo *type_info); void _pygi_hash_pointer_to_arg (GIArgument *arg, GITypeInfo *type_info); GArray *_pygi_argument_to_array (GIArgument *arg, PyGIArgArrayLengthPolicy array_length_policy, void *user_data1, void *user_data2, GITypeInfo *type_info, gboolean *out_free_array); GIArgument _pygi_argument_from_object (PyObject *object, GITypeInfo *type_info, GITransfer transfer); PyObject *_pygi_argument_to_object (GIArgument *arg, GITypeInfo *type_info, GITransfer transfer); void _pygi_argument_release (GIArgument *arg, GITypeInfo *type_info, GITransfer transfer, GIDirection direction); gboolean pygi_argument_to_gssize (GIArgument *arg_in, GITypeTag type_tag, gssize *gssize_out); G_END_DECLS #endif /* __PYGI_ARGUMENT_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-array.c0000664000000000000000000010342315074673150015200 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-array.h" #include "pygi-basictype.h" #include "pygi-info.h" #include "pygi-marshal-cleanup.h" #include "pygi-util.h" /* Needed for _pygi_marshal_cleanup_from_py_interface_struct_gvalue hack */ #include "pygi-struct-marshal.h" /* * GArray to Python */ static gboolean gi_argument_from_py_ssize_t (GIArgument *arg_out, Py_ssize_t size_in, GITypeTag type_tag) { switch (type_tag) { case GI_TYPE_TAG_VOID: case GI_TYPE_TAG_BOOLEAN: goto unhandled_type; case GI_TYPE_TAG_INT8: if (size_in >= G_MININT8 && size_in <= G_MAXINT8) { arg_out->v_int8 = (gint8)size_in; return TRUE; } else { goto overflow; } case GI_TYPE_TAG_UINT8: if (size_in >= 0 && size_in <= G_MAXUINT8) { arg_out->v_uint8 = (guint8)size_in; return TRUE; } else { goto overflow; } case GI_TYPE_TAG_INT16: if (size_in >= G_MININT16 && size_in <= G_MAXINT16) { arg_out->v_int16 = (gint16)size_in; return TRUE; } else { goto overflow; } case GI_TYPE_TAG_UINT16: if (size_in >= 0 && size_in <= G_MAXUINT16) { arg_out->v_uint16 = (guint16)size_in; return TRUE; } else { goto overflow; } /* Ranges assume two's complement */ case GI_TYPE_TAG_INT32: if (size_in >= G_MININT32 && size_in <= G_MAXINT32) { arg_out->v_int32 = (gint32)size_in; return TRUE; } else { goto overflow; } case GI_TYPE_TAG_UINT32: if (size_in >= 0 && (gsize)size_in <= G_MAXUINT32) { arg_out->v_uint32 = (guint32)size_in; return TRUE; } else { goto overflow; } case GI_TYPE_TAG_INT64: arg_out->v_int64 = size_in; return TRUE; case GI_TYPE_TAG_UINT64: if (size_in >= 0) { arg_out->v_uint64 = size_in; return TRUE; } else { goto overflow; } case GI_TYPE_TAG_FLOAT: case GI_TYPE_TAG_DOUBLE: case GI_TYPE_TAG_GTYPE: case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_ARRAY: case GI_TYPE_TAG_INTERFACE: case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_GHASH: case GI_TYPE_TAG_ERROR: case GI_TYPE_TAG_UNICHAR: default: goto unhandled_type; } overflow: PyErr_Format (PyExc_OverflowError, "Unable to marshal C Py_ssize_t %zd to %s", size_in, gi_type_tag_to_string (type_tag)); return FALSE; unhandled_type: PyErr_Format (PyExc_TypeError, "Unable to marshal C Py_ssize_t %zd to %s", size_in, gi_type_tag_to_string (type_tag)); return FALSE; } static gboolean gi_argument_to_gsize (GIArgument *arg_in, gsize *gsize_out, GITypeTag type_tag) { switch (type_tag) { case GI_TYPE_TAG_INT8: *gsize_out = arg_in->v_int8; return TRUE; case GI_TYPE_TAG_UINT8: *gsize_out = arg_in->v_uint8; return TRUE; case GI_TYPE_TAG_INT16: *gsize_out = arg_in->v_int16; return TRUE; case GI_TYPE_TAG_UINT16: *gsize_out = arg_in->v_uint16; return TRUE; case GI_TYPE_TAG_INT32: *gsize_out = arg_in->v_int32; return TRUE; case GI_TYPE_TAG_UINT32: *gsize_out = arg_in->v_uint32; return TRUE; case GI_TYPE_TAG_INT64: if (arg_in->v_uint64 > G_MAXSIZE) { PyErr_Format (PyExc_TypeError, "Unable to marshal %s to gsize", gi_type_tag_to_string (type_tag)); return FALSE; } *gsize_out = (gsize)arg_in->v_int64; return TRUE; case GI_TYPE_TAG_UINT64: if (arg_in->v_uint64 > G_MAXSIZE) { PyErr_Format (PyExc_TypeError, "Unable to marshal %s to gsize", gi_type_tag_to_string (type_tag)); return FALSE; } *gsize_out = (gsize)arg_in->v_uint64; return TRUE; default: PyErr_Format (PyExc_TypeError, "Unable to marshal %s to gsize", gi_type_tag_to_string (type_tag)); return FALSE; } } static gboolean _pygi_marshal_from_py_array (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { PyGIMarshalFromPyFunc from_py_marshaller; guint i = 0; gsize success_count = 0; Py_ssize_t py_length; size_t fixed_size; guint length; guint item_size; gboolean is_ptr_array; GArray *array_ = NULL; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache; GITransfer cleanup_transfer = arg_cache->transfer; gboolean is_zero_terminated = gi_type_info_is_zero_terminated (arg_cache->type_info); GIArrayType array_type; if (Py_IsNone (py_arg)) { arg->v_pointer = NULL; return TRUE; } if (!PySequence_Check (py_arg)) { PyErr_Format (PyExc_TypeError, "Must be sequence, not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } py_length = PySequence_Length (py_arg); if (py_length < 0) return FALSE; if (!pygi_guint_from_pyssize (py_length, &length)) return FALSE; if (gi_type_info_get_array_fixed_size (arg_cache->type_info, &fixed_size) && (guint)fixed_size != length) { PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %u", fixed_size, length); return FALSE; } item_size = (guint)array_cache->item_size; is_ptr_array = (gi_type_info_get_array_type (arg_cache->type_info) == GI_ARRAY_TYPE_PTR_ARRAY); if (is_ptr_array) { array_ = (GArray *)g_ptr_array_sized_new (length); } else { array_ = g_array_sized_new (is_zero_terminated, TRUE, item_size, length); } if (array_ == NULL) { PyErr_NoMemory (); return FALSE; } array_type = gi_type_info_get_array_type (arg_cache->type_info); if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8 && PyBytes_Check (py_arg)) { gchar *data = PyBytes_AsString (py_arg); /* Avoid making a copy if the data * is not transferred to the C function * and cannot not be modified by it. */ if (array_type == GI_ARRAY_TYPE_C && arg_cache->transfer == GI_TRANSFER_NOTHING && !is_zero_terminated) { g_free (array_->data); array_->data = data; cleanup_transfer = GI_TRANSFER_EVERYTHING; } else { memcpy (array_->data, data, length); } array_->len = length; if (is_zero_terminated) { /* If array_ has been created with zero_termination, space for the * terminator is properly allocated, so we're not off-by-one here. */ array_->data[length] = '\0'; } goto array_success; } from_py_marshaller = sequence_cache->item_cache->from_py_marshaller; for (i = 0, success_count = 0; i < length; i++) { GIArgument item = { 0 }; gpointer item_cleanup_data = NULL; PyObject *py_item = PySequence_GetItem (py_arg, i); if (py_item == NULL) goto err; if (!from_py_marshaller (state, callable_cache, sequence_cache->item_cache, py_item, &item, &item_cleanup_data)) { Py_DECREF (py_item); goto err; } Py_DECREF (py_item); if (item_cleanup_data != NULL && item_cleanup_data != item.v_pointer) { /* We only support one level of data discrepancy between an items * data and its cleanup data. This is because we only track a single * extra cleanup data pointer per-argument and cannot track the entire * array of items differing data and cleanup_data. * For example, this would fail if trying to marshal an array of * callback closures marked with SCOPE call type where the cleanup data * is different from the items v_pointer, likewise an array of arrays. */ PyErr_SetString ( PyExc_RuntimeError, "Cannot cleanup item data for array due to " "the items data its cleanup data being different."); goto err; } /* FIXME: it is much more efficent to have seperate marshaller * for ptr arrays than doing the evaluation * and casting each loop iteration */ if (is_ptr_array) { g_ptr_array_add ((GPtrArray *)array_, item.v_pointer); } else if (sequence_cache->item_cache->is_pointer) { /* if the item is a pointer, simply copy the pointer */ g_assert (item_size == sizeof (item.v_pointer)); g_array_insert_val (array_, i, item); } else if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_INTERFACE) { /* Special case handling of flat arrays of gvalue/boxed/struct */ PyGIInterfaceCache *item_iface_cache = (PyGIInterfaceCache *)sequence_cache->item_cache; GIBaseInfo *base_info = (GIBaseInfo *)item_iface_cache->interface_info; if (GI_IS_STRUCT_INFO (base_info) || GI_IS_UNION_INFO (base_info)) { PyGIArgCache *item_arg_cache = (PyGIArgCache *)item_iface_cache; PyGIMarshalCleanupFunc from_py_cleanup = item_arg_cache->from_py_cleanup; if (g_type_is_a (item_iface_cache->g_type, G_TYPE_VALUE)) { /* Special case GValue flat arrays to properly init and copy the contents. */ GValue *dest = (GValue *)(void *)(array_->data + (i * item_size)); if (item.v_pointer != NULL) { memset (dest, 0, item_size); g_value_init (dest, G_VALUE_TYPE ((GValue *)item.v_pointer)); g_value_copy ((GValue *)item.v_pointer, dest); } /* Manually increment the length because we are manually setting the memory. */ array_->len++; } else { /* Handles flat arrays of boxed or struct types. */ g_array_insert_vals (array_, i, item.v_pointer, 1); } /* Cleanup any memory left by the per-item marshaler because * _pygi_marshal_cleanup_from_py_array will not know about this * due to "item" being a temporarily marshaled value done on the stack. */ if (from_py_cleanup) from_py_cleanup (state, item_arg_cache, py_item, item_cleanup_data, TRUE); } else { g_array_insert_val (array_, i, item); } } else { /* default value copy of a simple type */ g_array_insert_val (array_, i, item); } success_count++; } goto array_success; err: if (sequence_cache->item_cache->from_py_cleanup != NULL) { gsize j; PyGIMarshalCleanupFunc cleanup_func = sequence_cache->item_cache->from_py_cleanup; /* Only attempt per item cleanup on pointer items */ if (sequence_cache->item_cache->is_pointer) { for (j = 0; j < success_count; j++) { PyObject *py_seq_item = PySequence_GetItem (py_arg, j); cleanup_func (state, sequence_cache->item_cache, py_seq_item, is_ptr_array ? g_ptr_array_index ((GPtrArray *)array_, j) : g_array_index (array_, gpointer, j), TRUE); Py_DECREF (py_seq_item); } } } if (is_ptr_array) g_ptr_array_free ((GPtrArray *)array_, TRUE); else g_array_free (array_, TRUE); _PyGI_ERROR_PREFIX ("Item %u: ", i); return FALSE; array_success: if (array_cache->has_len_arg) { /* we have an child arg to handle */ PyGIArgCache *child_cache = _pygi_callable_cache_get_arg ( callable_cache, array_cache->len_arg_index); if (!gi_argument_from_py_ssize_t ( &state->args[child_cache->c_arg_index].arg_value, length, child_cache->type_tag)) { goto err; } } if (array_type == GI_ARRAY_TYPE_C) { /* In the case of GI_ARRAY_C, we give the data directly as the argument * but keep the array_ wrapper as cleanup data so we don't have to find * it's length again. */ arg->v_pointer = array_->data; if (cleanup_transfer == GI_TRANSFER_EVERYTHING) { g_array_free (array_, FALSE); *cleanup_data = NULL; } else { *cleanup_data = array_; } } else { arg->v_pointer = array_; if (cleanup_transfer == GI_TRANSFER_NOTHING) { /* Free everything in cleanup. */ *cleanup_data = array_; } else if (cleanup_transfer == GI_TRANSFER_CONTAINER) { /* Make a shallow copy so we can free the elements later in cleanup * because it is possible invoke will free the list before our cleanup. */ *cleanup_data = is_ptr_array ? (gpointer)g_ptr_array_ref ((GPtrArray *)array_) : (gpointer)g_array_ref (array_); } else { /* GI_TRANSFER_EVERYTHING */ /* No cleanup, everything is given to the callee. */ *cleanup_data = NULL; } } return TRUE; } static void _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed) { if (was_processed) { GArray *array_ = NULL; GPtrArray *ptr_array_ = NULL; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache; GIArrayType array_type = gi_type_info_get_array_type (arg_cache->type_info); if (array_type == GI_ARRAY_TYPE_PTR_ARRAY) { ptr_array_ = (GPtrArray *)data; } else { array_ = (GArray *)data; } /* clean up items first */ if (sequence_cache->item_cache->from_py_cleanup != NULL) { gsize i; guint len; PyGIMarshalCleanupFunc cleanup_func = sequence_cache->item_cache->from_py_cleanup; g_assert (array_ || ptr_array_); len = (array_ != NULL) ? array_->len : ptr_array_->len; for (i = 0; i < len; i++) { gpointer item; PyObject *py_item = NULL; /* case 1: GPtrArray */ if (ptr_array_ != NULL) item = g_ptr_array_index (ptr_array_, i); /* case 2: C array or GArray with object pointers */ else if (sequence_cache->item_cache->is_pointer) item = g_array_index (array_, gpointer, i); /* case 3: C array or GArray with simple types or structs */ else { item = array_->data + i * array_cache->item_size; /* special-case hack: GValue array items do not get slice * allocated in _pygi_marshal_from_py_array(), so we must * not try to deallocate it as a slice and thus * short-circuit cleanup_func. */ if (cleanup_func == pygi_arg_gvalue_from_py_cleanup) { g_value_unset ((GValue *)item); continue; } } py_item = PySequence_GetItem (py_arg, i); cleanup_func (state, sequence_cache->item_cache, py_item, item, TRUE); Py_XDECREF (py_item); } } /* Only free the array when we didn't transfer ownership */ if (array_type == GI_ARRAY_TYPE_C) { /* always free the GArray wrapper created in from_py marshaling and * passed back as cleanup_data */ g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING); } else { if (array_ != NULL) g_array_unref (array_); else g_ptr_array_unref (ptr_array_); } } } /* * GArray from Python */ static PyObject * _pygi_marshal_to_py_array (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { GArray *array_; PyObject *py_obj = NULL; PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache; PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache; guint processed_items = 0; GIArrayType array_type = gi_type_info_get_array_type (arg_cache->type_info); /* GArrays make it easier to iterate over arrays * with different element sizes but requires that * we allocate a GArray if the argument was a C array */ if (array_type == GI_ARRAY_TYPE_C) { gsize len = 0; if (gi_type_info_get_array_fixed_size (arg_cache->type_info, &len)) { g_assert (arg->v_pointer != NULL); } else if (gi_type_info_is_zero_terminated (arg_cache->type_info)) { if (arg->v_pointer == NULL) { len = 0; } else if (array_cache->item_size == 1) { len = strlen (arg->v_pointer); } else if (array_cache->item_size == sizeof (gpointer)) { len = g_strv_length ((gchar **)arg->v_pointer); } else if (array_cache->item_size == sizeof (int)) { for (len = 0; *(((int *)arg->v_pointer) + len); len++); } else if (array_cache->item_size == sizeof (short)) { for (len = 0; *(((short *)arg->v_pointer) + len); len++); } else { g_assert_not_reached (); } } else if (array_cache->has_len_arg) { GIArgument *len_arg = &state->args[array_cache->len_arg_index].arg_value; PyGIArgCache *sub_cache = _pygi_callable_cache_get_arg ( callable_cache, array_cache->len_arg_index); if (!gi_argument_to_gsize (len_arg, &len, sub_cache->type_tag)) { return NULL; } } array_ = g_array_new (FALSE, FALSE, (guint)array_cache->item_size); if (array_ == NULL) { PyErr_NoMemory (); if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && arg->v_pointer != NULL) g_free (arg->v_pointer); return NULL; } if (array_->data != NULL) g_free (array_->data); array_->data = arg->v_pointer; array_->len = (guint)len; } else { array_ = arg->v_pointer; } if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) { if (arg->v_pointer == NULL) { py_obj = PyBytes_FromString (""); } else { py_obj = PyBytes_FromStringAndSize (array_->data, array_->len); } } else { if (arg->v_pointer == NULL) { py_obj = PyList_New (0); } else { guint i; gsize item_size; PyGIMarshalToPyFunc item_to_py_marshaller; PyGIArgCache *item_arg_cache; GPtrArray *item_cleanups; py_obj = PyList_New (array_->len); if (py_obj == NULL) goto err; item_cleanups = g_ptr_array_sized_new (array_->len); *cleanup_data = item_cleanups; item_arg_cache = seq_cache->item_cache; item_to_py_marshaller = item_arg_cache->to_py_marshaller; item_size = g_array_get_element_size (array_); for (i = 0; i < array_->len; i++) { GIArgument item_arg = { 0 }; PyObject *py_item; gpointer item_cleanup_data = NULL; /* If we are receiving an array of pointers, simply assign the pointer * and move on, letting the per-item marshaler deal with the * various transfer modes and ref counts (e.g. g_variant_ref_sink). */ if (array_type == GI_ARRAY_TYPE_PTR_ARRAY) { item_arg.v_pointer = g_ptr_array_index ((GPtrArray *)array_, i); } else if (item_arg_cache->is_pointer) { item_arg.v_pointer = g_array_index (array_, gpointer, i); } else if (item_arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)item_arg_cache; /* FIXME: This probably doesn't work with boxed types or gvalues. * See fx. _pygi_marshal_from_py_array() */ if (GI_IS_STRUCT_INFO (iface_cache->interface_info)) { if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && !g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) { /* array elements are structs */ gpointer *_struct = g_malloc (item_size); memcpy (_struct, array_->data + i * item_size, item_size); item_arg.v_pointer = _struct; } else { item_arg.v_pointer = array_->data + i * item_size; } } else if (GI_IS_ENUM_INFO (iface_cache->interface_info)) { memcpy (&item_arg, array_->data + i * item_size, item_size); } else { item_arg.v_pointer = g_array_index (array_, gpointer, i); } } else { memcpy (&item_arg, array_->data + i * item_size, item_size); } py_item = item_to_py_marshaller (state, callable_cache, item_arg_cache, &item_arg, &item_cleanup_data); g_ptr_array_index (item_cleanups, i) = item_cleanup_data; if (py_item == NULL) { Py_CLEAR (py_obj); g_ptr_array_unref (item_cleanups); goto err; } PyList_SET_ITEM (py_obj, i, py_item); processed_items++; } } } if (array_type == GI_ARRAY_TYPE_C) g_array_free (array_, FALSE); return py_obj; err: if (array_type == GI_ARRAY_TYPE_C) { g_array_free (array_, arg_cache->transfer == GI_TRANSFER_EVERYTHING); } else { /* clean up unprocessed items */ if (seq_cache->item_cache->to_py_cleanup != NULL) { guint j; PyGIMarshalToPyCleanupFunc cleanup_func = seq_cache->item_cache->to_py_cleanup; for (j = processed_items; j < array_->len; j++) { cleanup_func (state, seq_cache->item_cache, NULL, g_array_index (array_, gpointer, j), FALSE); } } if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) g_array_free (array_, TRUE); } return NULL; } static GArray * _wrap_c_array (PyGIInvokeState *state, PyGIArgGArray *array_cache, gpointer data) { size_t len = 0; if (gi_type_info_get_array_fixed_size ( ((PyGIArgCache *)array_cache)->type_info, &len)) { /* len is set. */ } else if (gi_type_info_is_zero_terminated ( ((PyGIArgCache *)array_cache)->type_info)) { if (array_cache->item_size == sizeof (gpointer)) len = g_strv_length ((gchar **)data); else if (array_cache->item_size == 1) len = strlen ((gchar *)data); else if (array_cache->item_size == sizeof (int)) for (len = 0; *(((int *)data) + len); len++); else if (array_cache->item_size == sizeof (short)) for (len = 0; *(((short *)data) + len); len++); else g_assert_not_reached (); } else if (array_cache->has_len_arg) { GIArgument *len_arg = &state->args[array_cache->len_arg_index].arg_value; len = len_arg->v_long; } return g_array_new_take (data, (guint)len, FALSE, (guint)array_cache->item_size); } static void _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state, PyGIArgCache *arg_cache, gpointer cleanup_data, gpointer data, gboolean was_processed) { GArray *array_ = NULL; GPtrArray *ptr_array_ = NULL; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache; gboolean free_array = FALSE; gboolean free_array_full = TRUE; GIArrayType array_type = gi_type_info_get_array_type (arg_cache->type_info); if (arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->transfer == GI_TRANSFER_CONTAINER) { free_array = TRUE; } /* If this isn't a garray create one to help process variable sized array elements */ if (array_type == GI_ARRAY_TYPE_C) { array_ = _wrap_c_array (state, array_cache, data); if (array_ == NULL) return; free_array = TRUE; free_array_full = arg_cache->transfer != GI_TRANSFER_NOTHING; } else if (array_type == GI_ARRAY_TYPE_PTR_ARRAY) { ptr_array_ = (GPtrArray *)data; } else { array_ = (GArray *)data; } if (sequence_cache->item_cache->to_py_cleanup != NULL) { GPtrArray *item_cleanups = (GPtrArray *)cleanup_data; gsize i; guint len; PyGIMarshalToPyCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup; g_assert (array_ || ptr_array_); len = (array_ != NULL) ? array_->len : ptr_array_->len; for (i = 0; i < len; i++) { cleanup_func (state, sequence_cache->item_cache, g_ptr_array_index (item_cleanups, i), (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i), was_processed); } } if (cleanup_data) g_ptr_array_unref ((GPtrArray *)cleanup_data); if (free_array) { if (array_ != NULL) g_array_free (array_, free_array_full); else g_ptr_array_free (ptr_array_, free_array_full); } } static void _array_cache_free_func (PyGIArgGArray *cache) { if (cache != NULL) { pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache); g_slice_free (PyGIArgGArray, cache); } } static void pygi_arg_garray_len_arg_setup (PyGIArgGArray *seq_cache, GITypeInfo *type_info, PyGICallableCache *callable_cache, PyGIDirection direction, gssize arg_index, gssize *py_arg_index) { /* attempt len_arg_index setup for the first time */ if (!seq_cache->has_len_arg) { seq_cache->has_len_arg = gi_type_info_get_array_length_index ( type_info, &seq_cache->len_arg_index); /* offset by self arg for methods and vfuncs */ if (seq_cache->has_len_arg && callable_cache != NULL) { seq_cache->len_arg_index += callable_cache->args_offset; } } if (seq_cache->has_len_arg) { PyGIArgCache *child_cache = NULL; child_cache = _pygi_callable_cache_get_arg (callable_cache, seq_cache->len_arg_index); if (child_cache == NULL) { child_cache = pygi_arg_cache_alloc (); _pygi_callable_cache_set_arg ( callable_cache, seq_cache->len_arg_index, child_cache); } else { /* If the "length" arg cache already exists (the length comes before * the array in the argument list), remove it from the to_py_args list * because it does not belong in "to python" return tuple. The length * will implicitly be a part of the returned Python list. */ if (direction & PYGI_DIRECTION_TO_PYTHON) { callable_cache->to_py_args = g_slist_remove (callable_cache->to_py_args, child_cache); } /* This is a case where the arg cache already exists and has been * setup by another array argument sharing the same length argument. * See: gi_marshalling_tests_multi_array_key_value_in */ if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD) return; } /* There is a length argument for this array, so increment the number * of "to python" child arguments when applicable. */ if (direction & PYGI_DIRECTION_TO_PYTHON) callable_cache->n_to_py_child_args++; child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD; child_cache->direction = direction; child_cache->to_py_marshaller = pygi_marshal_to_py_basic_type_cache_adapter; child_cache->from_py_marshaller = pygi_marshal_from_py_basic_type_cache_adapter; child_cache->py_arg_index = -1; /* ugly edge case code: * * When the length comes before the array parameter we need to update * indexes of arguments after the index argument. */ if (((gssize)seq_cache->len_arg_index) < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) { guint i; (*py_arg_index) -= 1; callable_cache->n_py_args -= 1; for (i = (guint)seq_cache->len_arg_index + 1; (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) { PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i); if (update_cache == NULL) break; update_cache->py_arg_index -= 1; } } } } static gboolean pygi_arg_garray_setup ( PyGIArgGArray *sc, GITypeInfo *type_info, GIArgInfo *arg_info, /* may be NULL for return arguments */ GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache) { GITypeInfo *item_type_info; PyGIArgCache *arg_cache = (PyGIArgCache *)sc; if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc, type_info, arg_info, transfer, direction, callable_cache)) { return FALSE; } ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func; sc->has_len_arg = FALSE; /* setup by pygi_arg_garray_len_arg_setup */ item_type_info = gi_type_info_get_param_type (type_info, 0); sc->item_size = _pygi_gi_type_info_size (item_type_info); gi_base_info_unref ((GIBaseInfo *)item_type_info); if (direction & PYGI_DIRECTION_FROM_PYTHON) { arg_cache->from_py_marshaller = _pygi_marshal_from_py_array; arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array; } if (direction & PYGI_DIRECTION_TO_PYTHON) { arg_cache->to_py_marshaller = _pygi_marshal_to_py_array; arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array; } return TRUE; } PyGIArgCache * pygi_arg_garray_new_from_info (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache, gssize arg_index, gssize *py_arg_index) { PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray); if (array_cache == NULL) return NULL; if (!pygi_arg_garray_setup (array_cache, type_info, arg_info, transfer, direction, callable_cache)) { pygi_arg_cache_free ((PyGIArgCache *)array_cache); return NULL; } pygi_arg_garray_len_arg_setup (array_cache, type_info, callable_cache, direction, arg_index, py_arg_index); return (PyGIArgCache *)array_cache; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-array.h0000664000000000000000000000231515074673150015203 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_ARRAY_H__ #define __PYGI_ARRAY_H__ #include #include "pygi-cache.h" G_BEGIN_DECLS PyGIArgCache *pygi_arg_garray_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache, gssize arg_index, gssize *py_arg_index); G_END_DECLS #endif /*__PYGI_ARRAY_H__*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-async.c0000664000000000000000000004335715074673150015210 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2015 Christoph Reiter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include #include "pygobject-object.h" #include "pygboxed.h" #include "pygi-async.h" #include "pygi-info.h" #include "pygi-invoke.h" #include "pygi-util.h" static PyObject *asyncio_InvalidStateError; static PyObject *asyncio_get_running_loop; #if defined(PYPY_VERSION) static PyObject *contextvars_copy_context; #endif static PyObject *cancellable_info; /* This is never instantiated. */ PYGI_DEFINE_TYPE ("gi._gi.Async", PyGIAsync_Type, PyGIAsync) /** * Async.__repr__() implementation. * Takes the _Async.__repr_format format string and applies the finish function * info to it. */ static PyObject * async_repr (PyGIAsync *self) { PyObject *string; char *func_descr; func_descr = _pygi_gi_base_info_get_fullname (self->finish_func->base.info); string = PyUnicode_FromFormat ( "%s(finish_func=%s, done=%s)", Py_TYPE (self)->tp_name, func_descr, (self->result || self->exception) ? "True" : "False"); g_free (func_descr); return string; } /** * async_cancel: * * Cancel the asynchronous operation. */ static PyObject * async_cancel (PyGIAsync *self) { return PyObject_CallMethod (self->cancellable, "cancel", NULL); } static PyObject * async_done (PyGIAsync *self) { return PyBool_FromLong (self->result || self->exception); } static PyObject * async_result (PyGIAsync *self) { if (!self->result && !self->exception) { PyErr_SetString (asyncio_InvalidStateError, "Async task is still running!"); return NULL; } self->log_tb = FALSE; if (self->result) { Py_INCREF (self->result); return self->result; } else { PyErr_SetObject (PyExceptionInstance_Class (self->exception), self->exception); return NULL; } } static PyObject * async_exception (PyGIAsync *self) { PyObject *res; if (!self->result && !self->exception) { PyErr_SetString (asyncio_InvalidStateError, "Async task is still running!"); return NULL; } if (self->exception) res = self->exception; else res = Py_None; self->log_tb = FALSE; Py_INCREF (res); return res; } static PyObject * call_soon (PyGIAsync *self, PyGIAsyncCallback *cb) { PyObject *call_soon; PyObject *args, *kwargs = NULL; PyObject *ret; call_soon = PyObject_GetAttrString (self->loop, "call_soon"); if (!call_soon) return NULL; args = Py_BuildValue ("(OO)", cb->func, self); kwargs = PyDict_New (); PyDict_SetItemString (kwargs, "context", cb->context); ret = PyObject_Call (call_soon, args, kwargs); Py_CLEAR (args); Py_CLEAR (kwargs); Py_CLEAR (call_soon); return ret; } static PyObject * async_add_done_callback (PyGIAsync *self, PyObject *args, PyObject *kwargs) { PyGIAsyncCallback callback = { NULL }; static char *kwlist[] = { "", "context", NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O|$O:add_done_callback", kwlist, &callback.func, &callback.context)) return NULL; Py_INCREF (callback.func); if (callback.context == NULL) #ifndef PYPY_VERSION callback.context = PyContext_CopyCurrent (); #else callback.context = PyObject_CallObject (contextvars_copy_context, NULL); #endif else Py_INCREF (callback.context); /* Note that we don't need to copy the current context in this case. */ if (self->result || self->exception) { PyObject *res = call_soon (self, &callback); Py_DECREF (callback.func); Py_DECREF (callback.context); if (res) { Py_DECREF (res); Py_RETURN_NONE; } else { return NULL; } } if (!self->callbacks) self->callbacks = g_array_new (TRUE, TRUE, sizeof (PyGIAsyncCallback)); g_array_append_val (self->callbacks, callback); Py_RETURN_NONE; } static PyObject * async_remove_done_callback (PyGIAsync *self, PyObject *fn) { guint i = 0; gssize removed = 0; while (self->callbacks && i < self->callbacks->len) { PyGIAsyncCallback *cb = &g_array_index (self->callbacks, PyGIAsyncCallback, i); if (PyObject_RichCompareBool (cb->func, fn, Py_EQ) == 1) { Py_DECREF (cb->func); Py_DECREF (cb->context); removed += 1; g_array_remove_index (self->callbacks, i); } else { i += 1; } } return PyLong_FromSsize_t (removed); } static int async_init (PyGIAsync *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "finish_func", "cancellable", NULL }; PyObject *context = NULL; GMainContext *ctx = NULL; int ret = -1; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "O!|O!$:gi._gi.Async.__init__", kwlist, &PyGICallableInfo_Type, &self->finish_func, &PyGObject_Type, &self->cancellable)) goto out; Py_INCREF (self->finish_func); /* We need to pull in Gio.Cancellable at some point, but we delay it * until really needed to avoid having a dependency. */ if (G_UNLIKELY (!cancellable_info)) { PyObject *gio; gio = PyImport_ImportModule ("gi.repository.Gio"); if (gio == NULL) goto out; cancellable_info = PyObject_GetAttrString (gio, "Cancellable"); Py_DECREF (gio); if (!cancellable_info) goto out; } if (self->cancellable) { int res; Py_INCREF (self->cancellable); res = PyObject_IsInstance (self->cancellable, cancellable_info); if (res == -1) goto out; if (res == 0) { PyErr_SetString ( PyExc_TypeError, "cancellable argument needs to be of type Gio.Cancellable"); goto out; } } else { self->cancellable = PyObject_CallObject (cancellable_info, NULL); } self->loop = PyObject_CallObject (asyncio_get_running_loop, NULL); if (!self->loop) goto out; /* We use g_main_context_ref_thread_default() here, as that is what GTask * does. We then only allow creating an awaitable if python has a *running* * EventLoop iterating this context (i.e. has it as its `_context` attr). * * NOTE: This is a bit backward. Instead, it would make more sense to just * fetch the current EventLoop object for the ref'ed GMainContext. * Python will then do the rest and ensure it is not awaited from the wrong * EventLoop. */ ctx = g_main_context_ref_thread_default (); assert (ctx != NULL); /* Duck-type the running loop. It needs to have a _context attribute. */ context = PyObject_GetAttrString (self->loop, "_context"); if (context == NULL) goto out; if (!pyg_boxed_check (context, G_TYPE_MAIN_CONTEXT) || pyg_boxed_get_ptr (context) != ctx) { PyErr_SetString ( PyExc_TypeError, "Running EventLoop is iterating a different GMainContext"); goto out; } /* Success! */ ret = 0; out: g_main_context_unref (ctx); Py_XDECREF (context); return ret; } static PyMethodDef async_methods[] = { { "cancel", (PyCFunction)async_cancel, METH_NOARGS }, { "done", (PyCFunction)async_done, METH_NOARGS }, { "result", (PyCFunction)async_result, METH_NOARGS }, { "exception", (PyCFunction)async_exception, METH_NOARGS }, { "add_done_callback", (PyCFunction)async_add_done_callback, METH_VARARGS | METH_KEYWORDS }, { "remove_done_callback", (PyCFunction)async_remove_done_callback, METH_O }, { NULL, NULL, 0 }, }; static PyObject * async_await (PyGIAsync *self) { /* We return ourselves as iterator. This is legal in principle, but we * don't stop iterating after one item and just continue indefinately, * meaning that certain errors cannot be caught! */ if (!self->result && !self->exception) self->_asyncio_future_blocking = TRUE; Py_INCREF (self); return (PyObject *)self; } static PyObject * async_iternext (PyGIAsync *self) { /* Return ourselves if iteration needs to continue. */ if (!self->result && !self->exception) { Py_INCREF (self); return (PyObject *)self; } if (self->exception) { PyErr_SetObject (PyExceptionInstance_Class (self->exception), self->exception); return NULL; } else { PyObject *e; e = PyObject_CallFunctionObjArgs (PyExc_StopIteration, self->result, NULL); if (e == NULL) return NULL; PyErr_SetObject (PyExc_StopIteration, e); Py_DECREF (e); return NULL; } } static PyAsyncMethods async_async_methods = { .am_await = (unaryfunc)async_await, }; static void async_finalize (PyGIAsync *self) { if (self->log_tb) { PyObject *error_type, *error_value, *error_traceback; PyObject *context = NULL; PyObject *message = NULL; PyObject *call_exception_handler = NULL; PyObject *res = NULL; assert (self->exception != NULL); self->log_tb = 0; /* Save the current exception, if any. */ PyErr_Fetch (&error_type, &error_value, &error_traceback); context = PyDict_New (); if (!context) goto finally; message = PyUnicode_FromFormat ("%s exception was never retrieved", Py_TYPE (self)->tp_name); if (!message) goto finally; if (PyDict_SetItemString (context, "message", message) < 0 || PyDict_SetItemString (context, "exception", self->exception) < 0 || PyDict_SetItemString (context, "future", (PyObject *)self) < 0) goto finally; call_exception_handler = PyObject_GetAttrString (self->loop, "call_exception_handler"); if (!call_exception_handler) goto finally; res = PyObject_CallFunction (call_exception_handler, "(O)", context); if (res == NULL) PyErr_WriteUnraisable (context); finally: Py_CLEAR (res); Py_CLEAR (context); Py_CLEAR (message); Py_CLEAR (call_exception_handler); /* Restore the saved exception. */ PyErr_Restore (error_type, error_value, error_traceback); } Py_CLEAR (self->loop); Py_CLEAR (self->finish_func); if (self->cancellable) Py_CLEAR (self->cancellable); if (self->result) Py_CLEAR (self->result); if (self->exception) Py_CLEAR (self->exception); /* Precation, cannot happen */ if (self->callbacks) g_array_free (self->callbacks, TRUE); } static void async_dealloc (PyGIAsync *self) { #ifndef PYPY_VERSION /* The finalizer might resurrect the object */ if (PyObject_CallFinalizerFromDealloc ((PyObject *)self) < 0) return; #endif Py_TYPE (self)->tp_free ((PyObject *)self); } void pygi_async_finish_cb (GObject *source_object, gpointer res, PyGIAsync *self) { PyGILState_STATE py_state; PyObject *source_pyobj, *res_pyobj; PyObject *args[2]; size_t nargs; PyObject *ret; guint i; /* Lock the GIL as we are coming into this code without the lock and we may be executing python code */ py_state = PyGILState_Ensure (); /* We might still be called at shutdown time. */ if (!Py_IsInitialized ()) { PyGILState_Release (py_state); return; } res_pyobj = pygobject_new (res); if (source_object) { source_pyobj = pygobject_new (source_object); args[0] = source_pyobj; args[1] = res_pyobj; nargs = 2; } else { source_pyobj = NULL; args[0] = res_pyobj; nargs = 1; } /* We are calling pygi_callable_info_invoke directly here to avoid * the constructor type checks in _function_info_vectorcall. * * Note that the first argument does not match what is expected * when invoking a constructor function (it expects a class), but * things work out because the argument is discarded. We should * instead check the signature of finish_func to see whether it * expects source_object. */ ret = pygi_callable_info_invoke (self->finish_func, args, nargs, NULL); Py_XDECREF (res_pyobj); Py_XDECREF (source_pyobj); if (PyErr_Occurred ()) { PyObject *exc = NULL, *value = NULL, *traceback = NULL; /* NOTE: cPython >=3.12 has PyErr_{Get,Set}RaisedException */ PyErr_Fetch (&exc, &value, &traceback); PyErr_NormalizeException (&exc, &value, &traceback); self->exception = value; self->log_tb = TRUE; Py_XDECREF (exc); Py_XDECREF (traceback); Py_XDECREF (ret); } else { self->result = ret; } for (i = 0; self->callbacks && i < self->callbacks->len; i++) { PyGIAsyncCallback *cb = &g_array_index (self->callbacks, PyGIAsyncCallback, i); /* We stop calling anything after the first exception, but still clear * the internal state as if we did. * This matches the pure python implementation of Future. */ if (!PyErr_Occurred ()) { ret = call_soon (self, cb); if (!ret) PyErr_PrintEx (FALSE); else Py_DECREF (ret); } Py_DECREF (cb->func); Py_DECREF (cb->context); } if (self->callbacks) g_array_free (self->callbacks, TRUE); self->callbacks = NULL; Py_DECREF (self); PyGILState_Release (py_state); } /** * pygi_async_new: * @finish_func: A #GIFunctionInfo to wrap that is used to finish. * @cancellable: A #PyObject containging a #GCancellable, or None * * Return a new async instance. * * Returns: An instance of gi.Async or %NULL on error. */ PyObject * pygi_async_new (PyObject *finish_func, PyObject *cancellable) { PyObject *res; PyObject *args; res = PyGIAsync_Type.tp_alloc (&PyGIAsync_Type, 0); if (res) { if (cancellable && !Py_IsNone (cancellable)) args = Py_BuildValue ("(OO)", finish_func, cancellable); else args = Py_BuildValue ("(O)", finish_func); if (PyGIAsync_Type.tp_init (res, args, NULL) < 0) { Py_DECREF (args); Py_DECREF (res); /* Ignore exception from object initializer */ PyErr_Clear (); return NULL; } Py_DECREF (args); } return res; } static struct PyMemberDef async_members[] = { { "_asyncio_future_blocking", T_BOOL, offsetof (PyGIAsync, _asyncio_future_blocking), 0, NULL }, { "_loop", T_OBJECT, offsetof (PyGIAsync, loop), READONLY, NULL }, { "_finish_func", T_OBJECT, offsetof (PyGIAsync, finish_func), READONLY, NULL }, { "cancellable", T_OBJECT, offsetof (PyGIAsync, cancellable), READONLY, "The Gio.Cancellable associated with the task." }, { NULL, }, }; /** * pygi_async_register_types: * @module: A Python modules to which Async gets added to. * * Initializes the Async class and adds it to the passed @module. * * Returns: -1 on error, 0 on success. */ int pygi_async_register_types (PyObject *module) { PyObject *asyncio = NULL; #ifdef PYPY_VERSION PyObject *contextvars = NULL; #endif #ifndef PYPY_VERSION PyGIAsync_Type.tp_finalize = (destructor)async_finalize; #else PyGIAsync_Type.tp_del = (destructor)async_finalize; #endif PyGIAsync_Type.tp_dealloc = (destructor)async_dealloc; PyGIAsync_Type.tp_repr = (reprfunc)async_repr; PyGIAsync_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE; PyGIAsync_Type.tp_methods = async_methods; PyGIAsync_Type.tp_members = async_members; PyGIAsync_Type.tp_as_async = &async_async_methods; PyGIAsync_Type.tp_iter = PyObject_SelfIter; PyGIAsync_Type.tp_iternext = (iternextfunc)&async_iternext; PyGIAsync_Type.tp_init = (initproc)async_init; PyGIAsync_Type.tp_new = PyType_GenericNew; if (PyType_Ready (&PyGIAsync_Type) < 0) return -1; Py_INCREF (&PyGIAsync_Type); if (PyModule_AddObject (module, "Async", (PyObject *)&PyGIAsync_Type) < 0) { Py_DECREF (&PyGIAsync_Type); return -1; } asyncio = PyImport_ImportModule ("asyncio"); if (asyncio == NULL) { goto fail; } asyncio_InvalidStateError = PyObject_GetAttrString (asyncio, "InvalidStateError"); if (asyncio_InvalidStateError == NULL) goto fail; asyncio_get_running_loop = PyObject_GetAttrString (asyncio, "_get_running_loop"); if (asyncio_get_running_loop == NULL) goto fail; #if defined(PYPY_VERSION) contextvars = PyImport_ImportModule ("contextvars"); if (contextvars == NULL) { goto fail; } contextvars_copy_context = PyObject_GetAttrString (contextvars, "copy_context"); Py_CLEAR (contextvars); if (contextvars_copy_context == NULL) goto fail; #endif /* Only initialized when really needed! */ cancellable_info = NULL; Py_CLEAR (asyncio); return 0; fail: Py_CLEAR (asyncio); return -1; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-async.h0000664000000000000000000000313715074673150015205 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2015 Christoph Reiter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_ASYNC_H__ #define __PYGI_ASYNC_H__ #include "Python.h" #include "pygi-info.h" #include "pygi-cache.h" typedef struct { PyObject *func; PyObject *context; } PyGIAsyncCallback; typedef struct { PyObject_HEAD /* Everything for the instance, finish_func is kept in the class. */ PyGICallableInfo *finish_func; PyObject *loop; PyObject *cancellable; char _asyncio_future_blocking; PyObject *result; PyObject *exception; gboolean log_tb; GArray *callbacks; } PyGIAsync; int pygi_async_register_types (PyObject *d); void pygi_async_finish_cb (GObject *source_object, gpointer res, PyGIAsync *async); PyObject *pygi_async_new (PyObject *async_finish, PyObject *cancellable); #endif /* __PYGI_ASYNCRESULT_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-basictype.c0000664000000000000000000010017615074673150016047 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-type.h" #include "pygi-argument.h" #include "pygi-basictype.h" #include "pygi-util.h" #if defined(G_OS_WIN32) #include static gboolean pygi_isfinite (gdouble value) { return _finite (value); } #else #include static gboolean pygi_isfinite (gdouble value) { return isfinite (value); } #endif static gboolean pygi_gpointer_from_py (PyObject *py_arg, gpointer *result) { void *temp; if (Py_IsNone (py_arg)) { *result = NULL; return TRUE; } else if (PyCapsule_CheckExact (py_arg)) { temp = PyCapsule_GetPointer (py_arg, NULL); if (temp == NULL) return FALSE; *result = temp; return TRUE; } else if (PyLong_Check (py_arg)) { temp = PyLong_AsVoidPtr (py_arg); if (PyErr_Occurred ()) return FALSE; *result = temp; return TRUE; } else { PyErr_SetString ( PyExc_ValueError, "Pointer arguments are restricted to integers, capsules, and " "None. " "See: https://bugzilla.gnome.org/show_bug.cgi?id=683599"); return FALSE; } } static gboolean marshal_from_py_void (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { g_warn_if_fail (arg_cache->transfer == GI_TRANSFER_NOTHING); if (pygi_gpointer_from_py (py_arg, &(arg->v_pointer))) { *cleanup_data = arg->v_pointer; return TRUE; } return FALSE; } PyObject * pygi_gsize_to_py (gsize value) { return PyLong_FromSize_t (value); } PyObject * pygi_gssize_to_py (gssize value) { return PyLong_FromSsize_t (value); } static PyObject * base_float_checks (PyObject *object) { if (!PyNumber_Check (object)) { PyErr_Format (PyExc_TypeError, "Must be number, not %s", Py_TYPE (object)->tp_name); return NULL; } return PyNumber_Float (object); } gboolean pygi_gdouble_from_py (PyObject *py_arg, gdouble *result) { PyObject *py_float; gdouble temp; py_float = base_float_checks (py_arg); if (py_float == NULL) return FALSE; temp = PyFloat_AsDouble (py_float); Py_DECREF (py_float); if (PyErr_Occurred ()) return FALSE; *result = temp; return TRUE; } PyObject * pygi_gdouble_to_py (gdouble value) { return PyFloat_FromDouble (value); } gboolean pygi_gfloat_from_py (PyObject *py_arg, gfloat *result) { gdouble double_; PyObject *py_float; py_float = base_float_checks (py_arg); if (py_float == NULL) return FALSE; double_ = PyFloat_AsDouble (py_float); if (PyErr_Occurred ()) { Py_DECREF (py_float); return FALSE; } if (pygi_isfinite (double_) && (double_ < -G_MAXFLOAT || double_ > G_MAXFLOAT)) { PyObject *min, *max; min = pygi_gfloat_to_py (-G_MAXFLOAT); max = pygi_gfloat_to_py (G_MAXFLOAT); PyErr_Format (PyExc_OverflowError, "%S not in range %S to %S", py_float, min, max); Py_DECREF (min); Py_DECREF (max); Py_DECREF (py_float); return FALSE; } Py_DECREF (py_float); *result = (gfloat)double_; return TRUE; } PyObject * pygi_gfloat_to_py (gfloat value) { return PyFloat_FromDouble (value); } gboolean pygi_gunichar_from_py (PyObject *py_arg, gunichar *result) { Py_ssize_t size; gchar *string_; if (Py_IsNone (py_arg)) { *result = 0; return FALSE; } if (PyUnicode_Check (py_arg)) { PyObject *py_bytes; size = PyUnicode_GET_LENGTH (py_arg); py_bytes = PyUnicode_AsUTF8String (py_arg); if (!py_bytes) return FALSE; string_ = g_strdup (PyBytes_AsString (py_bytes)); Py_DECREF (py_bytes); } else { PyErr_Format (PyExc_TypeError, "Must be string, not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } if (size != 1) { PyErr_Format (PyExc_TypeError, "Must be a one character string, not %lld characters", (long long)size); g_free (string_); return FALSE; } *result = g_utf8_get_char (string_); g_free (string_); return TRUE; } static PyObject * pygi_gunichar_to_py (gunichar value) { PyObject *py_obj = NULL; /* Preserve the bidirectional mapping between 0 and "" */ if (value == 0) { py_obj = PyUnicode_FromString (""); } else if (g_unichar_validate (value)) { gchar utf8[6]; gint bytes; bytes = g_unichar_to_utf8 (value, utf8); py_obj = PyUnicode_FromStringAndSize ((char *)utf8, bytes); } else { /* TODO: Convert the error to an exception. */ PyErr_Format (PyExc_TypeError, "Invalid unicode codepoint %" G_GUINT32_FORMAT, value); } return py_obj; } static gboolean pygi_gtype_from_py (PyObject *py_arg, GType *type) { GType temp = pyg_type_from_object (py_arg); if (temp == 0) { if (!PyErr_Occurred ()) { PyErr_SetString (PyExc_ValueError, "Invalid GType"); return FALSE; } PyErr_Format (PyExc_TypeError, "Must be GObject.GType, not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } *type = temp; return TRUE; } gboolean pygi_utf8_from_py (PyObject *py_arg, gchar **result) { gchar *string_; if (Py_IsNone (py_arg)) { *result = NULL; return TRUE; } if (PyUnicode_Check (py_arg)) { PyObject *pystr_obj = PyUnicode_AsUTF8String (py_arg); if (!pystr_obj) return FALSE; string_ = g_strdup (PyBytes_AsString (pystr_obj)); Py_DECREF (pystr_obj); } else { PyErr_Format (PyExc_TypeError, "Must be string, not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } *result = string_; return TRUE; } G_GNUC_UNUSED static gboolean filename_from_py_unix (PyObject *py_arg, gchar **result) { gchar *filename; if (Py_IsNone (py_arg)) { *result = NULL; return TRUE; } if (PyBytes_Check (py_arg)) { char *buffer; if (PyBytes_AsStringAndSize (py_arg, &buffer, NULL) == -1) return FALSE; filename = g_strdup (buffer); } else if (PyUnicode_Check (py_arg)) { PyObject *bytes; char *buffer; bytes = PyUnicode_EncodeFSDefault (py_arg); if (!bytes) return FALSE; if (PyBytes_AsStringAndSize (bytes, &buffer, NULL) == -1) { Py_DECREF (bytes); return FALSE; } filename = g_strdup (buffer); Py_DECREF (bytes); } else { PyErr_Format (PyExc_TypeError, "Must be bytes, not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } *result = filename; return TRUE; } G_GNUC_UNUSED static gboolean filename_from_py_win32 (PyObject *py_arg, gchar **result) { gchar *filename; if (Py_IsNone (py_arg)) { *result = NULL; return TRUE; } if (PyBytes_Check (py_arg)) { PyObject *uni_arg; gboolean temp_result; char *buffer; if (PyBytes_AsStringAndSize (py_arg, &buffer, NULL) == -1) return FALSE; uni_arg = PyUnicode_DecodeFSDefault (buffer); if (!uni_arg) return FALSE; temp_result = filename_from_py_win32 (uni_arg, result); Py_DECREF (uni_arg); return temp_result; } else if (PyUnicode_Check (py_arg)) { PyObject *bytes, *temp_uni; char *buffer; /* The roundtrip merges lone surrogates, so we get the same output as * with Py 2. Requires 3.4+ because of https://bugs.python.org/issue27971 * Separated lone surrogates can occur when concatenating two paths. */ bytes = PyUnicode_AsEncodedString (py_arg, "utf-16-le", "surrogatepass"); if (!bytes) return FALSE; temp_uni = PyUnicode_FromEncodedObject (bytes, "utf-16-le", "surrogatepass"); Py_DECREF (bytes); if (!temp_uni) return FALSE; /* glib uses utf-8, so encode to that and allow surrogates so we can * represent all possible path values */ bytes = PyUnicode_AsEncodedString (temp_uni, "utf-8", "surrogatepass"); Py_DECREF (temp_uni); if (!bytes) return FALSE; if (PyBytes_AsStringAndSize (bytes, &buffer, NULL) == -1) { Py_DECREF (bytes); return FALSE; } filename = g_strdup (buffer); Py_DECREF (bytes); } else { PyErr_Format (PyExc_TypeError, "Must be str, not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } *result = filename; return TRUE; } static gboolean pygi_filename_from_py (PyObject *py_arg, gchar **result) { #ifdef G_OS_WIN32 return filename_from_py_win32 (py_arg, result); #else return filename_from_py_unix (py_arg, result); #endif } static PyObject * base_number_checks (PyObject *object) { PyObject *number; if (!PyNumber_Check (object)) { PyErr_Format (PyExc_TypeError, "Must be number, not %s", Py_TYPE (object)->tp_name); return NULL; } number = PyNumber_Long (object); if (number == NULL) { PyErr_SetString (PyExc_TypeError, "expected int argument"); return NULL; } return number; } gboolean pygi_gboolean_from_py (PyObject *object, gboolean *result) { int value = PyObject_IsTrue (object); if (value == -1) return FALSE; *result = (gboolean)value; return TRUE; } PyObject * pygi_gboolean_to_py (gboolean value) { return PyBool_FromLong (value); } /* A super set of pygi_gint8_from_py (also handles unicode) */ gboolean pygi_gschar_from_py (PyObject *object, gint8 *result) { if (PyUnicode_Check (object)) { gunichar uni; PyObject *temp; gboolean status; if (!pygi_gunichar_from_py (object, &uni)) return FALSE; temp = pygi_guint32_to_py (uni); status = pygi_gint8_from_py (temp, result); Py_DECREF (temp); return status; } else { /* pygi_gint8_from_py handles numbers and bytes */ return pygi_gint8_from_py (object, result); } return FALSE; } /* A super set of pygi_guint8_from_py (also handles unicode) */ gboolean pygi_guchar_from_py (PyObject *object, guchar *result) { if (PyUnicode_Check (object)) { gunichar uni; PyObject *temp; gboolean status; gint8 codepoint; if (!pygi_gunichar_from_py (object, &uni)) return FALSE; temp = pygi_guint32_to_py (uni); status = pygi_gint8_from_py (temp, &codepoint); Py_DECREF (temp); if (status) *result = (guchar)codepoint; return status; } else { /* pygi_guint8_from_py handles numbers and bytes */ return pygi_guint8_from_py (object, result); } } gboolean pygi_gint_from_py (PyObject *object, gint *result) { long long_value; PyObject *number; number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsLong (number); if (PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } else if (long_value < G_MININT || long_value > G_MAXINT) { goto overflow; } Py_DECREF (number); *result = (gint)long_value; return TRUE; overflow: PyErr_Clear (); PyErr_Format (PyExc_OverflowError, "%S not in range %d to %d", number, (int)G_MININT, (int)G_MAXINT); Py_DECREF (number); return FALSE; } PyObject * pygi_gint_to_py (gint value) { return PyLong_FromLong (value); } gboolean pygi_guint_from_py (PyObject *object, guint *result) { unsigned long long_value; PyObject *number; number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsUnsignedLong (number); if (PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } else if (long_value > G_MAXUINT) { goto overflow; } Py_DECREF (number); *result = (gint)long_value; return TRUE; overflow: PyErr_Clear (); PyErr_Format (PyExc_OverflowError, "%S not in range %ld to %lu", number, (long)0, (unsigned long)G_MAXUINT); Py_DECREF (number); return FALSE; } PyObject * pygi_guint_to_py (guint value) { #if (G_MAXUINT <= LONG_MAX) return PyLong_FromLong ((long)value); #else if (value <= LONG_MAX) return PyLong_FromLong ((long)value); return PyLong_FromUnsignedLong (value); #endif } gboolean pygi_glong_from_py (PyObject *object, glong *result) { long long_value; PyObject *number; number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsLong (number); if (long_value == -1 && PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } Py_DECREF (number); *result = (glong)long_value; return TRUE; overflow: PyErr_Clear (); PyErr_Format (PyExc_OverflowError, "%S not in range %ld to %ld", number, (long)G_MINLONG, (long)G_MAXLONG); Py_DECREF (number); return FALSE; } PyObject * pygi_glong_to_py (glong value) { return PyLong_FromLong (value); } gboolean pygi_gulong_from_py (PyObject *object, gulong *result) { unsigned long long_value; PyObject *number; number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsUnsignedLong (number); if (PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } Py_DECREF (number); *result = (gulong)long_value; return TRUE; overflow: PyErr_Clear (); PyErr_Format (PyExc_OverflowError, "%S not in range %ld to %lu", number, (long)0, (unsigned long)G_MAXULONG); Py_DECREF (number); return FALSE; } PyObject * pygi_gulong_to_py (gulong value) { if (value <= LONG_MAX) return PyLong_FromLong ((long)value); else return PyLong_FromUnsignedLong (value); } gboolean pygi_gint8_from_py (PyObject *object, gint8 *result) { long long_value; PyObject *number; if (PyBytes_Check (object)) { if (PyBytes_Size (object) != 1) { PyErr_Format (PyExc_TypeError, "Must be a single character"); return FALSE; } *result = (gint8)(PyBytes_AsString (object)[0]); return TRUE; } number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsLong (number); if (long_value == -1 && PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } else if (long_value < G_MININT8 || long_value > G_MAXINT8) { goto overflow; } Py_DECREF (number); *result = (gint8)long_value; return TRUE; overflow: PyErr_Clear (); PyErr_Format (PyExc_OverflowError, "%S not in range %ld to %ld", number, (long)G_MININT8, (long)G_MAXINT8); Py_DECREF (number); return FALSE; } PyObject * pygi_gint8_to_py (gint8 value) { return PyLong_FromLong (value); } gboolean pygi_guint8_from_py (PyObject *object, guint8 *result) { long long_value; PyObject *number; if (PyBytes_Check (object)) { if (PyBytes_Size (object) != 1) { PyErr_Format (PyExc_TypeError, "Must be a single character"); return FALSE; } *result = (guint8)(PyBytes_AsString (object)[0]); return TRUE; } number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsLong (number); if (long_value == -1 && PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } else if (long_value < 0 || long_value > G_MAXUINT8) { goto overflow; } Py_DECREF (number); *result = (guint8)long_value; return TRUE; overflow: PyErr_Clear (); PyErr_Format (PyExc_OverflowError, "%S not in range %ld to %ld", number, (long)0, (long)G_MAXUINT8); Py_DECREF (number); return FALSE; } PyObject * pygi_guint8_to_py (guint8 value) { return PyLong_FromLong (value); } static gboolean pygi_gint16_from_py (PyObject *object, gint16 *result) { long long_value; PyObject *number; number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsLong (number); if (long_value == -1 && PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } else if (long_value < G_MININT16 || long_value > G_MAXINT16) { goto overflow; } Py_DECREF (number); *result = (gint16)long_value; return TRUE; overflow: PyErr_Clear (); PyErr_Format (PyExc_OverflowError, "%S not in range %ld to %ld", number, (long)G_MININT16, (long)G_MAXINT16); Py_DECREF (number); return FALSE; } static PyObject * pygi_gint16_to_py (gint16 value) { return PyLong_FromLong (value); } static gboolean pygi_guint16_from_py (PyObject *object, guint16 *result) { long long_value; PyObject *number; number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsLong (number); if (long_value == -1 && PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } else if (long_value < 0 || long_value > G_MAXUINT16) { goto overflow; } Py_DECREF (number); *result = (guint16)long_value; return TRUE; overflow: PyErr_Clear (); PyErr_Format (PyExc_OverflowError, "%S not in range %ld to %ld", number, (long)0, (long)G_MAXUINT16); Py_DECREF (number); return FALSE; } static PyObject * pygi_guint16_to_py (guint16 value) { return PyLong_FromLong (value); } static gboolean pygi_gint32_from_py (PyObject *object, gint32 *result) { long long_value; PyObject *number; number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsLong (number); if (long_value == -1 && PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } else if (long_value < G_MININT32 || long_value > G_MAXINT32) { goto overflow; } Py_DECREF (number); *result = (gint32)long_value; return TRUE; overflow: PyErr_Clear (); PyErr_Format (PyExc_OverflowError, "%S not in range %ld to %ld", number, (long)G_MININT32, (long)G_MAXINT32); Py_DECREF (number); return FALSE; } static PyObject * pygi_gint32_to_py (gint32 value) { return PyLong_FromLong (value); } static gboolean pygi_guint32_from_py (PyObject *object, guint32 *result) { long long long_value; PyObject *number; number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsLongLong (number); if (PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } else if (long_value < 0 || long_value > G_MAXUINT32) { goto overflow; } Py_DECREF (number); *result = (guint32)long_value; return TRUE; overflow: PyErr_Clear (); PyErr_Format (PyExc_OverflowError, "%S not in range %ld to %lu", number, (long)0, (unsigned long)G_MAXUINT32); Py_DECREF (number); return FALSE; } PyObject * pygi_guint32_to_py (guint32 value) { #if (G_MAXUINT <= LONG_MAX) return PyLong_FromLong (value); #else if (value <= LONG_MAX) return PyLong_FromLong ((long)value); else return PyLong_FromLongLong (value); #endif } gboolean pygi_gint64_from_py (PyObject *object, gint64 *result) { long long long_value; PyObject *number, *min, *max; number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsLongLong (number); if (PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } else if (long_value < G_MININT64 || long_value > G_MAXINT64) { goto overflow; } Py_DECREF (number); *result = (gint64)long_value; return TRUE; overflow: PyErr_Clear (); min = pygi_gint64_to_py (G_MININT64); max = pygi_gint64_to_py (G_MAXINT64); PyErr_Format (PyExc_OverflowError, "%S not in range %S to %S", number, min, max); Py_DECREF (number); Py_DECREF (min); Py_DECREF (max); return FALSE; } PyObject * pygi_gint64_to_py (gint64 value) { if (LONG_MIN <= value && value <= LONG_MAX) return PyLong_FromLong ((long)value); else return PyLong_FromLongLong (value); } gboolean pygi_guint64_from_py (PyObject *object, guint64 *result) { unsigned long long long_value; PyObject *number, *max; number = base_number_checks (object); if (number == NULL) return FALSE; long_value = PyLong_AsUnsignedLongLong (number); if (PyErr_Occurred ()) { if (PyErr_ExceptionMatches (PyExc_OverflowError)) goto overflow; Py_DECREF (number); return FALSE; } else if (long_value > G_MAXUINT64) { goto overflow; } Py_DECREF (number); *result = (guint64)long_value; return TRUE; overflow: PyErr_Clear (); max = pygi_guint64_to_py (G_MAXUINT64); PyErr_Format (PyExc_OverflowError, "%S not in range %ld to %S", number, (long)0, max); Py_DECREF (number); Py_DECREF (max); return FALSE; } PyObject * pygi_guint64_to_py (guint64 value) { if (value <= LONG_MAX) return PyLong_FromLong ((long)value); else return PyLong_FromUnsignedLongLong (value); } gboolean pygi_marshal_from_py_basic_type (PyObject *object, /* in */ GIArgument *arg, /* out */ GITypeTag type_tag, GITransfer transfer, gpointer *cleanup_data /* out */) { switch (type_tag) { case GI_TYPE_TAG_VOID: g_warn_if_fail (transfer == GI_TRANSFER_NOTHING); if (pygi_gpointer_from_py (object, &(arg->v_pointer))) { *cleanup_data = arg->v_pointer; return TRUE; } return FALSE; case GI_TYPE_TAG_INT8: return pygi_gint8_from_py (object, &(arg->v_int8)); case GI_TYPE_TAG_UINT8: return pygi_guint8_from_py (object, &(arg->v_uint8)); case GI_TYPE_TAG_INT16: return pygi_gint16_from_py (object, &(arg->v_int16)); case GI_TYPE_TAG_UINT16: return pygi_guint16_from_py (object, &(arg->v_uint16)); case GI_TYPE_TAG_INT32: return pygi_gint32_from_py (object, &(arg->v_int32)); case GI_TYPE_TAG_UINT32: return pygi_guint32_from_py (object, &(arg->v_uint32)); case GI_TYPE_TAG_INT64: return pygi_gint64_from_py (object, &(arg->v_int64)); case GI_TYPE_TAG_UINT64: return pygi_guint64_from_py (object, &(arg->v_uint64)); case GI_TYPE_TAG_BOOLEAN: return pygi_gboolean_from_py (object, &(arg->v_boolean)); case GI_TYPE_TAG_FLOAT: return pygi_gfloat_from_py (object, &(arg->v_float)); case GI_TYPE_TAG_DOUBLE: return pygi_gdouble_from_py (object, &(arg->v_double)); case GI_TYPE_TAG_GTYPE: return pygi_gtype_from_py (object, &(arg->v_size)); case GI_TYPE_TAG_UNICHAR: return pygi_gunichar_from_py (object, &(arg->v_uint32)); case GI_TYPE_TAG_UTF8: if (pygi_utf8_from_py (object, &(arg->v_string))) { *cleanup_data = arg->v_string; return TRUE; } return FALSE; case GI_TYPE_TAG_FILENAME: if (pygi_filename_from_py (object, &(arg->v_string))) { *cleanup_data = arg->v_string; return TRUE; } return FALSE; default: PyErr_Format (PyExc_TypeError, "Type tag %d not supported", type_tag); return FALSE; } return TRUE; } gboolean pygi_marshal_from_py_basic_type_cache_adapter ( PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { return pygi_marshal_from_py_basic_type (py_arg, arg, arg_cache->type_tag, arg_cache->transfer, cleanup_data); } static void marshal_cleanup_from_py_utf8 (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed) { /* We strdup strings so free unless ownership is transferred to C. */ if (was_processed && arg_cache->transfer == GI_TRANSFER_NOTHING) g_free (data); } static PyObject * marshal_to_py_void (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { if (arg_cache->is_pointer) { return PyLong_FromVoidPtr (arg->v_pointer); } Py_RETURN_NONE; } PyObject * pygi_utf8_to_py (gchar *value) { if (value == NULL) { Py_RETURN_NONE; } return PyUnicode_FromString (value); } PyObject * pygi_filename_to_py (gchar *value) { PyObject *py_obj; if (value == NULL) { Py_RETURN_NONE; } #ifdef G_OS_WIN32 py_obj = PyUnicode_DecodeUTF8 (value, strlen (value), "surrogatepass"); #else py_obj = PyUnicode_DecodeFSDefault (value); #endif return py_obj; } /** * pygi_marshal_to_py_basic_type: * @arg: The argument to convert to an object. * @type_tag: Type tag for @arg * @transfer: Transfer annotation * * Convert the given argument to a Python object. This function * is restricted to simple types that only require the GITypeTag * and GITransfer. For a more complete conversion routine, use: * _pygi_argument_to_object. * * Returns: A PyObject representing @arg or NULL if it cannot convert * the argument. */ PyObject * pygi_marshal_to_py_basic_type (GIArgument *arg, GITypeTag type_tag, GITransfer transfer) { switch (type_tag) { case GI_TYPE_TAG_BOOLEAN: return pygi_gboolean_to_py (arg->v_boolean); case GI_TYPE_TAG_INT8: return pygi_gint8_to_py (arg->v_int8); case GI_TYPE_TAG_UINT8: return pygi_guint8_to_py (arg->v_uint8); case GI_TYPE_TAG_INT16: return pygi_gint16_to_py (arg->v_int16); case GI_TYPE_TAG_UINT16: return pygi_guint16_to_py (arg->v_uint16); case GI_TYPE_TAG_INT32: return pygi_gint32_to_py (arg->v_int32); case GI_TYPE_TAG_UINT32: return pygi_guint32_to_py (arg->v_uint32); case GI_TYPE_TAG_INT64: return pygi_gint64_to_py (arg->v_int64); case GI_TYPE_TAG_UINT64: return pygi_guint64_to_py (arg->v_uint64); case GI_TYPE_TAG_FLOAT: return pygi_gfloat_to_py (arg->v_float); case GI_TYPE_TAG_DOUBLE: return pygi_gdouble_to_py (arg->v_double); case GI_TYPE_TAG_GTYPE: return pyg_type_wrapper_new ((GType)arg->v_size); case GI_TYPE_TAG_UNICHAR: return pygi_gunichar_to_py (arg->v_uint32); case GI_TYPE_TAG_UTF8: return pygi_utf8_to_py (arg->v_string); case GI_TYPE_TAG_FILENAME: return pygi_filename_to_py (arg->v_string); default: PyErr_Format (PyExc_TypeError, "Type tag %d not supported", type_tag); return NULL; } } PyObject * pygi_marshal_to_py_basic_type_cache_adapter (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { return pygi_marshal_to_py_basic_type (arg, arg_cache->type_tag, arg_cache->transfer); } static void marshal_cleanup_to_py_utf8 (PyGIInvokeState *state, PyGIArgCache *arg_cache, gpointer cleanup_data, gpointer data, gboolean was_processed) { /* Python copies the string so we need to free it if the interface is transfering ownership, whether or not it has been processed yet */ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) g_free (data); } static gboolean arg_basic_type_setup_from_info (PyGIArgCache *arg_cache, GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction) { GITypeTag type_tag = gi_type_info_get_tag (type_info); if (!pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction)) return FALSE; switch (type_tag) { case GI_TYPE_TAG_VOID: if (direction & PYGI_DIRECTION_FROM_PYTHON) arg_cache->from_py_marshaller = marshal_from_py_void; if (direction & PYGI_DIRECTION_TO_PYTHON) arg_cache->to_py_marshaller = marshal_to_py_void; break; case GI_TYPE_TAG_BOOLEAN: arg_cache->allow_none = TRUE; /* fall through */ case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_UINT8: case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_INT32: case GI_TYPE_TAG_UINT32: case GI_TYPE_TAG_INT64: case GI_TYPE_TAG_UINT64: case GI_TYPE_TAG_FLOAT: case GI_TYPE_TAG_DOUBLE: case GI_TYPE_TAG_UNICHAR: case GI_TYPE_TAG_GTYPE: if (direction & PYGI_DIRECTION_FROM_PYTHON) arg_cache->from_py_marshaller = pygi_marshal_from_py_basic_type_cache_adapter; if (direction & PYGI_DIRECTION_TO_PYTHON) arg_cache->to_py_marshaller = pygi_marshal_to_py_basic_type_cache_adapter; break; case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: if (direction & PYGI_DIRECTION_FROM_PYTHON) { arg_cache->from_py_marshaller = pygi_marshal_from_py_basic_type_cache_adapter; arg_cache->from_py_cleanup = marshal_cleanup_from_py_utf8; } if (direction & PYGI_DIRECTION_TO_PYTHON) { arg_cache->to_py_marshaller = pygi_marshal_to_py_basic_type_cache_adapter; arg_cache->to_py_cleanup = marshal_cleanup_to_py_utf8; } break; default: g_assert_not_reached (); } return TRUE; } PyGIArgCache * pygi_arg_basic_type_new_from_info (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction) { gboolean res = FALSE; PyGIArgCache *arg_cache = pygi_arg_cache_alloc (); res = arg_basic_type_setup_from_info (arg_cache, type_info, arg_info, transfer, direction); if (res) { return arg_cache; } else { pygi_arg_cache_free (arg_cache); return NULL; } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-basictype.h0000664000000000000000000000730715074673150016056 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_ARG_BASICTYPE_H__ #define __PYGI_ARG_BASICTYPE_H__ #include #include "pygi-cache.h" G_BEGIN_DECLS gboolean pygi_marshal_from_py_basic_type (PyObject *object, /* in */ GIArgument *arg, /* out */ GITypeTag type_tag, GITransfer transfer, gpointer *cleanup_data); gboolean pygi_marshal_from_py_basic_type_cache_adapter ( PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data); PyObject *pygi_marshal_to_py_basic_type (GIArgument *arg, /* in */ GITypeTag type_tag, GITransfer transfer); PyObject *pygi_marshal_to_py_basic_type_cache_adapter ( PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data); PyGIArgCache *pygi_arg_basic_type_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction); PyObject *pygi_gint64_to_py (gint64 value); PyObject *pygi_guint64_to_py (guint64 value); PyObject *pygi_gfloat_to_py (gfloat value); PyObject *pygi_gdouble_to_py (gdouble value); PyObject *pygi_gboolean_to_py (gboolean value); PyObject *pygi_gint8_to_py (gint8 value); PyObject *pygi_guint8_to_py (guint8 value); PyObject *pygi_utf8_to_py (gchar *value); PyObject *pygi_gint_to_py (gint value); PyObject *pygi_glong_to_py (glong value); PyObject *pygi_guint_to_py (guint value); PyObject *pygi_gulong_to_py (gulong value); PyObject *pygi_filename_to_py (gchar *value); PyObject *pygi_gsize_to_py (gsize value); PyObject *pygi_gssize_to_py (gssize value); PyObject *pygi_guint32_to_py (guint32 value); gboolean pygi_gboolean_from_py (PyObject *object, gboolean *result); gboolean pygi_gint64_from_py (PyObject *object, gint64 *result); gboolean pygi_guint64_from_py (PyObject *object, guint64 *result); gboolean pygi_gfloat_from_py (PyObject *py_arg, gfloat *result); gboolean pygi_gdouble_from_py (PyObject *py_arg, gdouble *result); gboolean pygi_utf8_from_py (PyObject *py_arg, gchar **result); gboolean pygi_glong_from_py (PyObject *object, glong *result); gboolean pygi_gulong_from_py (PyObject *object, gulong *result); gboolean pygi_gint_from_py (PyObject *object, gint *result); gboolean pygi_guint_from_py (PyObject *object, guint *result); gboolean pygi_gunichar_from_py (PyObject *py_arg, gunichar *result); gboolean pygi_gint8_from_py (PyObject *object, gint8 *result); gboolean pygi_gschar_from_py (PyObject *object, gint8 *result); gboolean pygi_guint8_from_py (PyObject *object, guint8 *result); gboolean pygi_guchar_from_py (PyObject *object, guchar *result); G_END_DECLS #endif /*__PYGI_ARG_BASICTYPE_H__*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-boxed.c0000664000000000000000000001527115074673150015166 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2009 Simon van der Linden * * pygi-boxed.c: wrapper to handle registered structures. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-type.h" #include "pygboxed.h" #include "pygi-basictype.h" #include "pygi-boxed.h" #include "pygi-info.h" #include "pygi-util.h" struct _PyGIBoxed { PyGBoxed base; gboolean slice_allocated; gsize size; }; static void boxed_clear (PyGIBoxed *self) { gpointer boxed = pyg_boxed_get_ptr (self); GType g_type = ((PyGBoxed *)self)->gtype; if (((PyGBoxed *)self)->free_on_dealloc && boxed != NULL) { if (self->slice_allocated) { if (g_type && g_type_is_a (g_type, G_TYPE_VALUE)) g_value_unset (boxed); g_slice_free1 (self->size, boxed); self->slice_allocated = FALSE; self->size = 0; } else { g_boxed_free (g_type, boxed); } } pyg_boxed_set_ptr (self, NULL); } static PyObject * boxed_clear_wrapper (PyGIBoxed *self) { boxed_clear (self); Py_RETURN_NONE; } static void boxed_dealloc (PyGIBoxed *self) { boxed_clear (self); Py_TYPE (self)->tp_free ((PyObject *)self); } void * pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out) { gpointer boxed = NULL; gsize size = 0; if (GI_IS_UNION_INFO (info)) { size = gi_union_info_get_size ((GIUnionInfo *)info); } else if (GI_IS_STRUCT_INFO (info)) { size = gi_struct_info_get_size ((GIStructInfo *)info); } else { PyErr_Format (PyExc_TypeError, "info should be Boxed or Union, not '%d'", g_type_name (G_TYPE_FROM_INSTANCE (info))); return NULL; } if (size == 0) { PyErr_Format (PyExc_TypeError, "boxed cannot be created directly; try using a " "constructor, see: help(%s.%s)", gi_base_info_get_namespace (info), gi_base_info_get_name (info)); return NULL; } if (size_out != NULL) *size_out = size; boxed = g_slice_alloc0 (size); if (boxed == NULL) PyErr_NoMemory (); return boxed; } static PyObject * boxed_new (PyTypeObject *type, PyObject *args, PyObject *kwargs) { GIBaseInfo *info; gsize size = 0; gpointer boxed; PyGIBoxed *self = NULL; info = _pygi_object_get_gi_info ((PyObject *)type, &PyGIBaseInfo_Type); if (info == NULL) { if (PyErr_ExceptionMatches (PyExc_AttributeError)) { PyErr_Format (PyExc_TypeError, "missing introspection information"); } return NULL; } boxed = pygi_boxed_alloc (info, &size); if (boxed == NULL) { goto out; } self = (PyGIBoxed *)pygi_boxed_new (type, boxed, TRUE, size); if (self == NULL) { g_slice_free1 (size, boxed); goto out; } self->size = size; self->slice_allocated = TRUE; out: gi_base_info_unref (info); return (PyObject *)self; } static int boxed_init (PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "", kwlist)) { PyErr_Clear (); PyErr_Warn ( PyExc_DeprecationWarning, "Passing arguments to gi.types.Boxed.__init__() is deprecated. " "All arguments passed will be ignored."); } /* Don't call PyGBoxed's init, which raises an exception. */ return 0; } PYGI_DEFINE_TYPE ("gi.Boxed", PyGIBoxed_Type, PyGIBoxed); PyObject * pygi_boxed_new (PyTypeObject *type, gpointer boxed, gboolean free_on_dealloc, gsize allocated_slice) { PyGIBoxed *self; if (!boxed) { Py_RETURN_NONE; } if (!PyType_IsSubtype (type, &PyGIBoxed_Type)) { PyErr_SetString (PyExc_TypeError, "must be a subtype of gi.Boxed"); return NULL; } self = (PyGIBoxed *)type->tp_alloc (type, 0); if (self == NULL) { return NULL; } ((PyGBoxed *)self)->gtype = pyg_type_from_object ((PyObject *)type); ((PyGBoxed *)self)->free_on_dealloc = free_on_dealloc; pyg_boxed_set_ptr (self, boxed); if (allocated_slice > 0) { self->size = allocated_slice; self->slice_allocated = TRUE; } else { self->size = 0; self->slice_allocated = FALSE; } return (PyObject *)self; } /** * pygi_boxed_copy_in_place: * * Replace the boxed pointer held by this wrapper with a boxed copy * freeing the previously held pointer (when free_on_dealloc is TRUE). * This can be used in cases where Python is passed a reference which * it does not own and the wrapper is held by the Python program * longer than the duration of a callback it was passed to. */ void pygi_boxed_copy_in_place (PyGIBoxed *self) { PyGBoxed *pygboxed = (PyGBoxed *)self; gpointer ptr = pyg_boxed_get_ptr (self); gpointer copy = NULL; if (ptr) copy = g_boxed_copy (pygboxed->gtype, ptr); boxed_clear (self); pyg_boxed_set_ptr (pygboxed, copy); pygboxed->free_on_dealloc = TRUE; } static PyMethodDef boxed_methods[] = { { "_clear_boxed", (PyCFunction)boxed_clear_wrapper, METH_NOARGS }, { NULL, NULL, 0 }, }; /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_boxed_register_types (PyObject *m) { Py_SET_TYPE (&PyGIBoxed_Type, &PyType_Type); g_assert (Py_TYPE (&PyGBoxed_Type) != NULL); PyGIBoxed_Type.tp_base = &PyGBoxed_Type; PyGIBoxed_Type.tp_new = (newfunc)boxed_new; PyGIBoxed_Type.tp_init = (initproc)boxed_init; PyGIBoxed_Type.tp_dealloc = (destructor)boxed_dealloc; PyGIBoxed_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); PyGIBoxed_Type.tp_methods = boxed_methods; if (PyType_Ready (&PyGIBoxed_Type) < 0) return -1; Py_INCREF ((PyObject *)&PyGIBoxed_Type); if (PyModule_AddObject (m, "Boxed", (PyObject *)&PyGIBoxed_Type) < 0) { Py_DECREF ((PyObject *)&PyGIBoxed_Type); return -1; } return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-boxed.h0000664000000000000000000000257715074673150015200 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2009 Simon van der Linden * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_BOXED_H__ #define __PYGI_BOXED_H__ #include #include #include "pygobject-internal.h" G_BEGIN_DECLS typedef struct _PyGIBoxed PyGIBoxed; extern PyTypeObject PyGIBoxed_Type; PyObject *pygi_boxed_new (PyTypeObject *type, gpointer boxed, gboolean free_on_dealloc, gsize allocated_slice); void *pygi_boxed_alloc (GIBaseInfo *info, gsize *size); void pygi_boxed_copy_in_place (PyGIBoxed *self); int pygi_boxed_register_types (PyObject *m); G_END_DECLS #endif /* __PYGI_BOXED_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-cache.c0000664000000000000000000011431015074673150015122 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2013 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-array.h" #include "pygi-basictype.h" #include "pygi-cache.h" #include "pygi-closure.h" #include "pygi-enum-marshal.h" #include "pygi-error.h" #include "pygi-hashtable.h" #include "pygi-info.h" #include "pygi-invoke.h" #include "pygi-list.h" #include "pygi-marshal-cleanup.h" #include "pygi-object.h" #include "pygi-repository.h" #include "pygi-resulttuple.h" #include "pygi-struct-marshal.h" #include "pygi-type.h" /* pygi_arg_base_setup: * arg_cache: argument cache to initialize * type_info: source for type related attributes to cache * arg_info: (allow-none): source for argument related attributes to cache * transfer: transfer mode to store in the argument cache * direction: marshaling direction to store in the cache * * Initializer for PyGIArgCache * * Returns: TRUE on success and FALSE on failure */ gboolean pygi_arg_base_setup ( PyGIArgCache *arg_cache, GITypeInfo *type_info, GIArgInfo *arg_info, /* may be NULL for return arguments */ GITransfer transfer, PyGIDirection direction) { arg_cache->direction = direction; arg_cache->transfer = transfer; arg_cache->py_arg_index = -1; arg_cache->c_arg_index = -1; if (type_info != NULL) { arg_cache->is_pointer = gi_type_info_is_pointer (type_info); arg_cache->type_tag = gi_type_info_get_tag (type_info); gi_base_info_ref ((GIBaseInfo *)type_info); arg_cache->type_info = type_info; } if (arg_info != NULL) { arg_cache->arg_name = gi_base_info_get_name ((GIBaseInfo *)arg_info); arg_cache->allow_none = gi_arg_info_may_be_null (arg_info) || (direction & PYGI_DIRECTION_FROM_PYTHON && gi_arg_info_is_optional (arg_info)); if (arg_cache->type_tag == GI_TYPE_TAG_INTERFACE || arg_cache->type_tag == GI_TYPE_TAG_ARRAY) arg_cache->is_caller_allocates = gi_arg_info_is_caller_allocates (arg_info); else arg_cache->is_caller_allocates = FALSE; } return TRUE; } void pygi_arg_cache_free (PyGIArgCache *cache) { if (cache == NULL) return; if (cache->type_info != NULL) gi_base_info_unref ((GIBaseInfo *)cache->type_info); if (cache->destroy_notify) cache->destroy_notify (cache); else g_slice_free (PyGIArgCache, cache); } /* PyGIInterfaceCache */ static void _interface_cache_free_func (PyGIInterfaceCache *cache) { if (cache != NULL) { Py_XDECREF (cache->py_type); if (cache->type_name != NULL) g_free (cache->type_name); if (cache->interface_info != NULL) gi_base_info_unref ((GIBaseInfo *)cache->interface_info); g_slice_free (PyGIInterfaceCache, cache); } } /* pygi_arg_interface_setup: * arg_cache: argument cache to initialize * type_info: source for type related attributes to cache * arg_info: (allow-none): source for argument related attributes to cache * transfer: transfer mode to store in the argument cache * direction: marshaling direction to store in the cache * iface_info: interface info to cache * * Initializer for PyGIInterfaceCache * * Returns: TRUE on success and FALSE on failure */ static gboolean pygi_arg_interface_setup ( PyGIInterfaceCache *iface_cache, GITypeInfo *type_info, GIArgInfo *arg_info, /* may be NULL for return arguments */ GITransfer transfer, PyGIDirection direction, GIRegisteredTypeInfo *iface_info) { GIBaseInfo *base_info = GI_BASE_INFO (iface_info); if (!pygi_arg_base_setup ((PyGIArgCache *)iface_cache, type_info, arg_info, transfer, direction)) { return FALSE; } ((PyGIArgCache *)iface_cache)->destroy_notify = (GDestroyNotify)_interface_cache_free_func; gi_base_info_ref (base_info); iface_cache->interface_info = iface_info; iface_cache->arg_cache.type_tag = GI_TYPE_TAG_INTERFACE; iface_cache->type_name = _pygi_gi_base_info_get_fullname (base_info); iface_cache->g_type = gi_registered_type_info_get_g_type (iface_info); iface_cache->py_type = pygi_type_import_by_gi_info (base_info); if (g_type_is_a (iface_cache->g_type, G_TYPE_OBJECT)) { if (g_str_equal (g_type_name (iface_cache->g_type), "GCancellable")) iface_cache->arg_cache.async_context = PYGI_ASYNC_CONTEXT_CANCELLABLE; } if (iface_cache->py_type == NULL) { return FALSE; } return TRUE; } PyGIArgCache * pygi_arg_interface_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be NULL for return arguments */ GITransfer transfer, PyGIDirection direction, GIRegisteredTypeInfo *iface_info) { PyGIInterfaceCache *ic; ic = g_slice_new0 (PyGIInterfaceCache); if (!pygi_arg_interface_setup (ic, type_info, arg_info, transfer, direction, iface_info)) { pygi_arg_cache_free ((PyGIArgCache *)ic); return NULL; } return (PyGIArgCache *)ic; } /* PyGISequenceCache */ static void _sequence_cache_free_func (PyGISequenceCache *cache) { if (cache != NULL) { pygi_arg_cache_free (cache->item_cache); g_slice_free (PyGISequenceCache, cache); } } /* pygi_arg_sequence_setup: * sc: sequence cache to initialize * type_info: source for type related attributes to cache * arg_info: (allow-none): source for argument related attributes to cache * transfer: transfer mode to store in the argument cache * direction: marshaling direction to store in the cache * iface_info: interface info to cache * * Initializer for PyGISequenceCache used for holding list and array argument * caches. * * Returns: TRUE on success and FALSE on failure */ gboolean pygi_arg_sequence_setup ( PyGISequenceCache *seq_cache, GITypeInfo *type_info, GIArgInfo *arg_info, /* may be NULL for return arguments */ GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache) { GITypeInfo *item_type_info; GITransfer item_transfer; if (!pygi_arg_base_setup ((PyGIArgCache *)seq_cache, type_info, arg_info, transfer, direction)) { return FALSE; } seq_cache->arg_cache.destroy_notify = (GDestroyNotify)_sequence_cache_free_func; item_type_info = gi_type_info_get_param_type (type_info, 0); item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; seq_cache->item_cache = pygi_arg_cache_new ( item_type_info, NULL, item_transfer, direction, callable_cache, 0, 0); gi_base_info_unref ((GIBaseInfo *)item_type_info); if (seq_cache->item_cache == NULL) { return FALSE; } return TRUE; } PyGIArgCache * pygi_arg_cache_alloc (void) { return g_slice_new0 (PyGIArgCache); } static PyGIArgCache * _arg_cache_new_for_interface (GIBaseInfo *iface_info, GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache) { if (GI_IS_CALLBACK_INFO (iface_info)) { return pygi_arg_callback_new_from_info ( type_info, arg_info, transfer, direction, GI_CALLBACK_INFO (iface_info), callable_cache); } else if (GI_IS_OBJECT_INFO (iface_info) || GI_IS_INTERFACE_INFO (iface_info)) { return pygi_arg_gobject_new_from_info ( type_info, arg_info, transfer, direction, GI_REGISTERED_TYPE_INFO (iface_info), callable_cache); } else if (GI_IS_STRUCT_INFO (iface_info) || GI_IS_UNION_INFO (iface_info)) { return pygi_arg_struct_new_from_info ( type_info, arg_info, transfer, direction, GI_REGISTERED_TYPE_INFO (iface_info)); } else if (GI_IS_FLAGS_INFO (iface_info)) { /* Check flags before enums: flags are a subtype of enum. */ return pygi_arg_flags_new_from_info (type_info, arg_info, transfer, direction, GI_FLAGS_INFO (iface_info)); } else if (GI_IS_ENUM_INFO (iface_info)) { return pygi_arg_enum_new_from_info (type_info, arg_info, transfer, direction, GI_ENUM_INFO (iface_info)); } else { g_assert_not_reached (); } return NULL; } PyGIArgCache * pygi_arg_cache_new (GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache, gssize c_arg_index, gssize py_arg_index) { PyGIArgCache *arg_cache = NULL; GITypeTag type_tag; type_tag = gi_type_info_get_tag (type_info); switch (type_tag) { case GI_TYPE_TAG_VOID: case GI_TYPE_TAG_BOOLEAN: case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_UINT8: case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_INT32: case GI_TYPE_TAG_UINT32: case GI_TYPE_TAG_INT64: case GI_TYPE_TAG_UINT64: case GI_TYPE_TAG_FLOAT: case GI_TYPE_TAG_DOUBLE: case GI_TYPE_TAG_UNICHAR: case GI_TYPE_TAG_GTYPE: case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: arg_cache = pygi_arg_basic_type_new_from_info (type_info, arg_info, transfer, direction); break; case GI_TYPE_TAG_ARRAY: arg_cache = pygi_arg_garray_new_from_info ( type_info, arg_info, transfer, direction, callable_cache, c_arg_index, &py_arg_index); break; case GI_TYPE_TAG_GLIST: arg_cache = pygi_arg_glist_new_from_info ( type_info, arg_info, transfer, direction, callable_cache); break; case GI_TYPE_TAG_GSLIST: arg_cache = pygi_arg_gslist_new_from_info ( type_info, arg_info, transfer, direction, callable_cache); break; case GI_TYPE_TAG_GHASH: arg_cache = pygi_arg_hash_table_new_from_info ( type_info, arg_info, transfer, direction, callable_cache); break; case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *interface_info = gi_type_info_get_interface (type_info); arg_cache = _arg_cache_new_for_interface (interface_info, type_info, arg_info, transfer, direction, callable_cache); gi_base_info_unref (interface_info); break; } case GI_TYPE_TAG_ERROR: arg_cache = pygi_arg_gerror_new_from_info (type_info, arg_info, transfer, direction); break; default: break; } if (arg_cache != NULL) { arg_cache->py_arg_index = py_arg_index; arg_cache->c_arg_index = c_arg_index; } return arg_cache; } /* PyGICallableCache */ static PyGIDirection _pygi_get_direction (PyGICallableCache *callable_cache, GIDirection gi_direction) { /* For vfuncs and callbacks our marshalling directions are reversed */ if (gi_direction == GI_DIRECTION_INOUT) { return PYGI_DIRECTION_BIDIRECTIONAL; } else if (gi_direction == GI_DIRECTION_IN) { if (callable_cache->calling_context != PYGI_CALLING_CONTEXT_IS_FROM_PY) return PYGI_DIRECTION_TO_PYTHON; return PYGI_DIRECTION_FROM_PYTHON; } else { if (callable_cache->calling_context != PYGI_CALLING_CONTEXT_IS_FROM_PY) return PYGI_DIRECTION_FROM_PYTHON; return PYGI_DIRECTION_TO_PYTHON; } } /* Generate the cache for the callable's arguments */ static gboolean _callable_cache_generate_args_cache_real (PyGICallableCache *callable_cache, GICallableInfo *callable_info) { gssize i; guint arg_index; GITypeInfo *return_info; GITransfer return_transfer; PyGIArgCache *return_cache; PyGIDirection return_direction; gssize last_explicit_arg_index; PyObject *tuple_names; GSList *arg_cache_item; PyTypeObject *resulttuple_type; /* Return arguments are always considered out */ return_direction = _pygi_get_direction (callable_cache, GI_DIRECTION_OUT); /* cache the return arg */ return_info = gi_callable_info_get_return_type (callable_info); return_transfer = gi_callable_info_get_caller_owns (callable_info); return_cache = pygi_arg_cache_new (return_info, NULL, return_transfer, return_direction, callable_cache, -1, -1); if (return_cache == NULL) return FALSE; return_cache->is_skipped = gi_callable_info_skip_return (callable_info); callable_cache->return_cache = return_cache; gi_base_info_unref (return_info); callable_cache->has_user_data = FALSE; for (i = 0, arg_index = (guint)callable_cache->args_offset; arg_index < _pygi_callable_cache_args_len (callable_cache); i++, arg_index++) { PyGIArgCache *arg_cache = NULL; GIArgInfo *arg_info; PyGIDirection direction; unsigned int closure_index; arg_info = gi_callable_info_get_arg (callable_info, i); /* This only happens when dealing with callbacks */ if (gi_arg_info_get_closure_index (arg_info, &closure_index) && ((gssize)closure_index) == i) { callable_cache->user_data_index = i; callable_cache->has_user_data = TRUE; arg_cache = pygi_arg_cache_alloc (); _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache); direction = _pygi_get_direction (callable_cache, GI_DIRECTION_IN); arg_cache->direction = direction; arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE; arg_cache->c_arg_index = i; arg_cache->is_pointer = TRUE; } else { GITypeInfo *type_info; direction = _pygi_get_direction ( callable_cache, gi_arg_info_get_direction (arg_info)); type_info = gi_arg_info_get_type_info (arg_info); /* must be an child arg filled in by its owner * and continue * fill in it's c_arg_index, add to the in count */ arg_cache = _pygi_callable_cache_get_arg (callable_cache, arg_index); if (arg_cache != NULL) { /* ensure c_arg_index always aligns with callable_cache->args_cache * and all of the various PyGIInvokeState arrays. */ arg_cache->c_arg_index = arg_index; if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) { arg_cache->py_arg_index = callable_cache->n_py_args; callable_cache->n_py_args++; } if (direction & PYGI_DIRECTION_TO_PYTHON) { callable_cache->n_to_py_args++; } arg_cache->type_tag = gi_type_info_get_tag (type_info); } else { GITransfer transfer; gssize py_arg_index = -1; transfer = gi_arg_info_get_ownership_transfer (arg_info); if (direction & PYGI_DIRECTION_FROM_PYTHON) { py_arg_index = callable_cache->n_py_args; callable_cache->n_py_args++; } arg_cache = pygi_arg_cache_new (type_info, arg_info, transfer, direction, callable_cache, arg_index, py_arg_index); if (arg_cache == NULL) { gi_base_info_unref ((GIBaseInfo *)type_info); gi_base_info_unref ((GIBaseInfo *)arg_info); return FALSE; } if (direction & PYGI_DIRECTION_TO_PYTHON) { callable_cache->n_to_py_args++; callable_cache->to_py_args = g_slist_append (callable_cache->to_py_args, arg_cache); } _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache); } gi_base_info_unref (type_info); } /* Ensure arguments always have a name when available */ arg_cache->arg_name = gi_base_info_get_name ((GIBaseInfo *)arg_info); /* Some property (notably booleans), can allow None */ arg_cache->allow_none = arg_cache->allow_none || gi_arg_info_may_be_null (arg_info); gi_base_info_unref ((GIBaseInfo *)arg_info); } if (callable_cache->arg_name_hash == NULL) { callable_cache->arg_name_hash = g_hash_table_new (g_str_hash, g_str_equal); } else { g_hash_table_remove_all (callable_cache->arg_name_hash); } callable_cache->user_data_varargs_arg = NULL; last_explicit_arg_index = -1; /* Reverse loop through all the arguments to setup arg_name_hash * and find the number of required arguments */ for (i = ((gssize)_pygi_callable_cache_args_len (callable_cache)) - 1; i >= 0; i--) { PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache, i); if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD && arg_cache->meta_type != PYGI_META_ARG_TYPE_CLOSURE && arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) { /* Setup arg_name_hash */ gpointer arg_name = (gpointer)arg_cache->arg_name; if (arg_name != NULL) { g_hash_table_insert (callable_cache->arg_name_hash, arg_name, arg_cache); } if (last_explicit_arg_index == -1) { last_explicit_arg_index = i; /* If the last "from python" argument in the args list is a child * with pyarg (currently only callback user_data). Set it to eat * variable args in the callable cache. */ if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) callable_cache->user_data_varargs_arg = arg_cache; } } } if (!return_cache->is_skipped && return_cache->type_tag != GI_TYPE_TAG_VOID) { callable_cache->has_return = TRUE; } tuple_names = PyList_New (0); if (callable_cache->has_return) { PyList_Append (tuple_names, Py_None); } arg_cache_item = callable_cache->to_py_args; while (arg_cache_item) { const gchar *arg_name = ((PyGIArgCache *)arg_cache_item->data)->arg_name; PyObject *arg_string = PyUnicode_FromString (arg_name); PyList_Append (tuple_names, arg_string); Py_DECREF (arg_string); arg_cache_item = arg_cache_item->next; } /* No need to create a tuple type if there aren't multiple values */ if (PyList_Size (tuple_names) > 1) { resulttuple_type = pygi_resulttuple_new_type (tuple_names); if (resulttuple_type == NULL) { Py_DECREF (tuple_names); return FALSE; } else { callable_cache->resulttuple_type = resulttuple_type; } } Py_DECREF (tuple_names); return TRUE; } static void _callable_cache_deinit_real (PyGICallableCache *cache) { g_clear_pointer (&cache->to_py_args, g_slist_free); g_clear_pointer (&cache->arg_name_hash, g_hash_table_unref); g_clear_pointer (&cache->args_cache, g_ptr_array_unref); Py_CLEAR (cache->resulttuple_type); g_clear_pointer (&cache->return_cache, pygi_arg_cache_free); } static gboolean _callable_cache_init (PyGICallableCache *cache, GICallableInfo *callable_info) { gint n_args; GIBaseInfo *container; if (cache->deinit == NULL) cache->deinit = _callable_cache_deinit_real; if (cache->generate_args_cache == NULL) cache->generate_args_cache = _callable_cache_generate_args_cache_real; cache->name = gi_base_info_get_name ((GIBaseInfo *)callable_info); cache->namespace = gi_base_info_get_namespace ((GIBaseInfo *)callable_info); container = gi_base_info_get_container ((GIBaseInfo *)callable_info); cache->container_name = NULL; /* https://bugzilla.gnome.org/show_bug.cgi?id=709456 */ if (container != NULL && !GI_IS_TYPE_INFO (container)) { cache->container_name = gi_base_info_get_name (container); } cache->throws = gi_callable_info_can_throw_gerror (callable_info); if (gi_base_info_is_deprecated (GI_BASE_INFO (callable_info))) { const gchar *deprecated = gi_base_info_get_attribute ( GI_BASE_INFO (callable_info), "deprecated"); gchar *warning; gchar *full_name = pygi_callable_cache_get_full_name (cache); if (deprecated != NULL) warning = g_strdup_printf ("%s is deprecated: %s", full_name, deprecated); else warning = g_strdup_printf ("%s is deprecated", full_name); g_free (full_name); PyErr_WarnEx (PyExc_DeprecationWarning, warning, 0); g_free (warning); } n_args = (gint)cache->args_offset + gi_callable_info_get_n_args (callable_info); if (n_args >= 0) { cache->args_cache = g_ptr_array_new_full (n_args, (GDestroyNotify)pygi_arg_cache_free); g_ptr_array_set_size (cache->args_cache, n_args); } if (!cache->generate_args_cache (cache, callable_info)) { _callable_cache_deinit_real (cache); return FALSE; } return TRUE; } gchar * pygi_callable_cache_get_full_name (PyGICallableCache *cache) { if (cache->container_name != NULL) { return g_strjoin (".", cache->namespace, cache->container_name, cache->name, NULL); } else { return g_strjoin (".", cache->namespace, cache->name, NULL); } } void pygi_callable_cache_free (PyGICallableCache *cache) { cache->deinit (cache); g_free (cache); } /* PyGIFunctionCache */ static PyObject * _function_cache_invoke_real (PyGIFunctionCache *function_cache, PyGIInvokeState *state, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames) { return pygi_invoke_c_callable (function_cache, state, py_args, py_nargsf, py_kwnames); } static void _function_cache_deinit_real (PyGICallableCache *callable_cache) { PyGIFunctionCache *function_cache = (PyGIFunctionCache *)callable_cache; gi_function_invoker_clear (&function_cache->invoker); Py_CLEAR (function_cache->async_finish); _callable_cache_deinit_real (callable_cache); } static gboolean _function_cache_init (PyGIFunctionCache *function_cache, GICallableInfo *callable_info) { PyGICallableCache *callable_cache = (PyGICallableCache *)function_cache; GIFunctionInvoker *invoker = &function_cache->invoker; GError *error = NULL; guint i; callable_cache->calling_context = PYGI_CALLING_CONTEXT_IS_FROM_PY; if (callable_cache->deinit == NULL) callable_cache->deinit = _function_cache_deinit_real; if (function_cache->invoke == NULL) function_cache->invoke = _function_cache_invoke_real; if (!_callable_cache_init (callable_cache, callable_info)) return FALSE; /* Check if this function is an async routine that is capable of returning * an async awaitable object. */ if (!callable_cache->has_return && callable_cache->n_to_py_args == 0) { PyGIArgCache *cancellable = NULL; PyGIArgCache *async_callback = NULL; for (i = 0; i < _pygi_callable_cache_args_len (callable_cache); i++) { PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache, i); /* Ignore any out or in/out parameters. */ if (arg_cache->async_context == PYGI_ASYNC_CONTEXT_CALLBACK) { if (async_callback) { async_callback = NULL; break; } async_callback = arg_cache; } else if (arg_cache->async_context == PYGI_ASYNC_CONTEXT_CANCELLABLE) { if (cancellable) { cancellable = NULL; break; } cancellable = arg_cache; } } if (cancellable && async_callback) { GIBaseInfo *container = gi_base_info_get_container ((GIBaseInfo *)callable_info); GIBaseInfo *async_finish = NULL; gint name_len; gchar *finish_name = NULL; /* This appears to be an async routine. As we have the * GCallableInfo at this point, so guess the finish name and look * up that information. */ name_len = strlen (callable_cache->name); if (g_str_has_suffix (callable_cache->name, "_async")) name_len -= 6; /* Original name without _async if it is there, _finish + NUL byte */ finish_name = g_malloc0 (name_len + 7 + 1); strncat (finish_name, callable_cache->name, name_len); strcat (finish_name, "_finish"); if (container && GI_IS_OBJECT_INFO (container)) { async_finish = GI_BASE_INFO (gi_object_info_find_method ( (GIObjectInfo *)container, finish_name)); } else if (container && GI_IS_INTERFACE_INFO (container)) { async_finish = GI_BASE_INFO (gi_interface_info_find_method ( (GIInterfaceInfo *)container, finish_name)); } else if (!container) { GIRepository *repository; repository = pygi_repository_get_default (); async_finish = gi_repository_find_by_name ( repository, callable_cache->namespace, finish_name); } else { g_debug ( "Awaitable async functions only work on GObjects and as " "toplevel functions."); } if (async_finish && GI_IS_BASE_INFO (async_finish)) { function_cache->async_finish = _pygi_info_new ((GIBaseInfo *)async_finish); function_cache->async_cancellable = cancellable; function_cache->async_callback = async_callback; } if (async_finish) gi_base_info_unref (async_finish); g_free (finish_name); } } /* Set by PyGICCallbackCache and PyGIVFuncCache */ if (invoker->native_address == NULL) { if (gi_function_info_prep_invoker ((GIFunctionInfo *)callable_info, invoker, &error)) { return TRUE; } } else { if (gi_function_invoker_new_for_address ( invoker->native_address, callable_info, invoker, &error)) { return TRUE; } } if (!pygi_error_check (&error)) { PyErr_Format (PyExc_RuntimeError, "unknown error creating invoker for %s", gi_base_info_get_name ((GIBaseInfo *)callable_info)); } _callable_cache_deinit_real (callable_cache); return FALSE; } PyGIFunctionCache * pygi_function_cache_new (GICallableInfo *info) { PyGIFunctionCache *function_cache; function_cache = g_new0 (PyGIFunctionCache, 1); if (!_function_cache_init (function_cache, info)) { g_free (function_cache); return NULL; } return function_cache; } PyObject * pygi_function_cache_invoke (PyGIFunctionCache *function_cache, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames) { PyGIInvokeState state = { 0, }; return function_cache->invoke (function_cache, &state, py_args, py_nargsf, py_kwnames); } /* PyGICCallbackCache */ PyGIFunctionCache * pygi_ccallback_cache_new (GICallableInfo *info, GCallback function_ptr) { PyGICCallbackCache *ccallback_cache; PyGIFunctionCache *function_cache; ccallback_cache = g_new0 (PyGICCallbackCache, 1); function_cache = (PyGIFunctionCache *)ccallback_cache; function_cache->invoker.native_address = function_ptr; if (!_function_cache_init (function_cache, info)) { g_free (ccallback_cache); return NULL; } return function_cache; } PyObject * pygi_ccallback_cache_invoke (PyGICCallbackCache *ccallback_cache, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames, gpointer user_data) { PyGIFunctionCache *function_cache = (PyGIFunctionCache *)ccallback_cache; PyGIInvokeState state = { 0, }; state.user_data = user_data; return function_cache->invoke (function_cache, &state, py_args, py_nargsf, py_kwnames); } /* PyGIConstructorCache */ static PyObject * _constructor_cache_invoke_real (PyGIFunctionCache *function_cache, PyGIInvokeState *state, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames) { PyGICallableCache *cache = (PyGICallableCache *)function_cache; Py_ssize_t nargs = PyVectorcall_NARGS (py_nargsf); PyObject *constructor_class; PyObject *ret; constructor_class = nargs > 0 ? py_args[0] : NULL; if (constructor_class == NULL) { gchar *full_name = pygi_callable_cache_get_full_name (cache); PyErr_Format ( PyExc_TypeError, "Constructors require the class to be passed in as an argument, " "No arguments passed to the %s constructor.", full_name); g_free (full_name); return FALSE; } ret = _function_cache_invoke_real (function_cache, state, py_args + 1, nargs - 1, py_kwnames); if (ret == NULL || cache->return_cache->is_skipped) return ret; if (!Py_IsNone (ret)) { if (!PyTuple_Check (ret)) return ret; if (PyTuple_GET_ITEM (ret, 0) != Py_None) return ret; } PyErr_SetString (PyExc_TypeError, "constructor returned NULL"); Py_DECREF (ret); return NULL; } PyGIFunctionCache * pygi_constructor_cache_new (GICallableInfo *info) { PyGIConstructorCache *constructor_cache; PyGIFunctionCache *function_cache; constructor_cache = g_new0 (PyGIConstructorCache, 1); function_cache = (PyGIFunctionCache *)constructor_cache; function_cache->invoke = _constructor_cache_invoke_real; if (!_function_cache_init (function_cache, info)) { g_free (constructor_cache); return NULL; } return function_cache; } /* PyGIFunctionWithInstanceCache */ static gboolean _function_with_instance_cache_generate_args_cache_real ( PyGICallableCache *callable_cache, GICallableInfo *callable_info) { GIBaseInfo *interface_info; PyGIArgCache *instance_cache; GITransfer transfer; interface_info = gi_base_info_get_container ((GIBaseInfo *)callable_info); transfer = gi_callable_info_get_instance_ownership_transfer (callable_info); instance_cache = _arg_cache_new_for_interface ( interface_info, NULL, NULL, transfer, PYGI_DIRECTION_FROM_PYTHON, callable_cache); if (instance_cache == NULL) return FALSE; /* Because we are not supplied a GITypeInfo for instance arguments, * assume some defaults. */ instance_cache->is_pointer = TRUE; instance_cache->py_arg_index = 0; instance_cache->c_arg_index = 0; _pygi_callable_cache_set_arg (callable_cache, 0, instance_cache); callable_cache->n_py_args++; return _callable_cache_generate_args_cache_real (callable_cache, callable_info); } static gboolean _function_with_instance_cache_init (PyGIFunctionWithInstanceCache *fwi_cache, GICallableInfo *info) { PyGICallableCache *callable_cache = (PyGICallableCache *)fwi_cache; callable_cache->args_offset += 1; callable_cache->generate_args_cache = _function_with_instance_cache_generate_args_cache_real; return _function_cache_init ((PyGIFunctionCache *)fwi_cache, info); } /* PyGIMethodCache */ PyGIFunctionCache * pygi_method_cache_new (GICallableInfo *info) { PyGIMethodCache *method_cache; PyGIFunctionWithInstanceCache *fwi_cache; method_cache = g_new0 (PyGIMethodCache, 1); fwi_cache = (PyGIFunctionWithInstanceCache *)method_cache; if (!_function_with_instance_cache_init (fwi_cache, info)) { g_free (method_cache); return NULL; } return (PyGIFunctionCache *)method_cache; } /* PyGIVFuncCache */ static PyObject * _vfunc_cache_invoke_real (PyGIFunctionCache *function_cache, PyGIInvokeState *state, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames) { PyGIVFuncCache *vfunc_cache = (PyGIVFuncCache *)function_cache; Py_ssize_t nargs = PyVectorcall_NARGS (py_nargsf); PyObject *py_gtype; GType implementor_gtype; GError *error = NULL; PyObject *ret; py_gtype = nargs > 0 ? py_args[0] : NULL; if (py_gtype == NULL) { PyErr_SetString (PyExc_TypeError, "need the GType of the implementor class"); return FALSE; } implementor_gtype = pyg_type_from_object (py_gtype); if (implementor_gtype == G_TYPE_INVALID) return FALSE; /* vfunc addresses are pulled into the state at call time and cannot be * cached because the call site can specify a different portion of the * class hierarchy. e.g. Object.do_func vs. SubObject.do_func might * retrieve a different vfunc address but GI gives us the same vfunc info. */ state->function_ptr = gi_vfunc_info_get_address ( (GIVFuncInfo *)vfunc_cache->info, implementor_gtype, &error); if (pygi_error_check (&error)) { return FALSE; } ret = _function_cache_invoke_real (function_cache, state, py_args + 1, nargs - 1, py_kwnames); return ret; } static void _vfunc_cache_deinit_real (PyGICallableCache *callable_cache) { gi_base_info_unref (((PyGIVFuncCache *)callable_cache)->info); _function_cache_deinit_real (callable_cache); } PyGIFunctionCache * pygi_vfunc_cache_new (GICallableInfo *info) { PyGIVFuncCache *vfunc_cache; PyGIFunctionCache *function_cache; PyGIFunctionWithInstanceCache *fwi_cache; vfunc_cache = g_new0 (PyGIVFuncCache, 1); function_cache = (PyGIFunctionCache *)vfunc_cache; fwi_cache = (PyGIFunctionWithInstanceCache *)vfunc_cache; ((PyGICallableCache *)vfunc_cache)->deinit = _vfunc_cache_deinit_real; /* This must be non-NULL for _function_cache_init() to create the * invoker, the real address will be set in _vfunc_cache_invoke_real(). */ function_cache->invoker.native_address = (gpointer)0xdeadbeef; function_cache->invoke = _vfunc_cache_invoke_real; if (!_function_with_instance_cache_init (fwi_cache, info)) { g_free (vfunc_cache); return NULL; } /* Required by _vfunc_cache_invoke_real() */ vfunc_cache->info = gi_base_info_ref ((GIBaseInfo *)info); return function_cache; } /* PyGIClosureCache */ PyGIClosureCache * pygi_closure_cache_new (GICallableInfo *info) { gssize i; PyGIClosureCache *closure_cache; PyGICallableCache *callable_cache; closure_cache = g_new0 (PyGIClosureCache, 1); callable_cache = (PyGICallableCache *)closure_cache; callable_cache->calling_context = PYGI_CALLING_CONTEXT_IS_FROM_C; if (!_callable_cache_init (callable_cache, info)) { g_free (closure_cache); return NULL; } /* For backwards compatibility closures include the array's length. * * See: https://bugzilla.gnome.org/show_bug.cgi?id=652115 */ for (i = 0; (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) { PyGIArgCache *arg_cache; PyGIArgGArray *garray_cache; PyGIArgCache *len_arg_cache; arg_cache = g_ptr_array_index (callable_cache->args_cache, i); if (arg_cache->type_tag != GI_TYPE_TAG_ARRAY) continue; garray_cache = (PyGIArgGArray *)arg_cache; if (!garray_cache->has_len_arg) continue; len_arg_cache = g_ptr_array_index (callable_cache->args_cache, garray_cache->len_arg_index); len_arg_cache->meta_type = PYGI_META_ARG_TYPE_PARENT; } /* Prevent guessing multiple user data arguments. * This is required because some versions of GI * do not recognize user_data/data arguments correctly. */ if (!callable_cache->has_user_data) { for (i = 0; (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) { PyGIArgCache *arg_cache; arg_cache = g_ptr_array_index (callable_cache->args_cache, i); if (arg_cache->direction == PYGI_DIRECTION_TO_PYTHON && arg_cache->type_tag == GI_TYPE_TAG_VOID && arg_cache->is_pointer) { callable_cache->user_data_index = i; callable_cache->has_user_data = TRUE; break; } } } return closure_cache; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-cache.h0000664000000000000000000002433215074673150015133 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2013 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_CACHE_H__ #define __PYGI_CACHE_H__ /* Workaround for FFI_GO_CLOSURES not being defined on macOS * See also: https://github.com/openjdk/jdk17u-dev/pull/741 */ #ifndef FFI_GO_CLOSURES #define FFI_GO_CLOSURES 0 #endif #include #include #include #include "pygi-invoke-state-struct.h" G_BEGIN_DECLS typedef struct _PyGIArgCache PyGIArgCache; typedef struct _PyGICallableCache PyGICallableCache; typedef struct _PyGIFunctionCache PyGIFunctionCache; typedef struct _PyGIVFuncCache PyGIVFuncCache; typedef PyGIFunctionCache PyGICCallbackCache; typedef PyGIFunctionCache PyGIConstructorCache; typedef PyGIFunctionCache PyGIFunctionWithInstanceCache; typedef PyGIFunctionCache PyGIMethodCache; typedef PyGICallableCache PyGIClosureCache; typedef gboolean (*PyGIMarshalFromPyFunc) (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data); typedef PyObject *(*PyGIMarshalToPyFunc) (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data); typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed); typedef void (*PyGIMarshalToPyCleanupFunc) (PyGIInvokeState *state, PyGIArgCache *arg_cache, gpointer cleanup_data, gpointer data, gboolean was_processed); /* Argument meta types denote how we process the argument: * - PYGI_META_ARG_TYPE_PARENT - parents may or may not have children * but are always processed via the normal marshaller for their * actual GI type. If they have children the marshaller will * also handle marshalling the children. * - PYGI_META_ARG_TYPE_CHILD - Children without python argument are * ignored by the marshallers and handled directly by their parents * marshaller. * - Children with pyargs (PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) are processed * the same as other child args but also have an index into the * python parameters passed to the invoker */ typedef enum { PYGI_META_ARG_TYPE_PARENT, PYGI_META_ARG_TYPE_CHILD, PYGI_META_ARG_TYPE_CHILD_WITH_PYARG, PYGI_META_ARG_TYPE_CLOSURE, } PyGIMetaArgType; /* * Argument direction types denotes how we marshal, * e.g. to Python or from Python or both. */ typedef enum { PYGI_DIRECTION_TO_PYTHON = 1 << 0, PYGI_DIRECTION_FROM_PYTHON = 1 << 1, PYGI_DIRECTION_BIDIRECTIONAL = PYGI_DIRECTION_TO_PYTHON | PYGI_DIRECTION_FROM_PYTHON } PyGIDirection; /* * In PyGI IN and OUT arguments mean different things depending on the context * of the callable, e.g. is it a callback that is being called from C or a * function that is being called from Python. */ typedef enum { PYGI_CALLING_CONTEXT_IS_FROM_C, PYGI_CALLING_CONTEXT_IS_FROM_PY } PyGICallingContext; typedef enum { PYGI_ASYNC_CONTEXT_NONE = 0, PYGI_ASYNC_CONTEXT_CALLBACK, PYGI_ASYNC_CONTEXT_CANCELLABLE, } PyGIAsyncContext; struct _PyGIArgCache { const gchar *arg_name; PyGIMetaArgType meta_type; PyGIAsyncContext async_context; gboolean is_pointer; gboolean is_caller_allocates; gboolean is_skipped; gboolean allow_none; PyGIDirection direction; GITransfer transfer; GITypeTag type_tag; GITypeInfo *type_info; PyGIMarshalFromPyFunc from_py_marshaller; PyGIMarshalToPyFunc to_py_marshaller; PyGIMarshalCleanupFunc from_py_cleanup; PyGIMarshalToPyCleanupFunc to_py_cleanup; GDestroyNotify destroy_notify; gssize c_arg_index; gssize py_arg_index; }; typedef struct _PyGISequenceCache { PyGIArgCache arg_cache; PyGIArgCache *item_cache; } PyGISequenceCache; typedef struct _PyGIArgGArray { PyGISequenceCache seq_cache; unsigned int len_arg_index; gboolean has_len_arg; gsize item_size; } PyGIArgGArray; typedef struct _PyGIInterfaceCache { PyGIArgCache arg_cache; gboolean is_foreign; GType g_type; PyObject *py_type; GIRegisteredTypeInfo *interface_info; gchar *type_name; } PyGIInterfaceCache; struct _PyGICallableCache { const gchar *name; const gchar *container_name; const gchar *namespace; PyGICallingContext calling_context; PyGIArgCache *return_cache; GPtrArray *args_cache; GSList *to_py_args; GHashTable *arg_name_hash; gboolean throws; /* Index of user_data arg passed to a callable. */ unsigned int user_data_index; gboolean has_user_data; /* A user_data arg that can eat variable args passed to a callable. */ PyGIArgCache *user_data_varargs_arg; /* Number of args already added */ gssize args_offset; /* Number of out args passed to gi_function_info_invoke. * This is used for the length of PyGIInvokeState.out_values */ gssize n_to_py_args; /* If the callable return value gets used */ gboolean has_return; /* The type used for returning multiple values or NULL */ PyTypeObject *resulttuple_type; /* Number of out args for gi_function_info_invoke that will be skipped * when marshaling to Python due to them being implicitly available * (list/array length). */ gssize n_to_py_child_args; /* Number of Python arguments expected for invoking the gi function. */ gssize n_py_args; void (*deinit) (PyGICallableCache *callable_cache); gboolean (*generate_args_cache) (PyGICallableCache *callable_cache, GICallableInfo *callable_info); }; struct _PyGIFunctionCache { PyGICallableCache callable_cache; /* Information about async functions. */ PyObject *async_finish; PyGIArgCache *async_callback; PyGIArgCache *async_cancellable; /* An invoker with ffi_cif already setup */ GIFunctionInvoker invoker; PyObject *(*invoke) (PyGIFunctionCache *function_cache, PyGIInvokeState *state, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames); }; struct _PyGIVFuncCache { PyGIFunctionWithInstanceCache fwi_cache; GIBaseInfo *info; }; gboolean pygi_arg_base_setup ( PyGIArgCache *arg_cache, GITypeInfo *type_info, GIArgInfo *arg_info, /* may be NULL for return arguments */ GITransfer transfer, PyGIDirection direction); gboolean pygi_arg_sequence_setup ( PyGISequenceCache *seq_cache, GITypeInfo *type_info, GIArgInfo *arg_info, /* may be NULL for return arguments */ GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache); PyGIArgCache *pygi_arg_interface_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be NULL for return arguments */ GITransfer transfer, PyGIDirection direction, GIRegisteredTypeInfo *iface_info); PyGIArgCache *pygi_arg_cache_alloc (void); PyGIArgCache *pygi_arg_cache_new (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache, gssize c_arg_index, gssize py_arg_index); void pygi_arg_cache_free (PyGIArgCache *cache); void pygi_callable_cache_free (PyGICallableCache *cache); gchar *pygi_callable_cache_get_full_name (PyGICallableCache *cache); PyGIFunctionCache *pygi_function_cache_new (GICallableInfo *info); PyObject *pygi_function_cache_invoke (PyGIFunctionCache *function_cache, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames); PyGIFunctionCache *pygi_ccallback_cache_new (GICallableInfo *info, GCallback function_ptr); PyObject *pygi_ccallback_cache_invoke (PyGIFunctionCache *function_cache, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames, gpointer user_data); PyGIFunctionCache *pygi_constructor_cache_new (GICallableInfo *info); PyGIFunctionCache *pygi_method_cache_new (GICallableInfo *info); PyGIFunctionCache *pygi_vfunc_cache_new (GICallableInfo *info); PyGIClosureCache *pygi_closure_cache_new (GICallableInfo *info); static inline guint _pygi_callable_cache_args_len (PyGICallableCache *cache) { return cache->args_cache->len; } static inline PyGIArgCache * _pygi_callable_cache_get_arg (PyGICallableCache *cache, guint index) { return (PyGIArgCache *)g_ptr_array_index (cache->args_cache, index); } static inline void _pygi_callable_cache_set_arg (PyGICallableCache *cache, guint index, PyGIArgCache *arg_cache) { cache->args_cache->pdata[index] = arg_cache; } G_END_DECLS #endif /* __PYGI_CACHE_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-ccallback.c0000664000000000000000000000650315074673150015762 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri , Red Hat, Inc. * * pygi-boxed-closure.c: wrapper to handle GClosure box types with C callbacks. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-ccallback.h" #include "pygi-util.h" static PyObject * _ccallback_vectorcall (PyGICCallback *self, PyObject *const *args, size_t nargsf, PyObject *kwnames) { PyObject *result; if (self->cache == NULL) { self->cache = (PyGICCallbackCache *)pygi_ccallback_cache_new ( GI_CALLABLE_INFO (self->info), self->callback); if (self->cache == NULL) return NULL; } result = pygi_ccallback_cache_invoke (self->cache, args, nargsf, kwnames, self->user_data); return result; } PYGI_DEFINE_TYPE ("gi.CCallback", PyGICCallback_Type, PyGICCallback); PyObject * _pygi_ccallback_new (GCallback callback, gpointer user_data, GIScopeType scope, GICallableInfo *info, GDestroyNotify destroy_notify) { PyGICCallback *self; if (!callback) { Py_RETURN_NONE; } self = (PyGICCallback *)PyGICCallback_Type.tp_alloc (&PyGICCallback_Type, 0); if (self == NULL) { return NULL; } self->callback = (GCallback)callback; self->user_data = user_data; self->scope = scope; self->destroy_notify_func = destroy_notify; self->info = GI_CALLABLE_INFO (gi_base_info_ref (info)); self->vectorcall = (vectorcallfunc)_ccallback_vectorcall; return (PyObject *)self; } static void _ccallback_dealloc (PyGICCallback *self) { gi_base_info_unref ((GIBaseInfo *)self->info); if (self->cache != NULL) { pygi_callable_cache_free ((PyGICallableCache *)self->cache); } Py_TYPE (self)->tp_free ((PyObject *)self); } /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_ccallback_register_types (PyObject *m) { Py_SET_TYPE (&PyGICCallback_Type, &PyType_Type); PyGICCallback_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL); PyGICCallback_Type.tp_dealloc = (destructor)_ccallback_dealloc; PyGICCallback_Type.tp_call = PyVectorcall_Call; PyGICCallback_Type.tp_vectorcall_offset = offsetof (PyGICCallback, vectorcall); if (PyType_Ready (&PyGICCallback_Type) < 0) return -1; Py_INCREF ((PyObject *)&PyGICCallback_Type); if (PyModule_AddObject (m, "CCallback", (PyObject *)&PyGICCallback_Type) < 0) { Py_DECREF ((PyObject *)&PyGICCallback_Type); return -1; } return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-ccallback.h0000664000000000000000000000302615074673150015764 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri , Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_CCLOSURE_H__ #define __PYGI_CCLOSURE_H__ #include #include "pygi-cache.h" G_BEGIN_DECLS typedef struct { PyObject_HEAD GCallback callback; GICallableInfo *info; gpointer user_data; GIScopeType scope; GDestroyNotify destroy_notify_func; PyGICCallbackCache *cache; vectorcallfunc vectorcall; } PyGICCallback; extern PyTypeObject PyGICCallback_Type; PyObject *_pygi_ccallback_new (GCallback callback, gpointer user_data, GIScopeType scope, GICallableInfo *info, GDestroyNotify destroy_notify); int pygi_ccallback_register_types (PyObject *m); G_END_DECLS #endif /* __PYGI_CCLOSURE_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-closure.c0000664000000000000000000010105015074673150015530 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * pygi-closure.c: PyGI C Closure functions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-closure.h" #include "pygi-async.h" #include "pygi-ccallback.h" #include "pygi-error.h" #include "pygi-info.h" #include "pygi-invoke.h" #include "pygi-marshal-cleanup.h" extern PyObject *_PyGIDefaultArgPlaceholder; typedef struct _PyGICallbackCache { PyGIArgCache arg_cache; unsigned int user_data_index; gboolean has_user_data; unsigned int destroy_notify_index; gboolean has_destroy_notify; GIScopeType scope; GIBaseInfo *interface_info; PyGIClosureCache *closure_cache; } PyGICallbackCache; /* This maintains a list of closures which can be free'd whenever as they have been called. We will free them on the next library function call. */ static GSList *async_free_list; static void _pygi_closure_assign_pyobj_to_retval (gpointer retval, GIArgument *arg, PyGIArgCache *arg_cache) { if (retval == NULL) return; switch (arg_cache->type_tag) { case GI_TYPE_TAG_BOOLEAN: *((ffi_sarg *)retval) = arg->v_boolean; break; case GI_TYPE_TAG_INT8: *((ffi_sarg *)retval) = arg->v_int8; break; case GI_TYPE_TAG_UINT8: *((ffi_arg *)retval) = arg->v_uint8; break; case GI_TYPE_TAG_INT16: *((ffi_sarg *)retval) = arg->v_int16; break; case GI_TYPE_TAG_UINT16: *((ffi_arg *)retval) = arg->v_uint16; break; case GI_TYPE_TAG_INT32: *((ffi_sarg *)retval) = arg->v_int32; break; case GI_TYPE_TAG_UINT32: *((ffi_arg *)retval) = arg->v_uint32; break; case GI_TYPE_TAG_INT64: *((ffi_sarg *)retval) = arg->v_int64; break; case GI_TYPE_TAG_UINT64: *((ffi_arg *)retval) = arg->v_uint64; break; case GI_TYPE_TAG_FLOAT: *((gfloat *)retval) = arg->v_float; break; case GI_TYPE_TAG_DOUBLE: *((gdouble *)retval) = arg->v_double; break; case GI_TYPE_TAG_GTYPE: *((ffi_arg *)retval) = arg->v_size; break; case GI_TYPE_TAG_UNICHAR: *((ffi_arg *)retval) = arg->v_uint32; break; case GI_TYPE_TAG_INTERFACE: { GIRegisteredTypeInfo *interface_info; interface_info = ((PyGIInterfaceCache *)arg_cache)->interface_info; if (GI_IS_FLAGS_INFO (interface_info)) { /* Check flags before enums: flags are a subtype of enum. */ *(ffi_arg *)retval = arg->v_uint; } else if (GI_IS_ENUM_INFO (interface_info)) { *(ffi_sarg *)retval = arg->v_int; } else { *(ffi_arg *)retval = (ffi_arg)arg->v_pointer; } break; } default: *(ffi_arg *)retval = (ffi_arg)arg->v_pointer; break; } } static void _pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, GIArgument *arg, PyGIArgCache *arg_cache) { if (out_arg == NULL) return; switch (arg_cache->type_tag) { case GI_TYPE_TAG_BOOLEAN: *((gboolean *)out_arg) = arg->v_boolean; break; case GI_TYPE_TAG_INT8: *((gint8 *)out_arg) = arg->v_int8; break; case GI_TYPE_TAG_UINT8: *((guint8 *)out_arg) = arg->v_uint8; break; case GI_TYPE_TAG_INT16: *((gint16 *)out_arg) = arg->v_int16; break; case GI_TYPE_TAG_UINT16: *((guint16 *)out_arg) = arg->v_uint16; break; case GI_TYPE_TAG_INT32: *((gint32 *)out_arg) = arg->v_int32; break; case GI_TYPE_TAG_UINT32: *((guint32 *)out_arg) = arg->v_uint32; break; case GI_TYPE_TAG_INT64: *((gint64 *)out_arg) = arg->v_int64; break; case GI_TYPE_TAG_UINT64: *((guint64 *)out_arg) = arg->v_uint64; break; case GI_TYPE_TAG_FLOAT: *((gfloat *)out_arg) = arg->v_float; break; case GI_TYPE_TAG_DOUBLE: *((gdouble *)out_arg) = arg->v_double; break; case GI_TYPE_TAG_GTYPE: *((GType *)out_arg) = arg->v_size; break; case GI_TYPE_TAG_UNICHAR: *((guint32 *)out_arg) = arg->v_uint32; break; case GI_TYPE_TAG_INTERFACE: { GIRegisteredTypeInfo *interface_info; interface_info = ((PyGIInterfaceCache *)arg_cache)->interface_info; if (GI_IS_FLAGS_INFO (interface_info)) { /* Check flags before enums: flags are a subtype of enum. */ *(guint *)out_arg = arg->v_uint; } else if (GI_IS_ENUM_INFO (interface_info)) { *(gint *)out_arg = arg->v_int; } else if (GI_IS_STRUCT_INFO (interface_info)) { if (!arg_cache->is_pointer) { if (arg->v_pointer != NULL) { gsize item_size = _pygi_gi_type_info_size (arg_cache->type_info); memcpy (out_arg, arg->v_pointer, item_size); } } else { *((gpointer *)out_arg) = arg->v_pointer; } } else { *((gpointer *)out_arg) = arg->v_pointer; } break; } default: *((gpointer *)out_arg) = arg->v_pointer; break; } } static void _pygi_closure_convert_ffi_arguments (PyGIInvokeArgState *state, PyGICallableCache *cache, void **args) { guint i; for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) { PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i); gpointer arg_pointer; if (arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) { state[i].arg_value.v_pointer = *(gpointer *)args[i]; if (state[i].arg_value.v_pointer == NULL) continue; state[i].arg_pointer.v_pointer = state[i].arg_value.v_pointer; arg_pointer = state[i].arg_value.v_pointer; } else { arg_pointer = args[i]; } switch (arg_cache->type_tag) { case GI_TYPE_TAG_BOOLEAN: state[i].arg_value.v_boolean = *(gboolean *)arg_pointer; break; case GI_TYPE_TAG_INT8: state[i].arg_value.v_int8 = *(gint8 *)arg_pointer; break; case GI_TYPE_TAG_UINT8: state[i].arg_value.v_uint8 = *(guint8 *)arg_pointer; break; case GI_TYPE_TAG_INT16: state[i].arg_value.v_int16 = *(gint16 *)arg_pointer; break; case GI_TYPE_TAG_UINT16: state[i].arg_value.v_uint16 = *(guint16 *)arg_pointer; break; case GI_TYPE_TAG_INT32: state[i].arg_value.v_int32 = *(gint32 *)arg_pointer; break; case GI_TYPE_TAG_UINT32: state[i].arg_value.v_uint32 = *(guint32 *)arg_pointer; break; case GI_TYPE_TAG_INT64: state[i].arg_value.v_int64 = *(gint64 *)arg_pointer; break; case GI_TYPE_TAG_UINT64: state[i].arg_value.v_uint64 = *(guint64 *)arg_pointer; break; case GI_TYPE_TAG_FLOAT: state[i].arg_value.v_float = *(gfloat *)arg_pointer; break; case GI_TYPE_TAG_DOUBLE: state[i].arg_value.v_double = *(gdouble *)arg_pointer; break; case GI_TYPE_TAG_UTF8: state[i].arg_value.v_string = *(gchar **)arg_pointer; break; case GI_TYPE_TAG_INTERFACE: { GIRegisteredTypeInfo *interface; interface = ((PyGIInterfaceCache *)arg_cache)->interface_info; if (GI_IS_FLAGS_INFO (interface)) { /* Check flags before enums: flags are a subtype of enum. */ state[i].arg_value.v_uint = *(guint *)arg_pointer; } else if (GI_IS_ENUM_INFO (interface)) { state[i].arg_value.v_int = *(gint *)arg_pointer; } else { state[i].arg_value.v_pointer = *(gpointer *)arg_pointer; } break; } case GI_TYPE_TAG_UNICHAR: state[i].arg_value.v_uint32 = *(guint32 *)arg_pointer; break; case GI_TYPE_TAG_ERROR: case GI_TYPE_TAG_GHASH: case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_ARRAY: case GI_TYPE_TAG_VOID: state[i].arg_value.v_pointer = *(gpointer *)arg_pointer; break; default: g_warning ("Unhandled type tag %s", gi_type_tag_to_string (arg_cache->type_tag)); state[i].arg_value.v_pointer = 0; } } if (cache->throws) { gssize error_index = _pygi_callable_cache_args_len (cache); state[error_index].arg_value.v_pointer = *(gpointer *)args[error_index]; } } static gboolean _invoke_state_init_from_cache (PyGIInvokeState *state, PyGIClosureCache *closure_cache, void **args) { PyGICallableCache *cache = (PyGICallableCache *)closure_cache; state->n_args = _pygi_callable_cache_args_len (cache); state->n_py_in_args = state->n_args; /* Increment after setting the number of Python input args */ if (cache->throws) { state->n_args++; } state->py_in_args = PyTuple_New (state->n_py_in_args); if (state->py_in_args == NULL) { PyErr_NoMemory (); return FALSE; } state->args = NULL; state->error = NULL; if (!_pygi_invoke_arg_state_init (state)) { return FALSE; } state->ffi_args = NULL; _pygi_closure_convert_ffi_arguments (state->args, cache, args); return TRUE; } static void _invoke_state_clear (PyGIInvokeState *state) { _pygi_invoke_arg_state_free (state); Py_XDECREF (state->py_in_args); } static gboolean _pygi_closure_convert_arguments (PyGIInvokeState *state, PyGIClosureCache *closure_cache) { PyGICallableCache *cache = (PyGICallableCache *)closure_cache; gssize n_in_args = 0; gssize i; for (i = 0; (gsize)i < _pygi_callable_cache_args_len (cache); i++) { PyGIArgCache *arg_cache; arg_cache = g_ptr_array_index (cache->args_cache, i); if (arg_cache->direction & PYGI_DIRECTION_TO_PYTHON) { PyObject *value; if (cache->has_user_data && ((gssize)cache->user_data_index) == i) { if (state->user_data == NULL) { /* user_data can be NULL for connect functions which don't accept * user_data or as the default for user_data in the middle of function * arguments. */ Py_INCREF (Py_None); value = Py_None; } else { /* Extend the callbacks args with user_data as variable args. */ gssize j, user_data_len; PyObject *py_user_data = state->user_data; if (!PyTuple_Check (py_user_data)) { PyErr_SetString ( PyExc_TypeError, "expected tuple for callback user_data"); return FALSE; } user_data_len = PyTuple_Size (py_user_data); _PyTuple_Resize (&state->py_in_args, state->n_py_in_args + user_data_len - 1); for (j = 0; j < user_data_len; j++, n_in_args++) { value = PyTuple_GetItem (py_user_data, j); Py_INCREF (value); PyTuple_SET_ITEM (state->py_in_args, n_in_args, value); } /* We can assume user_data args are never going to be inout, * so just continue here. */ continue; } } else if (arg_cache->meta_type != PYGI_META_ARG_TYPE_PARENT) { continue; } else { gpointer cleanup_data = NULL; value = arg_cache->to_py_marshaller (state, cache, arg_cache, &state->args[i].arg_value, &cleanup_data); state->args[i].to_py_arg_cleanup_data = cleanup_data; if (value == NULL) { pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, i); return FALSE; } } PyTuple_SET_ITEM (state->py_in_args, n_in_args, value); n_in_args++; } } if (_PyTuple_Resize (&state->py_in_args, n_in_args) == -1) return FALSE; return TRUE; } static gboolean _pygi_closure_set_out_arguments (PyGIInvokeState *state, PyGICallableCache *cache, PyObject *py_retval, void *resp) { gssize i; gssize i_py_retval = 0; gboolean success; if (cache->return_cache->type_tag != GI_TYPE_TAG_VOID) { PyObject *item = py_retval; if (PyTuple_Check (py_retval)) { item = PyTuple_GET_ITEM (py_retval, 0); } success = cache->return_cache->from_py_marshaller ( state, cache, cache->return_cache, item, &state->return_arg, &state->args[0].arg_cleanup_data); if (!success) { pygi_marshal_cleanup_args_return_fail (state, cache); return FALSE; } _pygi_closure_assign_pyobj_to_retval (resp, &state->return_arg, cache->return_cache); i_py_retval++; } for (i = 0; (gsize)i < _pygi_callable_cache_args_len (cache); i++) { PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i); if (arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) { PyObject *item = py_retval; if (arg_cache->type_tag == GI_TYPE_TAG_ERROR) { *(GError **)state->args[i].arg_pointer.v_pointer = NULL; continue; } if (PyTuple_Check (py_retval)) { item = PyTuple_GET_ITEM (py_retval, i_py_retval); } else if (i_py_retval != 0) { pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, i_py_retval); return FALSE; } success = arg_cache->from_py_marshaller ( state, cache, arg_cache, item, &state->args[i].arg_value, &state->args[i_py_retval].arg_cleanup_data); if (!success) { pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, i_py_retval); return FALSE; } _pygi_closure_assign_pyobj_to_out_argument ( state->args[i].arg_pointer.v_pointer, &state->args[i].arg_value, arg_cache); i_py_retval++; } } return TRUE; } static void _pygi_closure_clear_retvals (PyGIInvokeState *state, PyGICallableCache *cache, gpointer resp) { gsize i; GIArgument arg = { 0, }; if (cache->return_cache->type_tag != GI_TYPE_TAG_VOID) { _pygi_closure_assign_pyobj_to_retval (resp, &arg, cache->return_cache); } for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) { PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i); if (arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) { _pygi_closure_assign_pyobj_to_out_argument ( state->args[i].arg_pointer.v_pointer, &arg, arg_cache); } } if (cache->throws) { gssize error_index = state->n_args - 1; GError **error = (GError **)state->args[error_index].arg_value.v_pointer; if (error != NULL) { pygi_gerror_exception_check (error); } } } static void _pygi_invoke_closure_clear_py_data (PyGICClosure *invoke_closure) { PyGILState_STATE state = PyGILState_Ensure (); Py_CLEAR (invoke_closure->function); Py_CLEAR (invoke_closure->user_data); PyGILState_Release (state); } void _pygi_closure_handle (ffi_cif *cif, void *result, void **args, void *data) { PyGILState_STATE py_state; PyGICClosure *closure = data; PyObject *retval; gboolean success; PyGIInvokeState state = { 0, }; /* Ignore closures when Python is not initialized. This can happen in cases * where calling Python implemented vfuncs can happen at shutdown time. * See: https://bugzilla.gnome.org/show_bug.cgi?id=722562 */ if (!Py_IsInitialized ()) { return; } /* Lock the GIL as we are coming into this code without the lock and we may be executing python code */ py_state = PyGILState_Ensure (); if (closure->cache == NULL) goto end; state.user_data = closure->user_data; _invoke_state_init_from_cache (&state, closure->cache, args); if (!_pygi_closure_convert_arguments (&state, closure->cache)) { _pygi_closure_clear_retvals (&state, closure->cache, result); goto end; } retval = PyObject_CallObject ((PyObject *)closure->function, state.py_in_args); if (retval == NULL) { _pygi_closure_clear_retvals (&state, closure->cache, result); goto end; } pygi_marshal_cleanup_args_to_py_marshal_success (&state, closure->cache); success = _pygi_closure_set_out_arguments (&state, closure->cache, retval, result); if (!success) { pygi_marshal_cleanup_args_from_py_marshal_success (&state, closure->cache); _pygi_closure_clear_retvals (&state, closure->cache, result); } Py_DECREF (retval); end: if (PyErr_Occurred ()) PyErr_Print (); /* Now that the closure has finished we can make a decision about how to free it. Scope call gets free'd at the end of wrap_gi_function_info_invoke. Scope notified will be freed when the notify is called. Scope async closures free only their python data now and the closure later during the next creation of a closure. This minimizes potential ref leaks at least in regards to the python objects. (you can't free the closure you are currently using!) */ switch (closure->scope) { case GI_SCOPE_TYPE_CALL: case GI_SCOPE_TYPE_NOTIFIED: break; case GI_SCOPE_TYPE_ASYNC: /* Append this PyGICClosure to a list of closure that we will free after we're done with this function invokation */ _pygi_invoke_closure_clear_py_data (closure); async_free_list = g_slist_prepend (async_free_list, closure); break; default: /* Handle new scopes added by gobject-introspection */ g_critical ( "Unknown scope reached inside %s. Please file an issue " "at https://gitlab.gnome.org/GNOME/pygobject/issues/new", gi_base_info_get_name (GI_BASE_INFO (closure->info))); } _invoke_state_clear (&state); PyGILState_Release (py_state); } void _pygi_invoke_closure_free (PyGICClosure *invoke_closure) { gi_callable_info_destroy_closure (invoke_closure->info, invoke_closure->closure); if (invoke_closure->info) gi_base_info_unref ((GIBaseInfo *)invoke_closure->info); invoke_closure->cache = NULL; _pygi_invoke_closure_clear_py_data (invoke_closure); g_slice_free (PyGICClosure, invoke_closure); } PyGICClosure * _pygi_make_native_closure (GICallableInfo *info, PyGIClosureCache *cache, GIScopeType scope, PyObject *py_function, PyObject *py_user_data) { PyGICClosure *closure; ffi_closure *fficlosure; /* Begin by cleaning up old async functions */ g_slist_free_full (async_free_list, (GDestroyNotify)_pygi_invoke_closure_free); async_free_list = NULL; /* Build the closure itself */ closure = g_slice_new0 (PyGICClosure); closure->info = (GICallableInfo *)gi_base_info_ref ((GIBaseInfo *)info); closure->function = py_function; closure->user_data = py_user_data; closure->cache = cache; Py_INCREF (py_function); Py_XINCREF (closure->user_data); fficlosure = gi_callable_info_create_closure ( info, &closure->cif, _pygi_closure_handle, closure); closure->closure = fficlosure; /* Give the closure the information it needs to determine when to free itself later */ closure->scope = scope; return closure; } /* _pygi_destroy_notify_dummy: * * Dummy method used in the occasion when a method has a GDestroyNotify * argument without user data. */ static void _pygi_destroy_notify_dummy (gpointer data) { } static gboolean _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { GICallableInfo *callable_info; PyGICClosure *closure; PyGIArgCache *user_data_cache = NULL; PyGIArgCache *destroy_cache = NULL; PyGICallbackCache *callback_cache; PyObject *py_user_data = NULL; callback_cache = (PyGICallbackCache *)arg_cache; if (py_arg == _PyGIDefaultArgPlaceholder) { /* We need to have an async to "marshal" instead in this case. */ if (!state->py_async) return FALSE; if (callback_cache->user_data_index <= 0) return FALSE; user_data_cache = _pygi_callable_cache_get_arg ( callable_cache, callback_cache->user_data_index); Py_INCREF (state->py_async); arg->v_pointer = pygi_async_finish_cb; state->args[user_data_cache->c_arg_index].arg_value.v_pointer = state->py_async; return TRUE; } if (callback_cache->has_user_data && callback_cache->user_data_index > 0) { user_data_cache = _pygi_callable_cache_get_arg ( callable_cache, callback_cache->user_data_index); if (user_data_cache->py_arg_index < state->n_py_in_args) { /* py_user_data is a borrowed reference. */ py_user_data = PyTuple_GetItem (state->py_in_args, user_data_cache->py_arg_index); if (!py_user_data) return FALSE; /* NULL out user_data if it was not supplied and the default arg placeholder * was used instead. */ if (py_user_data == _PyGIDefaultArgPlaceholder) { py_user_data = NULL; } else if (callable_cache->user_data_varargs_arg == NULL) { /* For non-variable length user data, place the user data in a * single item tuple which is concatenated to the callbacks arguments. * This allows callback input arg marshaling to always expect a * tuple for user data. Note the */ py_user_data = Py_BuildValue ("(O)", py_user_data, NULL); } else { /* increment the ref borrowed from PyTuple_GetItem above */ Py_INCREF (py_user_data); } } } if (Py_IsNone (py_arg)) { return TRUE; } if (!PyCallable_Check (py_arg)) { PyErr_Format (PyExc_TypeError, "Callback needs to be a function or method not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } callable_info = (GICallableInfo *)callback_cache->interface_info; closure = _pygi_make_native_closure ( callable_info, callback_cache->closure_cache, callback_cache->scope, py_arg, py_user_data); if (closure->closure != NULL) arg->v_pointer = gi_callable_info_get_closure_native_address ( callable_info, closure->closure); else arg->v_pointer = NULL; /* always decref the user data as _pygi_make_native_closure adds its own ref */ Py_XDECREF (py_user_data); /* The PyGICClosure instance is used as user data passed into the C function. * The return trip to python will marshal this back and pull the python user data out. */ if (user_data_cache != NULL) { state->args[user_data_cache->c_arg_index].arg_value.v_pointer = closure; } /* Setup a GDestroyNotify callback if this method supports it along with * a user data field. The user data field is a requirement in order * free resources and ref counts associated with this arguments closure. * In case a user data field is not available, show a warning giving * explicit information and setup a dummy notification to avoid a crash * later on in _pygi_destroy_notify_callback_closure. */ if (callback_cache->has_destroy_notify && callback_cache->destroy_notify_index > 0) { destroy_cache = _pygi_callable_cache_get_arg ( callable_cache, callback_cache->destroy_notify_index); } if (destroy_cache) { if (user_data_cache != NULL) { state->args[destroy_cache->c_arg_index].arg_value.v_pointer = _pygi_invoke_closure_free; } else { char *full_name = pygi_callable_cache_get_full_name (callable_cache); gchar *msg = g_strdup_printf ( "Callables passed to %s will leak references because " "the method does not support a user_data argument. " "See: https://bugzilla.gnome.org/show_bug.cgi?id=685598", full_name); g_free (full_name); if (PyErr_WarnEx (PyExc_RuntimeWarning, msg, 2)) { g_free (msg); _pygi_invoke_closure_free (closure); return FALSE; } g_free (msg); state->args[destroy_cache->c_arg_index].arg_value.v_pointer = _pygi_destroy_notify_dummy; } } /* Use the PyGIClosure as data passed to cleanup for GI_SCOPE_TYPE_CALL. */ *cleanup_data = closure; return TRUE; } static PyObject * _pygi_marshal_to_py_interface_callback (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *arg_cleanup_data) { PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache; gpointer user_data = NULL; GDestroyNotify destroy_notify = NULL; if (callback_cache->has_user_data) user_data = state->args[callback_cache->user_data_index].arg_value.v_pointer; if (callback_cache->has_destroy_notify) destroy_notify = state->args[callback_cache->destroy_notify_index] .arg_value.v_pointer; return _pygi_ccallback_new ( arg->v_pointer, user_data, callback_cache->scope, GI_CALLABLE_INFO (callback_cache->interface_info), destroy_notify); } static void _callback_cache_free_func (PyGICallbackCache *cache) { if (cache != NULL) { if (cache->interface_info != NULL) gi_base_info_unref ((GIBaseInfo *)cache->interface_info); if (cache->closure_cache != NULL) { pygi_callable_cache_free ( (PyGICallableCache *)cache->closure_cache); cache->closure_cache = NULL; } g_slice_free (PyGICallbackCache, cache); } } static void _pygi_marshal_cleanup_from_py_interface_callback (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed) { PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache; if (was_processed && callback_cache->scope == GI_SCOPE_TYPE_CALL) { _pygi_invoke_closure_free (data); } } static gboolean pygi_arg_callback_setup_from_info (PyGICallbackCache *arg_cache, GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, GICallbackInfo *iface_info, PyGICallableCache *callable_cache) { PyGIArgCache *cache = (PyGIArgCache *)arg_cache; gssize child_offset = 0; if (!pygi_arg_base_setup ((PyGIArgCache *)arg_cache, type_info, arg_info, transfer, direction)) { return FALSE; } if (callable_cache != NULL) child_offset = callable_cache->args_offset; ((PyGIArgCache *)arg_cache)->destroy_notify = (GDestroyNotify)_callback_cache_free_func; arg_cache->has_user_data = gi_arg_info_get_closure_index (arg_info, &arg_cache->user_data_index); if (arg_cache->has_user_data) arg_cache->user_data_index += child_offset; arg_cache->has_destroy_notify = gi_arg_info_get_destroy_index ( arg_info, &arg_cache->destroy_notify_index); if (arg_cache->has_destroy_notify) arg_cache->destroy_notify_index += child_offset; if (arg_cache->has_user_data) { PyGIArgCache *user_data_arg_cache = pygi_arg_cache_alloc (); user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG; user_data_arg_cache->direction = direction; user_data_arg_cache->allow_none = TRUE; /* always allow user data with a NULL default. */ _pygi_callable_cache_set_arg ( callable_cache, arg_cache->user_data_index, user_data_arg_cache); } if (arg_cache->has_destroy_notify) { PyGIArgCache *destroy_arg_cache = pygi_arg_cache_alloc (); destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD; destroy_arg_cache->direction = direction; _pygi_callable_cache_set_arg (callable_cache, arg_cache->destroy_notify_index, destroy_arg_cache); } arg_cache->scope = gi_arg_info_get_scope (arg_info); gi_base_info_ref (iface_info); arg_cache->interface_info = GI_BASE_INFO (iface_info); if (direction & PYGI_DIRECTION_FROM_PYTHON) { arg_cache->closure_cache = pygi_closure_cache_new ( GI_CALLABLE_INFO (arg_cache->interface_info)); cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback; cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback; if (arg_cache->scope == GI_SCOPE_TYPE_ASYNC) arg_cache->arg_cache.async_context = PYGI_ASYNC_CONTEXT_CALLBACK; } if (direction & PYGI_DIRECTION_TO_PYTHON) { cache->to_py_marshaller = _pygi_marshal_to_py_interface_callback; } return TRUE; } PyGIArgCache * pygi_arg_callback_new_from_info (GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, GICallbackInfo *iface_info, PyGICallableCache *callable_cache) { gboolean res = FALSE; PyGICallbackCache *callback_cache; callback_cache = g_slice_new0 (PyGICallbackCache); if (callback_cache == NULL) return NULL; res = pygi_arg_callback_setup_from_info (callback_cache, type_info, arg_info, transfer, direction, iface_info, callable_cache); if (res) { return (PyGIArgCache *)callback_cache; } else { pygi_arg_cache_free ((PyGIArgCache *)callback_cache); return NULL; } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-closure.h0000664000000000000000000000405015074673150015537 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_CLOSURE_H__ #define __PYGI_CLOSURE_H__ /* Workaround for FFI_GO_CLOSURES not being defined on macOS * See also: https://github.com/openjdk/jdk17u-dev/pull/741 */ #ifndef FFI_GO_CLOSURES #define FFI_GO_CLOSURES 0 #endif #include #include #include #include "pygi-cache.h" G_BEGIN_DECLS /* Private */ typedef struct _PyGICClosure { GICallableInfo *info; PyObject *function; ffi_closure *closure; ffi_cif cif; GIScopeType scope; PyObject *user_data; PyGIClosureCache *cache; } PyGICClosure; void _pygi_closure_handle (ffi_cif *cif, void *result, void **args, void *userdata); void _pygi_invoke_closure_free (PyGICClosure *invoke_closure); PyGICClosure *_pygi_make_native_closure (GICallableInfo *info, PyGIClosureCache *cache, GIScopeType scope, PyObject *function, PyObject *user_data); PyGIArgCache *pygi_arg_callback_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, GICallbackInfo *iface_info, PyGICallableCache *callable_cache); G_END_DECLS #endif /* __PYGI_CLOSURE_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-enum-marshal.c0000664000000000000000000002612015074673150016451 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-type.h" #include "pygenum.h" #include "pygflags.h" #include "pygi-enum-marshal.h" static gboolean gi_argument_from_c_long (GIArgument *arg_out, long c_long_in, GITypeTag type_tag) { switch (type_tag) { case GI_TYPE_TAG_INT8: arg_out->v_int8 = (gint8)c_long_in; return TRUE; case GI_TYPE_TAG_UINT8: arg_out->v_uint8 = (guint8)c_long_in; return TRUE; case GI_TYPE_TAG_INT16: arg_out->v_int16 = (gint16)c_long_in; return TRUE; case GI_TYPE_TAG_UINT16: arg_out->v_uint16 = (guint16)c_long_in; return TRUE; case GI_TYPE_TAG_INT32: arg_out->v_int32 = (gint32)c_long_in; return TRUE; case GI_TYPE_TAG_UINT32: arg_out->v_uint32 = (guint32)c_long_in; return TRUE; case GI_TYPE_TAG_INT64: arg_out->v_int64 = (gint64)c_long_in; return TRUE; case GI_TYPE_TAG_UINT64: arg_out->v_uint64 = (guint64)c_long_in; return TRUE; default: PyErr_Format (PyExc_TypeError, "Unable to marshal C long %ld to %s", c_long_in, gi_type_tag_to_string (type_tag)); return FALSE; } } static gboolean gi_argument_to_c_long (GIArgument *arg_in, long *c_long_out, GITypeTag type_tag) { switch (type_tag) { case GI_TYPE_TAG_INT8: *c_long_out = arg_in->v_int8; return TRUE; case GI_TYPE_TAG_UINT8: *c_long_out = arg_in->v_uint8; return TRUE; case GI_TYPE_TAG_INT16: *c_long_out = arg_in->v_int16; return TRUE; case GI_TYPE_TAG_UINT16: *c_long_out = arg_in->v_uint16; return TRUE; case GI_TYPE_TAG_INT32: *c_long_out = arg_in->v_int32; return TRUE; case GI_TYPE_TAG_UINT32: *c_long_out = arg_in->v_uint32; return TRUE; case GI_TYPE_TAG_INT64: if (arg_in->v_int64 > G_MAXLONG || arg_in->v_int64 < G_MINLONG) { PyErr_Format (PyExc_TypeError, "Unable to marshal %s to C long", gi_type_tag_to_string (type_tag)); return FALSE; } *c_long_out = (glong)arg_in->v_int64; return TRUE; case GI_TYPE_TAG_UINT64: if (arg_in->v_uint64 > G_MAXLONG) { PyErr_Format (PyExc_TypeError, "Unable to marshal %s to C long", gi_type_tag_to_string (type_tag)); return FALSE; } *c_long_out = (glong)arg_in->v_uint64; return TRUE; default: PyErr_Format (PyExc_TypeError, "Unable to marshal %s to C long", gi_type_tag_to_string (type_tag)); return FALSE; } } static gboolean _pygi_marshal_from_py_interface_enum (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { PyObject *py_long; long c_long; gint is_instance; PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; GIBaseInfo *interface = NULL; is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type); py_long = PyNumber_Long (py_arg); if (py_long == NULL) { PyErr_Clear (); goto err; } c_long = PyLong_AsLong (py_long); Py_DECREF (py_long); /* Write c_long into arg */ interface = gi_type_info_get_interface (arg_cache->type_info); g_assert (GI_IS_ENUM_INFO (interface)); if (!gi_argument_from_c_long ( arg, c_long, gi_enum_info_get_storage_type ((GIEnumInfo *)interface))) { g_assert_not_reached (); gi_base_info_unref (interface); return FALSE; } /* If this is not an instance of the Enum type that we want * we need to check if the value is equivilant to one of the * Enum's memebers */ if (!is_instance) { unsigned int i; gboolean is_found = FALSE; for (i = 0; i < gi_enum_info_get_n_values ( GI_ENUM_INFO (iface_cache->interface_info)); i++) { GIValueInfo *value_info = gi_enum_info_get_value ( GI_ENUM_INFO (iface_cache->interface_info), i); gint64 enum_value = gi_value_info_get_value (value_info); gi_base_info_unref ((GIBaseInfo *)value_info); if (c_long == enum_value) { is_found = TRUE; break; } } if (!is_found) goto err; } gi_base_info_unref (interface); return TRUE; err: if (interface) gi_base_info_unref (interface); PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s", iface_cache->type_name, Py_TYPE (py_arg)->tp_name); return FALSE; } static gboolean _pygi_marshal_from_py_interface_flags (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { PyObject *py_long; unsigned long c_ulong; gint is_instance; PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; GIBaseInfo *interface; is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type); py_long = PyNumber_Long (py_arg); if (py_long == NULL) { PyErr_Clear (); goto err; } c_ulong = PyLong_AsUnsignedLongMask (py_long); Py_DECREF (py_long); /* only 0 or argument of type Flag is allowed */ if (!is_instance && c_ulong != 0) goto err; /* Write c_long into arg */ interface = gi_type_info_get_interface (arg_cache->type_info); g_assert (GI_IS_FLAGS_INFO (interface)); if (!gi_argument_from_c_long ( arg, c_ulong, gi_enum_info_get_storage_type ((GIEnumInfo *)interface))) { gi_base_info_unref (interface); return FALSE; } gi_base_info_unref (interface); return TRUE; err: PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s", iface_cache->type_name, Py_TYPE (py_arg)->tp_name); return FALSE; } static PyObject * _pygi_marshal_to_py_interface_enum (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; GIBaseInfo *interface; long c_long; interface = gi_type_info_get_interface (arg_cache->type_info); g_assert (GI_IS_ENUM_INFO (interface) && !GI_IS_FLAGS_INFO (interface)); if (!gi_argument_to_c_long ( arg, &c_long, gi_enum_info_get_storage_type ((GIEnumInfo *)interface))) { return NULL; } gi_base_info_unref (interface); return pyg_enum_val_new (iface_cache->py_type, c_long); } static PyObject * _pygi_marshal_to_py_interface_flags (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; GIBaseInfo *interface; long c_long; interface = gi_type_info_get_interface (arg_cache->type_info); g_assert (GI_IS_FLAGS_INFO (interface)); if (!gi_argument_to_c_long ( arg, &c_long, gi_enum_info_get_storage_type ((GIEnumInfo *)interface))) { gi_base_info_unref (interface); return NULL; } gi_base_info_unref (interface); return pyg_flags_val_new (iface_cache->py_type, (guint)c_long); } static gboolean pygi_arg_enum_setup_from_info (PyGIArgCache *arg_cache, GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction) { if (direction & PYGI_DIRECTION_FROM_PYTHON) arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum; if (direction & PYGI_DIRECTION_TO_PYTHON) arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum; return TRUE; } PyGIArgCache * pygi_arg_enum_new_from_info (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, GIEnumInfo *iface_info) { gboolean res = FALSE; PyGIArgCache *cache = NULL; cache = pygi_arg_interface_new_from_info ( type_info, arg_info, transfer, direction, GI_REGISTERED_TYPE_INFO (iface_info)); if (cache == NULL) return NULL; res = pygi_arg_enum_setup_from_info (cache, type_info, arg_info, transfer, direction); if (res) { return cache; } else { pygi_arg_cache_free (cache); return NULL; } } static gboolean pygi_arg_flags_setup_from_info (PyGIArgCache *arg_cache, GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction) { if (direction & PYGI_DIRECTION_FROM_PYTHON) arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags; if (direction & PYGI_DIRECTION_TO_PYTHON) arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags; return TRUE; } PyGIArgCache * pygi_arg_flags_new_from_info (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, GIFlagsInfo *iface_info) { gboolean res = FALSE; PyGIArgCache *cache = NULL; cache = pygi_arg_interface_new_from_info ( type_info, arg_info, transfer, direction, GI_REGISTERED_TYPE_INFO (iface_info)); if (cache == NULL) return NULL; res = pygi_arg_flags_setup_from_info (cache, type_info, arg_info, transfer, direction); if (res) { return cache; } else { pygi_arg_cache_free (cache); return NULL; } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-enum-marshal.h0000664000000000000000000000254515074673150016463 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_ENUM_MARSHAL_H__ #define __PYGI_ENUM_MARSHAL_H__ #include #include "pygi-cache.h" G_BEGIN_DECLS PyGIArgCache *pygi_arg_enum_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, GIEnumInfo *iface_info); PyGIArgCache *pygi_arg_flags_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, GIFlagsInfo *iface_info); G_END_DECLS #endif /*__PYGI_ENUM_MARSHAL_H__*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-error.c0000664000000000000000000002337315074673150015220 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-basictype.h" #include "pygi-error.h" #include "pygi-type.h" #include "pygi-util.h" PyObject *PyGError = NULL; /** * pygi_error_marshal_to_py: * @error: a pointer to the GError. * * Checks to see if @error has been set. If @error has been set, then a * GLib.GError Python exception object is returned (but not raised). * If not error is set returns Py_None. * * Returns: a GLib.GError Python exception object, or Py_None, * or NULL and sets an error if creating the exception object fails. */ PyObject * pygi_error_marshal_to_py (GError **error) { PyGILState_STATE state; PyObject *exc_type; PyObject *exc_instance; const char *domain = NULL; g_return_val_if_fail (error != NULL, NULL); if (*error == NULL) Py_RETURN_NONE; state = PyGILState_Ensure (); exc_type = PyGError; if ((*error)->domain) { domain = g_quark_to_string ((*error)->domain); } exc_instance = PyObject_CallFunction (exc_type, "ssi", (*error)->message, domain, (*error)->code); PyGILState_Release (state); return exc_instance; } /** * pygi_error_check: * @error: a pointer to the GError. * * Checks to see if the GError has been set. If the error has been * set, then the glib.GError Python exception will be raised, and * the GError cleared. * * Returns: True if an error was set. */ gboolean pygi_error_check (GError **error) { PyGILState_STATE state; PyObject *exc_instance; g_return_val_if_fail (error != NULL, FALSE); if (*error == NULL) return FALSE; state = PyGILState_Ensure (); exc_instance = pygi_error_marshal_to_py (error); if (exc_instance != NULL) { PyErr_SetObject (PyGError, exc_instance); Py_DECREF (exc_instance); } else { PyErr_Print (); PyErr_SetString (PyExc_RuntimeError, "Converting the GError failed"); } g_clear_error (error); PyGILState_Release (state); return TRUE; } /** * pygi_error_marshal_from_py: * @pyerr: A Python exception instance. * @error: a standard GLib GError ** output parameter * * Converts from a Python implemented GError into a GError. * * Returns: TRUE if the conversion was successful, otherwise a Python exception * is set and FALSE is returned. */ gboolean pygi_error_marshal_from_py (PyObject *pyerr, GError **error) { gint code; gchar *message = NULL; gchar *domain = NULL; gboolean res = FALSE; PyObject *py_message = NULL, *py_domain = NULL, *py_code = NULL; if (PyObject_IsInstance (pyerr, PyGError) != 1) { PyErr_Format (PyExc_TypeError, "Must be GLib.Error, not %s", Py_TYPE (pyerr)->tp_name); return FALSE; } py_message = PyObject_GetAttrString (pyerr, "message"); if (!py_message) { PyErr_SetString ( PyExc_ValueError, "GLib.Error instances must have a 'message' string attribute"); goto cleanup; } if (!pygi_utf8_from_py (py_message, &message)) goto cleanup; py_domain = PyObject_GetAttrString (pyerr, "domain"); if (!py_domain) { PyErr_SetString ( PyExc_ValueError, "GLib.Error instances must have a 'domain' string attribute"); goto cleanup; } if (!pygi_utf8_from_py (py_domain, &domain)) goto cleanup; py_code = PyObject_GetAttrString (pyerr, "code"); if (!py_code) { PyErr_SetString ( PyExc_ValueError, "GLib.Error instances must have a 'code' int attribute"); goto cleanup; } if (!pygi_gint_from_py (py_code, &code)) goto cleanup; res = TRUE; g_set_error_literal (error, g_quark_from_string (domain), code, message); cleanup: g_free (message); g_free (domain); Py_XDECREF (py_message); Py_XDECREF (py_code); Py_XDECREF (py_domain); return res; } /** * pygi_gerror_exception_check: * @error: a standard GLib GError ** output parameter * * Checks to see if a GError exception has been raised, and if so * translates the python exception to a standard GLib GError. If the * raised exception is not a GError then PyErr_Print() is called. * * Returns: 0 if no exception has been raised, -1 if it is a * valid glib.GError, -2 otherwise. */ gboolean pygi_gerror_exception_check (GError **error) { int res = -1; PyObject *type, *value, *traceback; PyErr_Fetch (&type, &value, &traceback); if (type == NULL) return 0; PyErr_NormalizeException (&type, &value, &traceback); if (value == NULL) { PyErr_Restore (type, value, traceback); PyErr_Print (); return -2; } if (!value || !PyErr_GivenExceptionMatches (type, (PyObject *)PyGError)) { PyErr_Restore (type, value, traceback); PyErr_Print (); return -2; } Py_DECREF (type); Py_XDECREF (traceback); if (!pygi_error_marshal_from_py (value, error)) { PyErr_Print (); res = -2; } Py_DECREF (value); return res; } static gboolean _pygi_marshal_from_py_gerror (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { GError *error = NULL; if (Py_IsNone (py_arg)) { arg->v_pointer = NULL; *cleanup_data = NULL; return TRUE; } else if (pygi_error_marshal_from_py (py_arg, &error)) { arg->v_pointer = error; *cleanup_data = error; return TRUE; } else { return FALSE; } } static void _pygi_marshal_from_py_gerror_cleanup (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed) { if (was_processed) { g_error_free ((GError *)data); } } static PyObject * _pygi_marshal_to_py_gerror (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { GError *error = arg->v_pointer; PyObject *py_obj = NULL; py_obj = pygi_error_marshal_to_py (&error); if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && error != NULL) { g_error_free (error); } return py_obj; } static gboolean pygi_arg_gerror_setup_from_info (PyGIArgCache *arg_cache, GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction) { if (!pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction)) { return FALSE; } if (direction & PYGI_DIRECTION_FROM_PYTHON) { arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror; /* Assign cleanup function if we manage memory after call completion. */ if (arg_cache->transfer == GI_TRANSFER_NOTHING) { arg_cache->from_py_cleanup = _pygi_marshal_from_py_gerror_cleanup; } } if (direction & PYGI_DIRECTION_TO_PYTHON) { arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror; arg_cache->meta_type = PYGI_META_ARG_TYPE_PARENT; } return TRUE; } PyGIArgCache * pygi_arg_gerror_new_from_info (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction) { gboolean res = FALSE; PyGIArgCache *arg_cache; arg_cache = pygi_arg_cache_alloc (); res = pygi_arg_gerror_setup_from_info (arg_cache, type_info, arg_info, transfer, direction); if (res) { return arg_cache; } else { pygi_arg_cache_free (arg_cache); return NULL; } } static PyObject * pygerror_from_gvalue (const GValue *value) { GError *gerror = (GError *)g_value_get_boxed (value); PyObject *pyerr = pygi_error_marshal_to_py (&gerror); return pyerr; } static int pygerror_to_gvalue (GValue *value, PyObject *pyerror) { GError *gerror = NULL; if (pygi_error_marshal_from_py (pyerror, &gerror)) { g_value_take_boxed (value, gerror); return 0; } return -1; } /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_error_register_types (PyObject *module) { PyObject *error_module = PyImport_ImportModule ("gi._error"); if (!error_module) { return -1; } /* Stash a reference to the Python implemented gi._error.GError. */ PyGError = PyObject_GetAttrString (error_module, "GError"); Py_DECREF (error_module); if (PyGError == NULL) return -1; pyg_register_gtype_custom (G_TYPE_ERROR, pygerror_from_gvalue, pygerror_to_gvalue); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-error.h0000664000000000000000000000300615074673150015214 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_ERROR_H__ #define __PYGI_ERROR_H__ #include #include "pygi-cache.h" G_BEGIN_DECLS extern PyObject *PyGError; gboolean pygi_error_check (GError **error); PyObject *pygi_error_marshal_to_py (GError **error); gboolean pygi_error_marshal_from_py (PyObject *pyerr, GError **error); gboolean pygi_gerror_exception_check (GError **error); PyGIArgCache *pygi_arg_gerror_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction); int pygi_error_register_types (PyObject *module); G_END_DECLS #endif /*__PYGI_ERROR_H__*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-foreign-api.h0000664000000000000000000000474715074673150016300 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2005-2009 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_FOREIGN_API_H__ #define __PYGI_FOREIGN_API_H__ #include #include typedef PyObject *(*PyGIArgOverrideToGIArgumentFunc) ( PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg); typedef PyObject *(*PyGIArgOverrideFromGIArgumentFunc) ( GIRegisteredTypeInfo *interface_info, GITransfer transfer, gpointer data); typedef PyObject *(*PyGIArgOverrideReleaseFunc) (GIBaseInfo *base_info, gpointer struct_); struct PyGI_API { void (*register_foreign_struct) ( const char *namespace_, const char *name, PyGIArgOverrideToGIArgumentFunc to_func, PyGIArgOverrideFromGIArgumentFunc from_func, PyGIArgOverrideReleaseFunc release_func); }; #ifndef _INSIDE_PYGOBJECT_ static struct PyGI_API *PyGI_API = NULL; static int _pygi_import (void) { if (PyGI_API != NULL) { return 1; } PyGI_API = (struct PyGI_API *)PyCapsule_Import ("gi._API", FALSE); if (PyGI_API == NULL) { return -1; } return 0; } static inline PyObject * pygi_register_foreign_struct (const char *namespace_, const char *name, PyGIArgOverrideToGIArgumentFunc to_func, PyGIArgOverrideFromGIArgumentFunc from_func, PyGIArgOverrideReleaseFunc release_func) { if (_pygi_import () < 0) { return NULL; } PyGI_API->register_foreign_struct (namespace_, name, to_func, from_func, release_func); Py_RETURN_NONE; } #endif /* _INSIDE_PYGOBJECT_ */ #endif /* __PYGI_FOREIGN_API_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-foreign-cairo.c0000664000000000000000000005204715074673150016613 0ustar00rootroot/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* * Copyright (c) 2010 Collabora Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include #include #include #include /* Limit includes from PyGI to APIs which do not have link dependencies * (pygobject.h and pygi-foreign-api.h) since _gi_cairo is built as a separate * shared library that interacts with PyGI through a PyCapsule API at runtime. */ #include static int _gi_cairo_exec (PyObject *module); /* * cairo_t marshaling */ static PyObject * cairo_context_to_arg (PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { cairo_t *cr; if (!PyObject_TypeCheck (value, &PycairoContext_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.Context"); return NULL; } cr = PycairoContext_GET (value); if (!cr) { return NULL; } if (transfer != GI_TRANSFER_NOTHING) cr = cairo_reference (cr); arg->v_pointer = cr; Py_RETURN_NONE; } static PyObject * cairo_context_from_arg (GIRegisteredTypeInfo *interface_info, GITransfer transfer, gpointer data) { cairo_t *context = (cairo_t *)data; if (transfer == GI_TRANSFER_NOTHING) cairo_reference (context); return PycairoContext_FromContext (context, &PycairoContext_Type, NULL); } static PyObject * cairo_context_release (GIBaseInfo *base_info, gpointer struct_) { cairo_destroy ((cairo_t *)struct_); Py_RETURN_NONE; } static int cairo_context_to_gvalue (GValue *value, PyObject *obj) { cairo_t *cr; if (!PyObject_TypeCheck (obj, &PycairoContext_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.Context"); return -1; } cr = PycairoContext_GET (obj); if (!cr) { return -1; } /* PycairoContext_GET returns a borrowed reference, use set_boxed * to add new ref to the context which will be managed by the GValue. */ g_value_set_boxed (value, cr); return 0; } static PyObject * cairo_context_from_gvalue (const GValue *value) { /* PycairoContext_FromContext steals a ref, so we dup it out of the GValue. */ cairo_t *cr = g_value_dup_boxed (value); if (!cr) { Py_RETURN_NONE; } return PycairoContext_FromContext (cr, &PycairoContext_Type, NULL); } /* * cairo_surface_t marshaling */ static PyObject * cairo_surface_to_arg (PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { cairo_surface_t *surface; if (!PyObject_TypeCheck (value, &PycairoSurface_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.Surface"); return NULL; } surface = ((PycairoSurface *)value)->surface; if (!surface) { PyErr_SetString (PyExc_ValueError, "Surface instance wrapping a NULL surface"); return NULL; } if (transfer != GI_TRANSFER_NOTHING) surface = cairo_surface_reference (surface); arg->v_pointer = surface; Py_RETURN_NONE; } static PyObject * cairo_surface_from_arg (GIRegisteredTypeInfo *interface_info, GITransfer transfer, gpointer data) { cairo_surface_t *surface = (cairo_surface_t *)data; if (transfer == GI_TRANSFER_NOTHING) cairo_surface_reference (surface); return PycairoSurface_FromSurface (surface, NULL); } static PyObject * cairo_surface_release (GIBaseInfo *base_info, gpointer struct_) { cairo_surface_destroy ((cairo_surface_t *)struct_); Py_RETURN_NONE; } static int cairo_surface_to_gvalue (GValue *value, PyObject *obj) { cairo_surface_t *surface; if (!PyObject_TypeCheck (obj, &PycairoSurface_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.Surface"); return -1; } surface = ((PycairoSurface *)obj)->surface; if (!surface) { return -1; } /* surface is a borrowed reference, use set_boxed * to add new ref to the context which will be managed by the GValue. */ g_value_set_boxed (value, surface); return 0; } static PyObject * cairo_surface_from_gvalue (const GValue *value) { /* PycairoSurface_FromSurface steals a ref, so we dup it out of the GValue. */ cairo_surface_t *surface = g_value_dup_boxed (value); if (!surface) { Py_RETURN_NONE; } return PycairoSurface_FromSurface (surface, NULL); } /* * cairo_path_t marshaling */ static cairo_path_t * _cairo_path_copy (cairo_path_t *path) { cairo_t *cr; cairo_surface_t *surface; cairo_path_t *copy; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); cr = cairo_create (surface); cairo_append_path (cr, path); copy = cairo_copy_path (cr); cairo_destroy (cr); cairo_surface_destroy (surface); return copy; } static PyObject * cairo_path_to_arg (PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { cairo_path_t *path; if (!PyObject_TypeCheck (value, &PycairoPath_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.Path"); return NULL; } path = ((PycairoPath *)value)->path; if (!path) { PyErr_SetString (PyExc_ValueError, "Path instance wrapping a NULL path"); return NULL; } if (transfer != GI_TRANSFER_NOTHING) path = _cairo_path_copy (path); arg->v_pointer = path; Py_RETURN_NONE; } static PyObject * cairo_path_from_arg (GIRegisteredTypeInfo *interface_info, GITransfer transfer, gpointer data) { cairo_path_t *path = (cairo_path_t *)data; if (transfer == GI_TRANSFER_NOTHING) { PyErr_SetString ( PyExc_TypeError, "Unsupported annotation (transfer none) for cairo.Path return"); return NULL; } return PycairoPath_FromPath (path); } static PyObject * cairo_path_release (GIBaseInfo *base_info, gpointer struct_) { cairo_path_destroy ((cairo_path_t *)struct_); Py_RETURN_NONE; } /* * cairo_font_face_t marshaling */ static PyObject * cairo_font_face_to_arg (PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { cairo_font_face_t *font_face; if (!PyObject_TypeCheck (value, &PycairoFontFace_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.FontFace"); return NULL; } font_face = ((PycairoFontFace *)value)->font_face; if (!font_face) { PyErr_SetString (PyExc_ValueError, "FontFace instance wrapping a NULL font_face"); return NULL; } if (transfer != GI_TRANSFER_NOTHING) font_face = cairo_font_face_reference (font_face); arg->v_pointer = font_face; Py_RETURN_NONE; } static PyObject * cairo_font_face_from_arg (GIRegisteredTypeInfo *interface_info, GITransfer transfer, gpointer data) { cairo_font_face_t *font_face = (cairo_font_face_t *)data; if (transfer == GI_TRANSFER_NOTHING) cairo_font_face_reference (font_face); return PycairoFontFace_FromFontFace (font_face); } static PyObject * cairo_font_face_release (GIBaseInfo *base_info, gpointer struct_) { cairo_font_face_destroy ((cairo_font_face_t *)struct_); Py_RETURN_NONE; } static int cairo_font_face_to_gvalue (GValue *value, PyObject *obj) { cairo_font_face_t *font_face; if (!PyObject_TypeCheck (obj, &PycairoFontFace_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.FontFace"); return -1; } font_face = ((PycairoFontFace *)obj)->font_face; if (!font_face) { return -1; } g_value_set_boxed (value, font_face); return 0; } static PyObject * cairo_font_face_from_gvalue (const GValue *value) { cairo_font_face_t *font_face = g_value_dup_boxed (value); if (!font_face) { Py_RETURN_NONE; } return PycairoFontFace_FromFontFace (font_face); } /* * cairo_font_options_t marshaling */ static PyObject * cairo_font_options_to_arg (PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { cairo_font_options_t *font_options; if (!PyObject_TypeCheck (value, &PycairoFontOptions_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.FontOptions"); return NULL; } font_options = ((PycairoFontOptions *)value)->font_options; if (!font_options) { PyErr_SetString (PyExc_ValueError, "FontOptions instance wrapping a NULL font_options"); return NULL; } if (transfer != GI_TRANSFER_NOTHING) font_options = cairo_font_options_copy (font_options); arg->v_pointer = font_options; Py_RETURN_NONE; } static PyObject * cairo_font_options_from_arg (GIRegisteredTypeInfo *interface_info, GITransfer transfer, gpointer data) { cairo_font_options_t *font_options = (cairo_font_options_t *)data; if (transfer == GI_TRANSFER_NOTHING) font_options = cairo_font_options_copy (font_options); return PycairoFontOptions_FromFontOptions (font_options); } static PyObject * cairo_font_options_release (GIBaseInfo *base_info, gpointer struct_) { cairo_font_options_destroy ((cairo_font_options_t *)struct_); Py_RETURN_NONE; } /* * scaled_font_t marshaling */ static PyObject * cairo_scaled_font_to_arg (PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { cairo_scaled_font_t *scaled_font; if (!PyObject_TypeCheck (value, &PycairoScaledFont_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.ScaledFont"); return NULL; } scaled_font = ((PycairoScaledFont *)value)->scaled_font; if (!scaled_font) { PyErr_SetString (PyExc_ValueError, "ScaledFont instance wrapping a NULL scaled_font"); return NULL; } if (transfer != GI_TRANSFER_NOTHING) scaled_font = cairo_scaled_font_reference (scaled_font); arg->v_pointer = scaled_font; Py_RETURN_NONE; } static PyObject * cairo_scaled_font_from_arg (GIRegisteredTypeInfo *interface_info, GITransfer transfer, gpointer data) { cairo_scaled_font_t *scaled_font = (cairo_scaled_font_t *)data; if (transfer == GI_TRANSFER_NOTHING) cairo_scaled_font_reference (scaled_font); return PycairoScaledFont_FromScaledFont (scaled_font); } static PyObject * cairo_scaled_font_release (GIBaseInfo *base_info, gpointer struct_) { cairo_scaled_font_destroy ((cairo_scaled_font_t *)struct_); Py_RETURN_NONE; } static int cairo_scaled_font_to_gvalue (GValue *value, PyObject *obj) { cairo_scaled_font_t *scaled_font; if (!PyObject_TypeCheck (obj, &PycairoScaledFont_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.ScaledFont"); return -1; } scaled_font = ((PycairoScaledFont *)obj)->scaled_font; if (!scaled_font) { return -1; } /* scaled_font is a borrowed reference, use set_boxed * to add new ref to the context which will be managed by the GValue. */ g_value_set_boxed (value, scaled_font); return 0; } static PyObject * cairo_scaled_font_from_gvalue (const GValue *value) { /* PycairoScaledFont_FromScaledFont steals a ref, so we dup it out of the GValue. */ cairo_scaled_font_t *scaled_font = g_value_dup_boxed (value); if (!scaled_font) { Py_RETURN_NONE; } return PycairoScaledFont_FromScaledFont (scaled_font); } /* * cairo_pattern_t marshaling */ static PyObject * cairo_pattern_to_arg (PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { cairo_pattern_t *pattern; if (!PyObject_TypeCheck (value, &PycairoPattern_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.Pattern"); return NULL; } pattern = ((PycairoPattern *)value)->pattern; if (!pattern) { PyErr_SetString (PyExc_ValueError, "Pattern instance wrapping a NULL pattern"); return NULL; } if (transfer != GI_TRANSFER_NOTHING) pattern = cairo_pattern_reference (pattern); arg->v_pointer = pattern; Py_RETURN_NONE; } static PyObject * cairo_pattern_from_arg (GIRegisteredTypeInfo *interface_info, GITransfer transfer, gpointer data) { cairo_pattern_t *pattern = (cairo_pattern_t *)data; if (transfer == GI_TRANSFER_NOTHING) pattern = cairo_pattern_reference (pattern); return PycairoPattern_FromPattern (pattern, NULL); } static PyObject * cairo_pattern_release (GIBaseInfo *base_info, gpointer struct_) { cairo_pattern_destroy ((cairo_pattern_t *)struct_); Py_RETURN_NONE; } static int cairo_pattern_to_gvalue (GValue *value, PyObject *obj) { cairo_pattern_t *pattern; if (!PyObject_TypeCheck (obj, &PycairoPattern_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.Pattern"); return -1; } pattern = ((PycairoPattern *)obj)->pattern; if (!pattern) { return -1; } /* pattern is a borrowed reference, use set_boxed * to add new ref to the context which will be managed by the GValue. */ g_value_set_boxed (value, pattern); return 0; } static PyObject * cairo_pattern_from_gvalue (const GValue *value) { /* PycairoPattern_FromPattern steals a ref, so we dup it out of the GValue. */ cairo_pattern_t *pattern = g_value_dup_boxed (value); if (!pattern) { Py_RETURN_NONE; } return PycairoPattern_FromPattern (pattern, NULL); } static PyObject * cairo_region_to_arg (PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { cairo_region_t *region; if (!PyObject_TypeCheck (value, &PycairoRegion_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.Region"); return NULL; } region = ((PycairoRegion *)value)->region; if (!region) { PyErr_SetString (PyExc_ValueError, "Region instance wrapping a NULL region"); return NULL; } if (transfer != GI_TRANSFER_NOTHING) region = cairo_region_copy (region); arg->v_pointer = region; Py_RETURN_NONE; } static PyObject * cairo_region_from_arg (GIRegisteredTypeInfo *interface_info, GITransfer transfer, gpointer data) { cairo_region_t *region = (cairo_region_t *)data; if (transfer == GI_TRANSFER_NOTHING) cairo_region_reference (region); return PycairoRegion_FromRegion (region); } static PyObject * cairo_region_release (GIBaseInfo *base_info, gpointer struct_) { cairo_region_destroy ((cairo_region_t *)struct_); Py_RETURN_NONE; } static PyObject * cairo_matrix_from_arg (GIRegisteredTypeInfo *interface_info, GITransfer transfer, gpointer data) { cairo_matrix_t *matrix = (cairo_matrix_t *)data; if (transfer != GI_TRANSFER_NOTHING) { PyErr_SetString ( PyExc_TypeError, "Unsupported annotation (transfer full) for cairo.Matrix"); return NULL; } if (matrix == NULL) { /* NULL in case of caller-allocates */ cairo_matrix_t temp = { 0 }; return PycairoMatrix_FromMatrix (&temp); } return PycairoMatrix_FromMatrix (matrix); } static PyObject * cairo_matrix_to_arg (PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { cairo_matrix_t *matrix; if (!PyObject_TypeCheck (value, &PycairoMatrix_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.Matrix"); return NULL; } matrix = &(((PycairoMatrix *)value)->matrix); arg->v_pointer = matrix; Py_RETURN_NONE; } static PyObject * cairo_matrix_release (GIBaseInfo *base_info, gpointer struct_) { Py_RETURN_NONE; } static int cairo_matrix_to_gvalue (GValue *value, PyObject *obj) { cairo_matrix_t *matrix; if (!PyObject_TypeCheck (obj, &PycairoMatrix_Type)) { PyErr_SetString (PyExc_TypeError, "Expected cairo.Matrix"); return -1; } matrix = &(((PycairoMatrix *)obj)->matrix); if (!matrix) { return -1; } g_value_set_boxed (value, matrix); return 0; } static PyObject * cairo_matrix_from_gvalue (const GValue *value) { cairo_matrix_t *matrix = g_value_get_boxed (value); if (!matrix) { Py_RETURN_NONE; } return PycairoMatrix_FromMatrix (matrix); } #ifdef __GNUC__ #define PYGI_MODINIT_FUNC \ __attribute__ ((visibility ("default"))) PyMODINIT_FUNC #else #define PYGI_MODINIT_FUNC PyMODINIT_FUNC #endif static PyMethodDef _gi_cairo_functions[] = { { 0, }, }; static PyModuleDef_Slot _gi_cairo_slots[] = { { Py_mod_exec, _gi_cairo_exec }, { 0, NULL }, }; static struct PyModuleDef __gi_cairomodule = { PyModuleDef_HEAD_INIT, "_gi_cairo", NULL, 0, _gi_cairo_functions, _gi_cairo_slots, NULL, NULL, NULL, }; PYGI_MODINIT_FUNC PyInit__gi_cairo (void); PYGI_MODINIT_FUNC PyInit__gi_cairo (void) { return PyModuleDef_Init (&__gi_cairomodule); } static int _gi_cairo_exec (PyObject *module) { PyObject *gobject_mod; import_cairo (); if (Pycairo_CAPI == NULL) return -1; gobject_mod = pygobject_init (3, 13, 2); if (gobject_mod == NULL) return -1; Py_DECREF (gobject_mod); pygi_register_foreign_struct ("cairo", "Matrix", cairo_matrix_to_arg, cairo_matrix_from_arg, cairo_matrix_release); pygi_register_foreign_struct ("cairo", "Context", cairo_context_to_arg, cairo_context_from_arg, cairo_context_release); pygi_register_foreign_struct ("cairo", "Surface", cairo_surface_to_arg, cairo_surface_from_arg, cairo_surface_release); pygi_register_foreign_struct ("cairo", "Path", cairo_path_to_arg, cairo_path_from_arg, cairo_path_release); pygi_register_foreign_struct ("cairo", "FontFace", cairo_font_face_to_arg, cairo_font_face_from_arg, cairo_font_face_release); pygi_register_foreign_struct ( "cairo", "FontOptions", cairo_font_options_to_arg, cairo_font_options_from_arg, cairo_font_options_release); pygi_register_foreign_struct ("cairo", "Pattern", cairo_pattern_to_arg, cairo_pattern_from_arg, cairo_pattern_release); pygi_register_foreign_struct ("cairo", "Region", cairo_region_to_arg, cairo_region_from_arg, cairo_region_release); pygi_register_foreign_struct ( "cairo", "ScaledFont", cairo_scaled_font_to_arg, cairo_scaled_font_from_arg, cairo_scaled_font_release); pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_MATRIX, cairo_matrix_from_gvalue, cairo_matrix_to_gvalue); pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_CONTEXT, cairo_context_from_gvalue, cairo_context_to_gvalue); pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_SURFACE, cairo_surface_from_gvalue, cairo_surface_to_gvalue); pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_FONT_FACE, cairo_font_face_from_gvalue, cairo_font_face_to_gvalue); pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_SCALED_FONT, cairo_scaled_font_from_gvalue, cairo_scaled_font_to_gvalue); pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_PATTERN, cairo_pattern_from_gvalue, cairo_pattern_to_gvalue); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-foreign.c0000664000000000000000000001504715074673150015517 0ustar00rootroot/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* * Copyright (c) 2010 litl, LLC * Copyright (c) 2010 Collabora Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include #include #include "pygobject-internal.h" #include "pygi-foreign.h" typedef struct { const char *namespace; const char *name; PyGIArgOverrideToGIArgumentFunc to_func; PyGIArgOverrideFromGIArgumentFunc from_func; PyGIArgOverrideReleaseFunc release_func; } PyGIForeignStruct; static GPtrArray *foreign_structs = NULL; static void init_foreign_structs (void) { foreign_structs = g_ptr_array_new (); } static PyGIForeignStruct * do_lookup (const gchar *namespace, const gchar *name) { guint i; for (i = 0; i < foreign_structs->len; i++) { PyGIForeignStruct *foreign_struct = g_ptr_array_index (foreign_structs, i); if ((strcmp (namespace, foreign_struct->namespace) == 0) && (strcmp (name, foreign_struct->name) == 0)) { return foreign_struct; } } return NULL; } static PyObject * pygi_struct_foreign_load_module (const char *namespace) { gchar *module_name = g_strconcat ("gi._gi_", namespace, NULL); PyObject *module = PyImport_ImportModule (module_name); g_free (module_name); return module; } static PyGIForeignStruct * pygi_struct_foreign_lookup_by_name (const char *namespace, const char *name) { PyGIForeignStruct *result; result = do_lookup (namespace, name); if (result == NULL) { PyObject *module = pygi_struct_foreign_load_module (namespace); if (module == NULL) PyErr_Clear (); else { Py_DECREF (module); result = do_lookup (namespace, name); } } if (result == NULL) { PyErr_Format (PyExc_TypeError, "Couldn't find foreign struct converter for '%s.%s'", namespace, name); } return result; } static PyGIForeignStruct * pygi_struct_foreign_lookup (GIBaseInfo *base_info) { const gchar *namespace = gi_base_info_get_namespace (base_info); const gchar *name = gi_base_info_get_name (base_info); return pygi_struct_foreign_lookup_by_name (namespace, name); } PyObject * pygi_struct_foreign_convert_to_g_argument ( PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { PyObject *result; GIBaseInfo *base_info = GI_BASE_INFO (interface_info); PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info); if (foreign_struct == NULL) { PyErr_Format (PyExc_KeyError, "could not find foreign type %s", gi_base_info_get_name (base_info)); return FALSE; } result = foreign_struct->to_func (value, interface_info, transfer, arg); return result; } PyObject * pygi_struct_foreign_convert_from_g_argument ( GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg) { GIBaseInfo *base_info = GI_BASE_INFO (interface_info); PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info); if (foreign_struct == NULL) return NULL; return foreign_struct->from_func (interface_info, transfer, arg); } PyObject * pygi_struct_foreign_release (GIBaseInfo *base_info, gpointer struct_) { PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info); if (foreign_struct == NULL) return NULL; if (!foreign_struct->release_func) Py_RETURN_NONE; return foreign_struct->release_func (base_info, struct_); } void pygi_register_foreign_struct (const char *namespace_, const char *name, PyGIArgOverrideToGIArgumentFunc to_func, PyGIArgOverrideFromGIArgumentFunc from_func, PyGIArgOverrideReleaseFunc release_func) { PyGIForeignStruct *new_struct = g_slice_new (PyGIForeignStruct); new_struct->namespace = namespace_; new_struct->name = name; new_struct->to_func = to_func; new_struct->from_func = from_func; new_struct->release_func = release_func; g_ptr_array_add (foreign_structs, new_struct); } PyObject * pygi_require_foreign (PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "namespace", "symbol", NULL }; const char *namespace = NULL; const char *symbol = NULL; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s|z:require_foreign", kwlist, &namespace, &symbol)) { return NULL; } if (symbol) { PyGIForeignStruct *foreign; foreign = pygi_struct_foreign_lookup_by_name (namespace, symbol); if (foreign == NULL) { return NULL; } } else { PyObject *module = pygi_struct_foreign_load_module (namespace); if (module) { Py_DECREF (module); } else { return NULL; } } Py_RETURN_NONE; } /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_foreign_init (void) { if (foreign_structs == NULL) { init_foreign_structs (); } return 0; } PyObject * pygi_register_foreign (PyObject *self, PyObject *args) { /* We need to try loading the foreign modules upfront so the GType * converters are registered: * https://gitlab.gnome.org/GNOME/pygobject/issues/260 */ PyObject *mod = pygi_struct_foreign_load_module ("cairo"); if (mod == NULL) PyErr_Clear (); else Py_DECREF (mod); Py_RETURN_NONE; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-foreign.h0000664000000000000000000000444615074673150015525 0ustar00rootroot/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* * Copyright (c) 2010 litl, LLC * Copyright (c) 2010 Collabora Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #ifndef __PYGI_FOREIGN_H__ #define __PYGI_FOREIGN_H__ #include #include "pygi-foreign-api.h" PyObject *pygi_struct_foreign_convert_to_g_argument ( PyObject *value, GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg); PyObject *pygi_struct_foreign_convert_from_g_argument ( GIRegisteredTypeInfo *interface_info, GITransfer transfer, GIArgument *arg); PyObject *pygi_struct_foreign_release (GIBaseInfo *base_info, gpointer struct_); void pygi_register_foreign_struct (const char *namespace_, const char *name, PyGIArgOverrideToGIArgumentFunc to_func, PyGIArgOverrideFromGIArgumentFunc from_func, PyGIArgOverrideReleaseFunc release_func); PyObject *pygi_require_foreign (PyObject *self, PyObject *args, PyObject *kwargs); int pygi_foreign_init (void); PyObject *pygi_register_foreign (PyObject *self, PyObject *args); #endif /* __PYGI_FOREIGN_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-fundamental.c0000664000000000000000000002124515074673150016361 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2009 Simon van der Linden * Copyright (C) 2010 Tomeu Vizoso * Copyright (C) 2012 Bastian Winkler * * pygi-fundamental.c: wrapper to handle instances of fundamental types. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA */ #include #include "pygobject-internal.h" #include "pygi-info.h" #include "pygi-util.h" #include "pygi-fundamental.h" #include "pygi-repository.h" #include "pygobject-object.h" // for pygobject_lookup_class static PyGIFundamental *_pygi_fundamental_new_internal (PyTypeObject *type, gpointer pointer); static void fundamental_dealloc (PyGIFundamental *self) { pygi_fundamental_unref (self); self->instance = NULL; PyObject_GC_UnTrack ((PyObject *)self); if (self->weaklist) PyObject_ClearWeakRefs ((PyObject *)self); Py_TYPE (self)->tp_free ((PyObject *)self); } static PyObject * fundamental_new (PyTypeObject *type, PyObject *args, PyObject *kwargs) { GIBaseInfo *info; gpointer pointer; PyGIFundamental *self = NULL; GType g_type; info = _pygi_object_get_gi_info ((PyObject *)type, &PyGIObjectInfo_Type); if (info == NULL) { if (PyErr_ExceptionMatches (PyExc_AttributeError)) { PyErr_Format (PyExc_TypeError, "missing introspection information"); } return NULL; } g_type = pyg_type_from_object ((PyObject *)type); if (G_TYPE_IS_ABSTRACT (g_type)) { PyErr_Format (PyExc_TypeError, "cannot instantiate abstract type %s", g_type_name (g_type)); return NULL; } pointer = g_type_create_instance (g_type); if (pointer == NULL) { PyErr_NoMemory (); goto out; } self = _pygi_fundamental_new_internal (type, pointer); if (self == NULL) { g_free (pointer); PyErr_Format (PyExc_TypeError, "cannot instantiate Fundamental Python wrapper type %s", g_type_name (g_type)); goto out; } out: gi_base_info_unref (info); return (PyObject *)self; } static int fundamental_init (PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, ":Fundamental.__init__", kwlist)) { return -1; } return 0; } static PyObject * fundamental_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE (self) == Py_TYPE (other)) { return pyg_ptr_richcompare (((PyGIFundamental *)self)->instance, ((PyGIFundamental *)other)->instance, op); } else { Py_INCREF (Py_NotImplemented); return Py_NotImplemented; } } static Py_hash_t fundamental_hash (PyGIFundamental *self) { return (Py_hash_t)(gintptr)(self->instance); } static PyObject * fundamental_repr (PyGIFundamental *self) { gchar buf[128]; g_snprintf (buf, sizeof (buf), "<%s at 0x%" G_GUINTPTR_FORMAT ">", g_type_name (self->gtype), (guintptr)self->instance); return PyUnicode_FromString (buf); } PYGI_DEFINE_TYPE ("gi.Fundamental", PyGIFundamental_Type, PyGIFundamental); PyObject * pygi_fundamental_new (gpointer instance) { GType gtype; PyTypeObject *type; PyGIFundamental *self; if (!instance) { Py_RETURN_NONE; } gtype = G_TYPE_FROM_INSTANCE (instance); type = pygobject_lookup_class (gtype); self = _pygi_fundamental_new_internal (type, instance); pygi_fundamental_ref (self); return (PyObject *)self; } static PyGIFundamental * _pygi_fundamental_new_internal (PyTypeObject *type, gpointer instance) { PyGIFundamental *self; GIObjectInfo *info; if (!PyType_IsSubtype (type, &PyGIFundamental_Type)) { PyErr_SetString (PyExc_TypeError, "must be a subtype of gi.Fundamental"); return NULL; } info = GI_OBJECT_INFO ( _pygi_object_get_gi_info ((PyObject *)type, &PyGIObjectInfo_Type)); if (info == NULL) { if (PyErr_ExceptionMatches (PyExc_AttributeError)) { PyErr_Format (PyExc_TypeError, "missing introspection information"); } return NULL; } self = (PyGIFundamental *)type->tp_alloc (type, 0); if (self == NULL) { return NULL; } self->gtype = pyg_type_from_object ((PyObject *)type); self->instance = instance; self->ref_func = gi_object_info_get_ref_function_pointer (info); self->unref_func = gi_object_info_get_unref_function_pointer (info); /* A special case for GParamSpec. It has a floating reference when created. * We make sure we have a proper reference, so we can ref/unref normally. */ if (G_TYPE_IS_PARAM (self->gtype)) { g_param_spec_ref_sink (self->instance); } gi_base_info_unref (info); return self; } void pygi_fundamental_ref (PyGIFundamental *self) { if (self->ref_func && self->instance) self->ref_func (self->instance); } void pygi_fundamental_unref (PyGIFundamental *self) { if (self->unref_func && self->instance) self->unref_func (self->instance); } GTypeInstance * pygi_fundamental_get (PyObject *self) { if (PyObject_TypeCheck (self, &PyGIFundamental_Type)) { return ((PyGIFundamental *)self)->instance; } else { PyErr_SetString (PyExc_TypeError, "Expected GObject Fundamental type"); return NULL; } } int pygi_fundamental_register_types (PyObject *m) { Py_SET_TYPE (&PyGIFundamental_Type, &PyType_Type); g_assert (Py_TYPE (&PyGIFundamental_Type) != NULL); PyGIFundamental_Type.tp_alloc = PyType_GenericAlloc; PyGIFundamental_Type.tp_new = (newfunc)fundamental_new; PyGIFundamental_Type.tp_init = (initproc)fundamental_init; PyGIFundamental_Type.tp_dealloc = (destructor)fundamental_dealloc; PyGIFundamental_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); PyGIFundamental_Type.tp_richcompare = fundamental_richcompare; PyGIFundamental_Type.tp_repr = (reprfunc)fundamental_repr; PyGIFundamental_Type.tp_hash = (hashfunc)fundamental_hash; PyGIFundamental_Type.tp_weaklistoffset = offsetof (PyGIFundamental, weaklist); if (PyType_Ready (&PyGIFundamental_Type)) return -1; if (PyModule_AddObject (m, "Fundamental", (PyObject *)&PyGIFundamental_Type)) return -1; return 0; } GTypeInstance * pygi_fundamental_from_value (const GValue *value) { GIRepository *repository = pygi_repository_get_default (); // Access to system wide (default) repo instead GIBaseInfo *info = gi_repository_find_by_gtype (repository, G_VALUE_TYPE (value)); GTypeInstance *instance = NULL; if (info == NULL) return NULL; if (GI_IS_OBJECT_INFO (info)) { GIObjectInfoGetValueFunction get_value_func = gi_object_info_get_get_value_function_pointer ( (GIObjectInfo *)info); if (get_value_func) { instance = get_value_func (value); } } gi_base_info_unref (info); return instance; } gboolean pygi_fundamental_set_value (GValue *value, GTypeInstance *instance) { GIRepository *repository; GIBaseInfo *info; gboolean result = FALSE; if (instance == NULL) return result; repository = pygi_repository_get_default (); info = gi_repository_find_by_gtype (repository, G_TYPE_FROM_INSTANCE (instance)); if (info == NULL) return result; if (GI_IS_OBJECT_INFO (info)) { GIObjectInfoSetValueFunction set_value_func = gi_object_info_get_set_value_function_pointer ( (GIObjectInfo *)info); if (set_value_func) { set_value_func (value, instance); result = TRUE; } } gi_base_info_unref (info); return result; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-fundamental.h0000664000000000000000000000416715074673150016372 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2009 Simon van der Linden * Copyright (C) 2010 Tomeu Vizoso * Copyright (C) 2012 Bastian Winkler * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA */ #ifndef __PYGI_FUNDAMENTAL_H__ #define __PYGI_FUNDAMENTAL_H__ #include #include #include "pygobject-internal.h" #include "pygpointer.h" #include "pygi-type.h" G_BEGIN_DECLS extern PyTypeObject PyGIFundamental_Type; typedef struct { PyObject_HEAD PyObject *weaklist; gpointer instance; GType gtype; GIObjectInfoRefFunction ref_func; GIObjectInfoUnrefFunction unref_func; } PyGIFundamental; PyObject *pygi_fundamental_new (gpointer instance); void pygi_fundamental_ref (PyGIFundamental *self); void pygi_fundamental_unref (PyGIFundamental *self); GTypeInstance *pygi_fundamental_get (PyObject *self); int pygi_fundamental_register_types (PyObject *m); #define pygi_check_fundamental(info) \ (GI_IS_OBJECT_INFO (info) \ && gi_object_info_get_fundamental ((GIObjectInfo *)(info))) GTypeInstance *pygi_fundamental_from_value (const GValue *value); gboolean pygi_fundamental_set_value (GValue *value, GTypeInstance *instance); #endif /* __PYGI_FUNDAMENTAL_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-hashtable.c0000664000000000000000000003004615074673150016015 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-hashtable.h" #include "pygi-argument.h" #include "pygi-util.h" typedef struct _PyGIHashCache { PyGIArgCache arg_cache; PyGIArgCache *key_cache; PyGIArgCache *value_cache; } PyGIHashCache; static void _hash_cache_free_func (PyGIHashCache *cache) { if (cache != NULL) { pygi_arg_cache_free (cache->key_cache); pygi_arg_cache_free (cache->value_cache); g_slice_free (PyGIHashCache, cache); } } static gboolean _pygi_marshal_from_py_ghash (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { PyGIMarshalFromPyFunc key_from_py_marshaller; PyGIMarshalFromPyFunc value_from_py_marshaller; int i; Py_ssize_t length; PyObject *py_keys, *py_values; GHashFunc hash_func; GEqualFunc equal_func; GHashTable *hash_ = NULL; PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache; if (Py_IsNone (py_arg)) { arg->v_pointer = NULL; return TRUE; } py_keys = PyMapping_Keys (py_arg); if (py_keys == NULL) { PyErr_Format (PyExc_TypeError, "Must be mapping, not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } length = PyMapping_Length (py_arg); if (length < 0) { Py_DECREF (py_keys); return FALSE; } py_values = PyMapping_Values (py_arg); if (py_values == NULL) { Py_DECREF (py_keys); return FALSE; } key_from_py_marshaller = hash_cache->key_cache->from_py_marshaller; value_from_py_marshaller = hash_cache->value_cache->from_py_marshaller; switch (hash_cache->key_cache->type_tag) { case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: hash_func = g_str_hash; equal_func = g_str_equal; break; default: hash_func = NULL; equal_func = NULL; } hash_ = g_hash_table_new (hash_func, equal_func); if (hash_ == NULL) { PyErr_NoMemory (); Py_DECREF (py_keys); Py_DECREF (py_values); return FALSE; } for (i = 0; i < length; i++) { GIArgument key, value; gpointer key_cleanup_data = NULL; gpointer value_cleanup_data = NULL; PyObject *py_key = PyList_GET_ITEM (py_keys, i); PyObject *py_value = PyList_GET_ITEM (py_values, i); if (py_key == NULL || py_value == NULL) goto err; if (!key_from_py_marshaller (state, callable_cache, hash_cache->key_cache, py_key, &key, &key_cleanup_data)) goto err; if (!value_from_py_marshaller (state, callable_cache, hash_cache->value_cache, py_value, &value, &value_cleanup_data)) goto err; g_hash_table_insert ( hash_, _pygi_arg_to_hash_pointer (&key, hash_cache->key_cache->type_info), _pygi_arg_to_hash_pointer (&value, hash_cache->value_cache->type_info)); continue; err: /* FIXME: cleanup hash keys and values */ Py_DECREF (py_keys); Py_DECREF (py_values); g_hash_table_unref (hash_); _PyGI_ERROR_PREFIX ("Item %i: ", i); return FALSE; } arg->v_pointer = hash_; if (arg_cache->transfer == GI_TRANSFER_NOTHING) { /* Free everything in cleanup. */ *cleanup_data = arg->v_pointer; } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) { /* Make a shallow copy so we can free the elements later in cleanup * because it is possible invoke will free the list before our cleanup. */ *cleanup_data = g_hash_table_ref (arg->v_pointer); } else { /* GI_TRANSFER_EVERYTHING */ /* No cleanup, everything is given to the callee. * Note that the keys and values will leak for transfer everything because * we do not use g_hash_table_new_full and set key/value_destroy_func. */ *cleanup_data = NULL; } return TRUE; } static void _pygi_marshal_cleanup_from_py_ghash (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed) { if (data == NULL) return; if (was_processed) { GHashTable *hash_; PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache; hash_ = (GHashTable *)data; /* clean up keys and values first */ if (hash_cache->key_cache->from_py_cleanup != NULL || hash_cache->value_cache->from_py_cleanup != NULL) { GHashTableIter hiter; gpointer key; gpointer value; PyGIMarshalCleanupFunc key_cleanup_func = hash_cache->key_cache->from_py_cleanup; PyGIMarshalCleanupFunc value_cleanup_func = hash_cache->value_cache->from_py_cleanup; g_hash_table_iter_init (&hiter, hash_); while (g_hash_table_iter_next (&hiter, &key, &value)) { if (key != NULL && key_cleanup_func != NULL) key_cleanup_func (state, hash_cache->key_cache, NULL, key, TRUE); if (value != NULL && value_cleanup_func != NULL) value_cleanup_func (state, hash_cache->value_cache, NULL, value, TRUE); } } g_hash_table_unref (hash_); } } static PyObject * _pygi_marshal_to_py_ghash (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { GHashTable *hash_; GHashTableIter hash_table_iter; PyGIMarshalToPyFunc key_to_py_marshaller; PyGIMarshalToPyFunc value_to_py_marshaller; PyGIArgCache *key_arg_cache; PyGIArgCache *value_arg_cache; PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache; GIArgument key_arg; GIArgument value_arg; PyObject *py_obj = NULL; hash_ = arg->v_pointer; if (hash_ == NULL) { py_obj = Py_None; Py_INCREF (py_obj); return py_obj; } py_obj = PyDict_New (); if (py_obj == NULL) return NULL; key_arg_cache = hash_cache->key_cache; key_to_py_marshaller = key_arg_cache->to_py_marshaller; value_arg_cache = hash_cache->value_cache; value_to_py_marshaller = value_arg_cache->to_py_marshaller; g_hash_table_iter_init (&hash_table_iter, hash_); while (g_hash_table_iter_next (&hash_table_iter, &key_arg.v_pointer, &value_arg.v_pointer)) { gpointer key_cleanup_data = NULL; gpointer value_cleanup_data = NULL; PyObject *py_key; PyObject *py_value; int retval; _pygi_hash_pointer_to_arg (&key_arg, hash_cache->key_cache->type_info); py_key = key_to_py_marshaller (state, callable_cache, key_arg_cache, &key_arg, &key_cleanup_data); if (py_key == NULL) { Py_CLEAR (py_obj); return NULL; } _pygi_hash_pointer_to_arg (&value_arg, hash_cache->value_cache->type_info); py_value = value_to_py_marshaller (state, callable_cache, value_arg_cache, &value_arg, &value_cleanup_data); if (py_value == NULL) { Py_CLEAR (py_obj); Py_DECREF (py_key); return NULL; } retval = PyDict_SetItem (py_obj, py_key, py_value); Py_DECREF (py_key); Py_DECREF (py_value); if (retval < 0) { Py_CLEAR (py_obj); return NULL; } } return py_obj; } static void _pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state, PyGIArgCache *arg_cache, gpointer cleanup_data, gpointer data, gboolean was_processed) { if (data == NULL) return; /* assume hashtable has boxed key and value */ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->transfer == GI_TRANSFER_CONTAINER) g_hash_table_unref ((GHashTable *)data); } static void _arg_cache_from_py_ghash_setup (PyGIArgCache *arg_cache) { arg_cache->from_py_marshaller = _pygi_marshal_from_py_ghash; arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_ghash; } static void _arg_cache_to_py_ghash_setup (PyGIArgCache *arg_cache) { arg_cache->to_py_marshaller = _pygi_marshal_to_py_ghash; arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_ghash; } static gboolean pygi_arg_hash_table_setup_from_info (PyGIHashCache *hc, GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache) { GITypeInfo *key_type_info; GITypeInfo *value_type_info; GITransfer item_transfer; if (!pygi_arg_base_setup ((PyGIArgCache *)hc, type_info, arg_info, transfer, direction)) return FALSE; ((PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func; key_type_info = gi_type_info_get_param_type (type_info, 0); value_type_info = gi_type_info_get_param_type (type_info, 1); item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; hc->key_cache = pygi_arg_cache_new (key_type_info, NULL, item_transfer, direction, callable_cache, 0, 0); if (hc->key_cache == NULL) { return FALSE; } hc->value_cache = pygi_arg_cache_new (value_type_info, NULL, item_transfer, direction, callable_cache, 0, 0); if (hc->value_cache == NULL) { return FALSE; } gi_base_info_unref ((GIBaseInfo *)key_type_info); gi_base_info_unref ((GIBaseInfo *)value_type_info); if (direction & PYGI_DIRECTION_FROM_PYTHON) { _arg_cache_from_py_ghash_setup ((PyGIArgCache *)hc); } if (direction & PYGI_DIRECTION_TO_PYTHON) { _arg_cache_to_py_ghash_setup ((PyGIArgCache *)hc); } return TRUE; } PyGIArgCache * pygi_arg_hash_table_new_from_info (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache) { gboolean res = FALSE; PyGIHashCache *hc = NULL; hc = g_slice_new0 (PyGIHashCache); if (hc == NULL) return NULL; res = pygi_arg_hash_table_setup_from_info ( hc, type_info, arg_info, transfer, direction, callable_cache); if (res) { return (PyGIArgCache *)hc; } else { pygi_arg_cache_free ((PyGIArgCache *)hc); return NULL; } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-hashtable.h0000664000000000000000000000226515074673150016024 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2013 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_HASHTABLE_H__ #define __PYGI_HASHTABLE_H__ #include "pygi-cache.h" #include G_BEGIN_DECLS PyGIArgCache *pygi_arg_hash_table_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache); G_END_DECLS #endif /*__PYGI_HASHTABLE_H__*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-info.c0000664000000000000000000023767315074673150015034 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2005-2009 Johan Dahlin * Copyright (C) 2013 Simon Feltman * * pygi-info.c: GI.*Info wrappers. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-type.h" #include "pygi-argument.h" #include "pygi-basictype.h" #include "pygi-cache.h" #include "pygi-fundamental.h" #include "pygi-info.h" #include "pygi-invoke.h" #include "pygi-util.h" /* _generate_doc_string * * C wrapper to call Python implemented "gi.docstring.generate_doc_string" */ static PyObject * _generate_doc_string (PyGIBaseInfo *self) { static PyObject *_py_generate_doc_string = NULL; if (_py_generate_doc_string == NULL) { PyObject *mod = PyImport_ImportModule ("gi.docstring"); if (!mod) return NULL; _py_generate_doc_string = PyObject_GetAttrString (mod, "generate_doc_string"); if (_py_generate_doc_string == NULL) { Py_DECREF (mod); return NULL; } Py_DECREF (mod); } return PyObject_CallFunctionObjArgs (_py_generate_doc_string, self, NULL); } static PyObject * _generate_signature (PyGICallableInfo *self) { static PyObject *_py_generate_signature = NULL; if (_py_generate_signature == NULL) { PyObject *mod = PyImport_ImportModule ("gi._signature"); if (!mod) return NULL; _py_generate_signature = PyObject_GetAttrString (mod, "generate_signature"); if (_py_generate_signature == NULL) { Py_DECREF (mod); return NULL; } Py_DECREF (mod); } return PyObject_CallFunctionObjArgs (_py_generate_signature, self, NULL); } static PyObject * _get_info_string (const gchar *value) { if (value == NULL) { Py_RETURN_NONE; } return pygi_utf8_to_py (value); } /* TODO Maybe rework this to be a macro which can do the type safety properly */ typedef GIBaseInfo *(*GetChildInfoCallback) (GIBaseInfo *info); static PyObject * _get_child_info (PyGIBaseInfo *self, GetChildInfoCallback get_child_info) { GIBaseInfo *info; PyObject *py_info; info = get_child_info ((GIBaseInfo *)self->info); if (info == NULL) { Py_RETURN_NONE; } py_info = _pygi_info_new (info); gi_base_info_unref (info); return py_info; } typedef GIBaseInfo *(*GetChildInfoByNameCallback) (GIBaseInfo *info, const char *name); static PyObject * _get_child_info_by_name (PyGIBaseInfo *self, PyObject *py_name, GetChildInfoByNameCallback get_child_info_by_name) { GIBaseInfo *info; PyObject *py_info; char *name; if (!pygi_utf8_from_py (py_name, &name)) return NULL; info = get_child_info_by_name (self->info, name); g_free (name); if (info == NULL) { Py_RETURN_NONE; } py_info = _pygi_info_new (info); gi_base_info_unref (info); return py_info; } /* _make_infos_tuple * * Build a tuple from the common API pattern in GI of having a * function which returns a count and an indexed GIBaseInfo * in the range of 0 to count; */ /* TODO Maybe rework this to be a macro which can do the type safety properly */ typedef unsigned int (*GetNInfosCallback) (GIBaseInfo *info); typedef GIBaseInfo *(*MakeInfosCallback) (GIBaseInfo *info, unsigned int idx); static PyObject * _make_infos_tuple (PyGIBaseInfo *self, GetNInfosCallback get_n_infos, MakeInfosCallback get_info) { gint n_infos; PyObject *infos; gint i; n_infos = get_n_infos ((GIBaseInfo *)self->info); infos = PyTuple_New (n_infos); if (infos == NULL) { return NULL; } for (i = 0; i < n_infos; i++) { GIBaseInfo *info; PyObject *py_info; info = (GIBaseInfo *)get_info (self->info, i); g_assert (info != NULL); py_info = _pygi_info_new (info); gi_base_info_unref (info); if (py_info == NULL) { Py_CLEAR (infos); break; } PyTuple_SET_ITEM (infos, i, py_info); } return infos; } /* BaseInfo */ /* We need to be careful about calling gi_base_info_get_name because * calling it with a GI_INFO_TYPE_TYPE will crash. * See: https://bugzilla.gnome.org/show_bug.cgi?id=709456 */ static const char * _safe_base_info_get_name (GIBaseInfo *info) { if (GI_IS_TYPE_INFO (info)) { return "type_type_instance"; } else { return gi_base_info_get_name (info); } } static void _base_info_dealloc (PyGIBaseInfo *self) { if (self->inst_weakreflist != NULL) PyObject_ClearWeakRefs ((PyObject *)self); gi_base_info_unref (self->info); Py_TYPE (self)->tp_free ((PyObject *)self); } static PyObject * _base_info_repr (PyGIBaseInfo *self) { return PyUnicode_FromFormat ("%s(%s)", Py_TYPE ((PyObject *)self)->tp_name, _safe_base_info_get_name (self->info)); } static PyObject * _wrap_gi_base_info_equal (PyGIBaseInfo *self, PyObject *other) { GIBaseInfo *other_info; if (!PyObject_TypeCheck (other, &PyGIBaseInfo_Type)) { Py_INCREF (Py_NotImplemented); return Py_NotImplemented; } other_info = ((PyGIBaseInfo *)other)->info; if (gi_base_info_equal (self->info, other_info)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } static PyObject * _base_info_richcompare (PyGIBaseInfo *self, PyObject *other, int op) { PyObject *res; switch (op) { case Py_EQ: return _wrap_gi_base_info_equal (self, other); case Py_NE: res = _wrap_gi_base_info_equal (self, other); if (Py_IsTrue (res)) { Py_DECREF (res); Py_RETURN_FALSE; } else { Py_DECREF (res); Py_RETURN_TRUE; } default: res = Py_NotImplemented; break; } return Py_NewRef (res); } PYGI_DEFINE_TYPE ("gi.BaseInfo", PyGIBaseInfo_Type, PyGIBaseInfo); PyObject * _pygi_is_python_keyword (const gchar *name) { static PyObject *iskeyword = NULL; PyObject *pyname, *result; if (!iskeyword) { PyObject *keyword_module = PyImport_ImportModule ("keyword"); if (!keyword_module) return NULL; iskeyword = PyObject_GetAttrString (keyword_module, "iskeyword"); Py_DECREF (keyword_module); if (!iskeyword) return NULL; } /* Python 3.x; note that we explicitly keep "print"; it is not a keyword * any more, but we do not want to break API between Python versions */ if (strcmp (name, "print") == 0) Py_RETURN_TRUE; pyname = PyUnicode_FromString (name); if (!pyname) return NULL; result = PyObject_CallOneArg (iskeyword, pyname); Py_DECREF (pyname); return result; } static PyObject * _wrap_gi_base_info_get_name (PyGIBaseInfo *self) { const gchar *name; PyObject *is_keyword, *obj; name = _safe_base_info_get_name (self->info); is_keyword = _pygi_is_python_keyword (name); if (!is_keyword) return NULL; /* escape keywords */ if (PyObject_IsTrue (is_keyword)) { gchar *escaped = g_strconcat (name, "_", NULL); obj = pygi_utf8_to_py (escaped); g_free (escaped); } else { obj = pygi_utf8_to_py (name); } Py_DECREF (is_keyword); return obj; } static PyObject * _wrap_gi_base_info_get_name_unescaped (PyGIBaseInfo *self) { return _get_info_string (_safe_base_info_get_name (self->info)); } static PyObject * _wrap_gi_base_info_get_namespace (PyGIBaseInfo *self) { return _get_info_string (gi_base_info_get_namespace (self->info)); } static PyObject * _wrap_gi_base_info_is_deprecated (PyGIBaseInfo *self) { if (gi_base_info_is_deprecated (self->info)) Py_RETURN_TRUE; else Py_RETURN_FALSE; } static PyObject * _wrap_gi_base_info_get_attribute (PyGIBaseInfo *self, PyObject *arg) { char *name; const char *value; if (!pygi_utf8_from_py (arg, &name)) return NULL; value = gi_base_info_get_attribute (self->info, name); g_free (name); if (value == NULL) { Py_RETURN_NONE; } return pygi_utf8_to_py (value); } static PyObject * _wrap_gi_base_info_get_container (PyGIBaseInfo *self) { /* Note: don't use _get_child_info because gi_base_info_get_container * is marked as [transfer none] and therefore returns a borrowed ref. */ GIBaseInfo *info; info = gi_base_info_get_container (self->info); if (info == NULL) { Py_RETURN_NONE; } return _pygi_info_new (info); } static PyMethodDef _PyGIBaseInfo_methods[] = { { "get_name", (PyCFunction)_wrap_gi_base_info_get_name, METH_NOARGS }, { "get_name_unescaped", (PyCFunction)_wrap_gi_base_info_get_name_unescaped, METH_NOARGS }, { "get_namespace", (PyCFunction)_wrap_gi_base_info_get_namespace, METH_NOARGS }, { "is_deprecated", (PyCFunction)_wrap_gi_base_info_is_deprecated, METH_NOARGS }, { "get_attribute", (PyCFunction)_wrap_gi_base_info_get_attribute, METH_O }, { "get_container", (PyCFunction)_wrap_gi_base_info_get_container, METH_NOARGS }, { "equal", (PyCFunction)_wrap_gi_base_info_equal, METH_O }, { NULL, NULL, 0 }, }; /* _base_info_getattro: * * The usage of __getattr__ is needed because the get/set method table * does not work for __doc__. */ static PyObject * _base_info_getattro (PyGIBaseInfo *self, PyObject *name) { PyObject *result; static PyObject *docstr; if (docstr == NULL) { docstr = PyUnicode_InternFromString ("__doc__"); if (docstr == NULL) return NULL; } Py_INCREF (name); PyUnicode_InternInPlace (&name); if (name == docstr) { result = _generate_doc_string (self); } else { result = PyObject_GenericGetAttr ((PyObject *)self, name); } Py_DECREF (name); return result; } static PyObject * _base_info_attr_name (PyGIBaseInfo *self, void *closure) { return _wrap_gi_base_info_get_name (self); } static PyObject * _base_info_attr_module (PyGIBaseInfo *self, void *closure) { return PyUnicode_FromFormat ("gi.repository.%s", gi_base_info_get_namespace (self->info)); } static PyGetSetDef _base_info_getsets[] = { { "__name__", (getter)_base_info_attr_name, (setter)0, "Name", NULL }, { "__module__", (getter)_base_info_attr_module, (setter)0, "Module name", NULL }, { NULL, 0, 0 }, }; static PyObject *_callable_info_vectorcall (PyGICallableInfo *self, PyObject *const *args, size_t nargsf, PyObject *kwnames); static PyObject *_function_info_vectorcall (PyGICallableInfo *self, PyObject *const *args, size_t nargsf, PyObject *kwnames); PyObject * _pygi_info_new (GIBaseInfo *info) { PyTypeObject *type = NULL; vectorcallfunc vectorcall = NULL; PyGIBaseInfo *self; if (GI_IS_FUNCTION_INFO (info)) { type = &PyGIFunctionInfo_Type; vectorcall = (vectorcallfunc)_function_info_vectorcall; } else if (GI_IS_CALLBACK_INFO (info)) { type = &PyGICallbackInfo_Type; vectorcall = (vectorcallfunc)_callable_info_vectorcall; } else if (GI_IS_STRUCT_INFO (info)) { type = &PyGIStructInfo_Type; } else if (GI_IS_ENUM_INFO (info)) { type = &PyGIEnumInfo_Type; } else if (GI_IS_OBJECT_INFO (info)) { type = &PyGIObjectInfo_Type; } else if (GI_IS_INTERFACE_INFO (info)) { type = &PyGIInterfaceInfo_Type; } else if (GI_IS_CONSTANT_INFO (info)) { type = &PyGIConstantInfo_Type; } else if (GI_IS_UNION_INFO (info)) { type = &PyGIUnionInfo_Type; } else if (GI_IS_VALUE_INFO (info)) { type = &PyGIValueInfo_Type; } else if (GI_IS_SIGNAL_INFO (info)) { type = &PyGISignalInfo_Type; vectorcall = (vectorcallfunc)_callable_info_vectorcall; } else if (GI_IS_VFUNC_INFO (info)) { type = &PyGIVFuncInfo_Type; vectorcall = (vectorcallfunc)_callable_info_vectorcall; } else if (GI_IS_PROPERTY_INFO (info)) { type = &PyGIPropertyInfo_Type; } else if (GI_IS_FIELD_INFO (info)) { type = &PyGIFieldInfo_Type; } else if (GI_IS_ARG_INFO (info)) { type = &PyGIArgInfo_Type; } else if (GI_IS_TYPE_INFO (info)) { type = &PyGITypeInfo_Type; } else if (GI_IS_UNRESOLVED_INFO (info)) { type = &PyGIUnresolvedInfo_Type; } else { PyErr_SetString (PyExc_RuntimeError, "Invalid info type"); return NULL; } self = (PyGIBaseInfo *)type->tp_alloc (type, 0); if (self == NULL) { return NULL; } self->info = gi_base_info_ref (info); self->inst_weakreflist = NULL; if (vectorcall != NULL) { ((PyGICallableInfo *)self)->vectorcall = vectorcall; } return (PyObject *)self; } GIBaseInfo * _pygi_object_get_gi_info (PyObject *object, PyTypeObject *type) { PyObject *py_info; GIBaseInfo *info = NULL; py_info = PyObject_GetAttrString (object, "__info__"); if (py_info == NULL) { return NULL; } if (!PyObject_TypeCheck (py_info, type)) { PyErr_Format (PyExc_TypeError, "attribute '__info__' must be %s, not %s", type->tp_name, Py_TYPE (py_info)->tp_name); goto out; } info = ((PyGIBaseInfo *)py_info)->info; gi_base_info_ref (info); out: Py_DECREF (py_info); return info; } /* CallableInfo */ PYGI_DEFINE_TYPE ("gi.CallableInfo", PyGICallableInfo_Type, PyGICallableInfo); static void _callable_info_dealloc (PyGICallableInfo *self) { if (self->cache != NULL) pygi_callable_cache_free ((PyGICallableCache *)self->cache); _base_info_dealloc ((PyGIBaseInfo *)self); } /* _callable_info_call: * * Shared wrapper for invoke which can be bound (instance method or class constructor) * or unbound (function or static method). */ static PyObject * _callable_info_vectorcall (PyGICallableInfo *self, PyObject *const *args, size_t nargsf, PyObject *kwnames) { return pygi_callable_info_invoke (self, args, nargsf, kwnames); } static PyObject * _callable_info_repr (PyGICallableInfo *self) { return PyUnicode_FromFormat ("%s(%s)", Py_TYPE ((PyObject *)self)->tp_name, _safe_base_info_get_name (self->base.info)); } /* _function_info_vectorcall: * * Specialization of _callable_info_call for GIFunctionInfo which * handles constructor error conditions. */ static PyObject * _function_info_vectorcall (PyGICallableInfo *self, PyObject *const *args, size_t nargsf, PyObject *kwnames) { GIFunctionInfoFlags flags; /* Ensure constructors are only called as class methods on the class * implementing the constructor and not on sub-classes. */ flags = gi_function_info_get_flags ((GIFunctionInfo *)self->base.info); if (flags & GI_FUNCTION_IS_CONSTRUCTOR) { Py_ssize_t nargs; PyObject *cls; PyObject *py_str_name; const gchar *str_name; GIBaseInfo *container_info = gi_base_info_get_container (self->base.info); g_assert (container_info != NULL); nargs = PyVectorcall_NARGS (nargsf); cls = nargs > 0 ? args[0] : NULL; if (cls == NULL) { PyErr_BadArgument (); return NULL; } py_str_name = PyObject_GetAttrString (cls, "__name__"); if (py_str_name == NULL) return NULL; if (!PyUnicode_Check (py_str_name)) { PyErr_SetString (PyExc_TypeError, "cls.__name__ attribute is not a string"); Py_DECREF (py_str_name); return NULL; } str_name = PyUnicode_AsUTF8 (py_str_name); if (strcmp (str_name, _safe_base_info_get_name (container_info))) { PyErr_Format ( PyExc_TypeError, "%s constructor cannot be used to create instances of " "a subclass %s", _safe_base_info_get_name (container_info), str_name); Py_DECREF (py_str_name); return NULL; } Py_DECREF (py_str_name); } return _callable_info_vectorcall (self, args, nargsf, kwnames); } /* _function_info_descr_get * * Descriptor protocol implementation for functions, methods, and constructors. */ static PyObject * _function_info_descr_get (PyGICallableInfo *self, PyObject *obj, PyObject *type) { if (obj != NULL && obj != Py_None) return PyMethod_New ((PyObject *)self, obj); return Py_NewRef (self); } /* _vfunc_info_descr_get * * Descriptor protocol implementation for virtual functions. */ static PyObject * _vfunc_info_descr_get (PyGICallableInfo *self, PyObject *obj, PyObject *type) { PyObject *result; PyObject *bound_arg = NULL; if (type == NULL) type = (PyObject *)Py_TYPE (obj); bound_arg = PyObject_GetAttrString (type, "__gtype__"); if (bound_arg == NULL) return NULL; /* _new_bound_callable_info adds its own ref so free the one from GetAttrString */ result = PyMethod_New ((PyObject *)self, bound_arg); Py_DECREF (bound_arg); return result; } static PyObject * _wrap_gi_callable_info_get_arguments (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_callable_info_get_n_args, (MakeInfosCallback)gi_callable_info_get_arg); } static PyObject * _wrap_gi_callable_info_get_return_type (PyGIBaseInfo *self) { return _get_child_info ( self, (GetChildInfoCallback)gi_callable_info_get_return_type); } static PyObject * _wrap_gi_callable_info_get_caller_owns (PyGIBaseInfo *self) { return pygi_guint_to_py ( gi_callable_info_get_caller_owns (GI_CALLABLE_INFO (self->info))); } static PyObject * _wrap_gi_callable_info_may_return_null (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_callable_info_may_return_null (GI_CALLABLE_INFO (self->info))); } static PyObject * _wrap_gi_callable_info_skip_return (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_callable_info_skip_return (GI_CALLABLE_INFO (self->info))); } static PyObject * _wrap_gi_callable_info_get_return_attribute (PyGIBaseInfo *self, PyObject *py_name) { gchar *name; const gchar *attr; if (!pygi_utf8_from_py (py_name, &name)) return NULL; attr = gi_callable_info_get_return_attribute ( GI_CALLABLE_INFO (self->info), name); if (attr) { g_free (name); return pygi_utf8_to_py (attr); } else { PyErr_Format (PyExc_AttributeError, "return attribute %s not found", name); g_free (name); return NULL; } } static PyObject * _wrap_gi_callable_info_can_throw_gerror (PyGIBaseInfo *self) { if (gi_callable_info_can_throw_gerror (GI_CALLABLE_INFO (self->info))) Py_RETURN_TRUE; else Py_RETURN_FALSE; } static PyMethodDef _PyGICallableInfo_methods[] = { { "invoke", (PyCFunction)PyObject_Call, METH_VARARGS | METH_KEYWORDS }, { "get_arguments", (PyCFunction)_wrap_gi_callable_info_get_arguments, METH_NOARGS }, { "get_return_type", (PyCFunction)_wrap_gi_callable_info_get_return_type, METH_NOARGS }, { "get_caller_owns", (PyCFunction)_wrap_gi_callable_info_get_caller_owns, METH_NOARGS }, { "may_return_null", (PyCFunction)_wrap_gi_callable_info_may_return_null, METH_NOARGS }, { "skip_return", (PyCFunction)_wrap_gi_callable_info_skip_return, METH_NOARGS }, { "get_return_attribute", (PyCFunction)_wrap_gi_callable_info_get_return_attribute, METH_O }, { "can_throw_gerror", (PyCFunction)_wrap_gi_callable_info_can_throw_gerror, METH_NOARGS }, { NULL, NULL, 0 }, }; static PyObject * _callable_info_signature (PyGICallableInfo *self) { return _generate_signature (self); } static PyGetSetDef _PyGICallableInfo_getsets[] = { { "__signature__", (getter)_callable_info_signature, (setter)NULL }, { NULL, NULL, NULL }, }; PyGIFunctionCache * pygi_callable_info_get_cache (PyGICallableInfo *self) { PyGIFunctionCache *function_cache; GIBaseInfo *info = self->base.info; if (self->cache != NULL) return self->cache; if (GI_IS_FUNCTION_INFO (info)) { GIFunctionInfoFlags flags; flags = gi_function_info_get_flags (GI_FUNCTION_INFO (info)); if (flags & GI_FUNCTION_IS_CONSTRUCTOR) { function_cache = pygi_constructor_cache_new (GI_CALLABLE_INFO (info)); } else if (flags & GI_FUNCTION_IS_METHOD) { function_cache = pygi_method_cache_new (GI_CALLABLE_INFO (info)); } else { function_cache = pygi_function_cache_new (GI_CALLABLE_INFO (info)); } } else if (GI_IS_VFUNC_INFO (info)) { function_cache = pygi_vfunc_cache_new (GI_CALLABLE_INFO (info)); } else if (GI_IS_CALLBACK_INFO (info)) { g_error ("Cannot invoke callback types"); } else { function_cache = pygi_method_cache_new (GI_CALLABLE_INFO (info)); } self->cache = function_cache; return function_cache; } /* CallbackInfo */ PYGI_DEFINE_TYPE ("gi.CallbackInfo", PyGICallbackInfo_Type, PyGICallableInfo); static PyMethodDef _PyGICallbackInfo_methods[] = { { NULL, NULL, 0 }, }; /* ErrorDomainInfo */ PYGI_DEFINE_TYPE ("gi.ErrorDomainInfo", PyGIErrorDomainInfo_Type, PyGIBaseInfo); static PyMethodDef _PyGIErrorDomainInfo_methods[] = { { NULL, NULL, 0 }, }; /* SignalInfo */ PYGI_DEFINE_TYPE ("gi.SignalInfo", PyGISignalInfo_Type, PyGICallableInfo); static PyObject * _wrap_gi_signal_info_get_flags (PyGIBaseInfo *self) { return pygi_guint_to_py ( gi_signal_info_get_flags ((GISignalInfo *)self->info)); } static PyObject * _wrap_gi_signal_info_get_class_closure (PyGIBaseInfo *self) { return _get_child_info ( self, (GetChildInfoCallback)gi_signal_info_get_class_closure); } static PyObject * _wrap_gi_signal_info_true_stops_emit (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_signal_info_true_stops_emit ((GISignalInfo *)self->info)); } static PyMethodDef _PyGISignalInfo_methods[] = { { "get_flags", (PyCFunction)_wrap_gi_signal_info_get_flags, METH_NOARGS }, { "get_class_closure", (PyCFunction)_wrap_gi_signal_info_get_class_closure, METH_NOARGS }, { "true_stops_emit", (PyCFunction)_wrap_gi_signal_info_true_stops_emit, METH_NOARGS }, { NULL, NULL, 0 }, }; /* PropertyInfo */ PYGI_DEFINE_TYPE ("gi.PropertyInfo", PyGIPropertyInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_property_info_get_flags (PyGIBaseInfo *self) { return pygi_guint_to_py ( gi_property_info_get_flags ((GIPropertyInfo *)self->info)); } static PyObject * _wrap_gi_property_info_get_type_info (PyGIBaseInfo *self) { return _get_child_info ( self, (GetChildInfoCallback)gi_property_info_get_type_info); } static PyObject * _wrap_gi_property_info_get_ownership_transfer (PyGIBaseInfo *self) { return pygi_guint_to_py (gi_property_info_get_ownership_transfer ( (GIPropertyInfo *)self->info)); } static PyMethodDef _PyGIPropertyInfo_methods[] = { { "get_flags", (PyCFunction)_wrap_gi_property_info_get_flags, METH_NOARGS }, { "get_type_info", (PyCFunction)_wrap_gi_property_info_get_type_info, METH_NOARGS }, { "get_ownership_transfer", (PyCFunction)_wrap_gi_property_info_get_ownership_transfer, METH_NOARGS }, { NULL, NULL, 0 }, }; /* ArgInfo */ PYGI_DEFINE_TYPE ("gi.ArgInfo", PyGIArgInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_arg_info_get_direction (PyGIBaseInfo *self) { return pygi_guint_to_py ( gi_arg_info_get_direction ((GIArgInfo *)self->info)); } static PyObject * _wrap_gi_arg_info_is_caller_allocates (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_arg_info_is_caller_allocates ((GIArgInfo *)self->info)); } static PyObject * _wrap_gi_arg_info_is_return_value (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_arg_info_is_return_value ((GIArgInfo *)self->info)); } static PyObject * _wrap_gi_arg_info_is_optional (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_arg_info_is_optional ((GIArgInfo *)self->info)); } static PyObject * _wrap_gi_arg_info_may_be_null (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_arg_info_may_be_null ((GIArgInfo *)self->info)); } static PyObject * _wrap_gi_arg_info_get_ownership_transfer (PyGIBaseInfo *self) { return pygi_guint_to_py ( gi_arg_info_get_ownership_transfer ((GIArgInfo *)self->info)); } static PyObject * _wrap_gi_arg_info_get_scope (PyGIBaseInfo *self) { return pygi_guint_to_py (gi_arg_info_get_scope ((GIArgInfo *)self->info)); } static PyObject * _wrap_gi_arg_info_get_closure_index (PyGIBaseInfo *self) { unsigned int closure_index; if (gi_arg_info_get_closure_index ((GIArgInfo *)self->info, &closure_index)) return pygi_guint_to_py (closure_index); else return pygi_gint_to_py (-1); } static PyObject * _wrap_gi_arg_info_get_destroy_index (PyGIBaseInfo *self) { unsigned int destroy_index; if (gi_arg_info_get_destroy_index ((GIArgInfo *)self->info, &destroy_index)) return pygi_guint_to_py (destroy_index); else return pygi_gint_to_py (-1); } static PyObject * _wrap_gi_arg_info_get_type_info (PyGIBaseInfo *self) { return _get_child_info (self, (GetChildInfoCallback)gi_arg_info_get_type_info); } static PyMethodDef _PyGIArgInfo_methods[] = { { "get_direction", (PyCFunction)_wrap_gi_arg_info_get_direction, METH_NOARGS }, { "is_caller_allocates", (PyCFunction)_wrap_gi_arg_info_is_caller_allocates, METH_NOARGS }, { "is_return_value", (PyCFunction)_wrap_gi_arg_info_is_return_value, METH_NOARGS }, { "is_optional", (PyCFunction)_wrap_gi_arg_info_is_optional, METH_NOARGS }, { "may_be_null", (PyCFunction)_wrap_gi_arg_info_may_be_null, METH_NOARGS }, { "get_ownership_transfer", (PyCFunction)_wrap_gi_arg_info_get_ownership_transfer, METH_NOARGS }, { "get_scope", (PyCFunction)_wrap_gi_arg_info_get_scope, METH_NOARGS }, { "get_closure_index", (PyCFunction)_wrap_gi_arg_info_get_closure_index, METH_NOARGS }, { "get_destroy_index", (PyCFunction)_wrap_gi_arg_info_get_destroy_index, METH_NOARGS }, { "get_type_info", (PyCFunction)_wrap_gi_arg_info_get_type_info, METH_NOARGS }, { NULL, NULL, 0 }, }; /* TypeInfo */ PYGI_DEFINE_TYPE ("gi.TypeInfo", PyGITypeInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_type_info_is_pointer (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_type_info_is_pointer (GI_TYPE_INFO (self->info))); } static PyObject * _wrap_gi_type_info_get_tag (PyGIBaseInfo *self) { return pygi_guint_to_py (gi_type_info_get_tag (GI_TYPE_INFO (self->info))); } static PyObject * _wrap_gi_type_info_get_tag_as_string (PyGIBaseInfo *self) { GITypeTag tag = gi_type_info_get_tag (GI_TYPE_INFO (self->info)); return pygi_utf8_to_py (gi_type_tag_to_string (tag)); } static PyObject * _wrap_gi_type_info_get_param_type (PyGIBaseInfo *self, PyObject *py_n) { GIBaseInfo *info; PyObject *py_info; gint n; if (!pygi_gint_from_py (py_n, &n)) return NULL; info = (GIBaseInfo *)gi_type_info_get_param_type ((GITypeInfo *)self->info, n); if (info == NULL) { Py_RETURN_NONE; } py_info = _pygi_info_new (info); gi_base_info_unref (info); return py_info; } static PyObject * _wrap_gi_type_info_get_interface (PyGIBaseInfo *self) { return _get_child_info (self, (GetChildInfoCallback)gi_type_info_get_interface); } static PyObject * _wrap_gi_type_info_get_array_length_index (PyGIBaseInfo *self) { unsigned int idx; if (gi_type_info_get_array_length_index (GI_TYPE_INFO (self->info), &idx)) return pygi_guint_to_py (idx); else return pygi_gint_to_py (-1); } static PyObject * _wrap_gi_type_info_get_array_fixed_size (PyGIBaseInfo *self) { size_t size; if (gi_type_info_get_array_fixed_size (GI_TYPE_INFO (self->info), &size)) return pygi_gint_to_py (size); g_assert_not_reached (); } static PyObject * _wrap_gi_type_info_is_zero_terminated (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_type_info_is_zero_terminated (GI_TYPE_INFO (self->info))); } static PyObject * _wrap_gi_type_info_get_array_type (PyGIBaseInfo *self) { return pygi_guint_to_py ( gi_type_info_get_array_type (GI_TYPE_INFO (self->info))); } static PyMethodDef _PyGITypeInfo_methods[] = { { "is_pointer", (PyCFunction)_wrap_gi_type_info_is_pointer, METH_NOARGS }, { "get_tag", (PyCFunction)_wrap_gi_type_info_get_tag, METH_NOARGS }, { "get_tag_as_string", (PyCFunction)_wrap_gi_type_info_get_tag_as_string, METH_NOARGS }, { "get_param_type", (PyCFunction)_wrap_gi_type_info_get_param_type, METH_O }, { "get_interface", (PyCFunction)_wrap_gi_type_info_get_interface, METH_NOARGS }, { "get_array_length_index", (PyCFunction)_wrap_gi_type_info_get_array_length_index, METH_NOARGS }, { "get_array_fixed_size", (PyCFunction)_wrap_gi_type_info_get_array_fixed_size, METH_NOARGS }, { "is_zero_terminated", (PyCFunction)_wrap_gi_type_info_is_zero_terminated, METH_NOARGS }, { "get_array_type", (PyCFunction)_wrap_gi_type_info_get_array_type, METH_NOARGS }, { NULL, NULL, 0 }, }; /* FunctionInfo */ PYGI_DEFINE_TYPE ("gi.FunctionInfo", PyGIFunctionInfo_Type, PyGICallableInfo); static PyObject * _wrap_gi_function_info_is_constructor (PyGIBaseInfo *self) { GIFunctionInfoFlags flags; gboolean is_constructor; flags = gi_function_info_get_flags ((GIFunctionInfo *)self->info); is_constructor = flags & GI_FUNCTION_IS_CONSTRUCTOR; return pygi_gboolean_to_py (is_constructor); } static PyObject * _wrap_gi_function_info_is_method (PyGIBaseInfo *self) { GIFunctionInfoFlags flags; gboolean is_method; flags = gi_function_info_get_flags ((GIFunctionInfo *)self->info); is_method = flags & GI_FUNCTION_IS_METHOD; return pygi_gboolean_to_py (is_method); } gsize _pygi_g_type_tag_size (GITypeTag type_tag) { gsize size = 0; switch (type_tag) { case GI_TYPE_TAG_BOOLEAN: size = sizeof (gboolean); break; case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_UINT8: size = sizeof (gint8); break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: size = sizeof (gint16); break; case GI_TYPE_TAG_INT32: case GI_TYPE_TAG_UINT32: size = sizeof (gint32); break; case GI_TYPE_TAG_INT64: case GI_TYPE_TAG_UINT64: size = sizeof (gint64); break; case GI_TYPE_TAG_FLOAT: size = sizeof (gfloat); break; case GI_TYPE_TAG_DOUBLE: size = sizeof (gdouble); break; case GI_TYPE_TAG_GTYPE: size = sizeof (GType); break; case GI_TYPE_TAG_UNICHAR: size = sizeof (gunichar); break; case GI_TYPE_TAG_VOID: case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_ARRAY: case GI_TYPE_TAG_INTERFACE: case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_GHASH: case GI_TYPE_TAG_ERROR: PyErr_Format (PyExc_TypeError, "Unable to know the size (assuming %s is not a pointer)", gi_type_tag_to_string (type_tag)); break; default: break; } return size; } gsize _pygi_gi_type_info_size (GITypeInfo *type_info) { gsize size = 0; GITypeTag type_tag; type_tag = gi_type_info_get_tag (type_info); switch (type_tag) { case GI_TYPE_TAG_BOOLEAN: case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_UINT8: case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_INT32: case GI_TYPE_TAG_UINT32: case GI_TYPE_TAG_INT64: case GI_TYPE_TAG_UINT64: case GI_TYPE_TAG_FLOAT: case GI_TYPE_TAG_DOUBLE: case GI_TYPE_TAG_GTYPE: case GI_TYPE_TAG_UNICHAR: size = _pygi_g_type_tag_size (type_tag); g_assert (size > 0); break; case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *info; info = gi_type_info_get_interface (type_info); if (GI_IS_STRUCT_INFO (info)) { if (gi_type_info_is_pointer (type_info)) { size = sizeof (gpointer); } else { size = gi_struct_info_get_size ((GIStructInfo *)info); } } else if (GI_IS_UNION_INFO (info)) { if (gi_type_info_is_pointer (type_info)) { size = sizeof (gpointer); } else { size = gi_union_info_get_size ((GIUnionInfo *)info); } } else if (GI_IS_ENUM_INFO (info)) { if (gi_type_info_is_pointer (type_info)) { size = sizeof (gpointer); } else { GITypeTag enum_type_tag; enum_type_tag = gi_enum_info_get_storage_type ((GIEnumInfo *)info); size = _pygi_g_type_tag_size (enum_type_tag); } } else if (GI_IS_OBJECT_INFO (info) || GI_IS_INTERFACE_INFO (info) || GI_IS_CALLBACK_INFO (info)) { size = sizeof (gpointer); } else { g_assert_not_reached (); } gi_base_info_unref (info); break; } case GI_TYPE_TAG_ARRAY: case GI_TYPE_TAG_VOID: case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_GHASH: case GI_TYPE_TAG_ERROR: size = sizeof (gpointer); break; default: break; } return size; } static PyObject * _wrap_gi_function_info_get_symbol (PyGIBaseInfo *self) { return _get_info_string ( gi_function_info_get_symbol (GI_FUNCTION_INFO (self->info))); } static PyObject * _wrap_gi_function_info_get_flags (PyGIBaseInfo *self) { return pygi_guint_to_py ( gi_function_info_get_flags (GI_FUNCTION_INFO (self->info))); } static PyObject * _wrap_gi_function_info_get_property (PyGIBaseInfo *self) { return _get_child_info ( self, (GetChildInfoCallback)gi_function_info_get_property); } static PyObject * _wrap_gi_function_info_get_vfunc (PyGIBaseInfo *self) { return _get_child_info (self, (GetChildInfoCallback)gi_function_info_get_vfunc); } static PyObject * _wrap_gi_function_info_get_finish_func (PyGICallableInfo *self) { PyGIFunctionCache *cache = pygi_callable_info_get_cache (self); if (PyErr_Occurred ()) return NULL; if (cache == NULL) return NULL; if (cache->async_finish) { Py_INCREF (cache->async_finish); return cache->async_finish; } Py_RETURN_NONE; } static PyMethodDef _PyGIFunctionInfo_methods[] = { { "is_constructor", (PyCFunction)_wrap_gi_function_info_is_constructor, METH_NOARGS }, { "is_method", (PyCFunction)_wrap_gi_function_info_is_method, METH_NOARGS }, { "get_symbol", (PyCFunction)_wrap_gi_function_info_get_symbol, METH_NOARGS }, { "get_flags", (PyCFunction)_wrap_gi_function_info_get_flags, METH_NOARGS }, { "get_property", (PyCFunction)_wrap_gi_function_info_get_property, METH_NOARGS }, { "get_vfunc", (PyCFunction)_wrap_gi_function_info_get_vfunc, METH_NOARGS }, { "get_finish_func", (PyCFunction)_wrap_gi_function_info_get_finish_func, METH_NOARGS }, { NULL, NULL, 0 }, }; /* RegisteredTypeInfo */ PYGI_DEFINE_TYPE ("gi.RegisteredTypeInfo", PyGIRegisteredTypeInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_registered_type_info_get_type_name (PyGIBaseInfo *self) { return _get_info_string (gi_registered_type_info_get_type_name ( GI_REGISTERED_TYPE_INFO (self->info))); } static PyObject * _wrap_gi_registered_type_info_get_type_init (PyGIBaseInfo *self) { return _get_info_string ( gi_registered_type_info_get_type_init_function_name ( GI_REGISTERED_TYPE_INFO (self->info))); } static PyObject * _wrap_gi_registered_type_info_get_g_type (PyGIBaseInfo *self) { GType type; type = gi_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)self->info); return pyg_type_wrapper_new (type); } static PyMethodDef _PyGIRegisteredTypeInfo_methods[] = { { "get_type_name", (PyCFunction)_wrap_gi_registered_type_info_get_type_name, METH_NOARGS }, { "get_type_init", (PyCFunction)_wrap_gi_registered_type_info_get_type_init, METH_NOARGS }, { "get_g_type", (PyCFunction)_wrap_gi_registered_type_info_get_g_type, METH_NOARGS }, { NULL, NULL, 0 }, }; /* GIStructInfo */ PYGI_DEFINE_TYPE ("StructInfo", PyGIStructInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_struct_info_get_fields (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_struct_info_get_n_fields, (MakeInfosCallback)gi_struct_info_get_field); } static PyObject * _wrap_gi_struct_info_get_methods (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_struct_info_get_n_methods, (MakeInfosCallback)gi_struct_info_get_method); } static PyObject * _wrap_gi_struct_info_get_size (PyGIBaseInfo *self) { return pygi_gsize_to_py ( gi_struct_info_get_size (GI_STRUCT_INFO (self->info))); } static PyObject * _wrap_gi_struct_info_get_alignment (PyGIBaseInfo *self) { return pygi_gsize_to_py ( gi_struct_info_get_alignment (GI_STRUCT_INFO (self->info))); } static PyObject * _wrap_gi_struct_info_is_gtype_struct (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_struct_info_is_gtype_struct (GI_STRUCT_INFO (self->info))); } static PyObject * _wrap_gi_struct_info_is_foreign (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_struct_info_is_foreign (GI_STRUCT_INFO (self->info))); } static PyObject * _wrap_gi_struct_info_find_method (PyGIBaseInfo *self, PyObject *py_name) { return _get_child_info_by_name ( self, py_name, (GetChildInfoByNameCallback)gi_struct_info_find_method); } static PyObject * _wrap_gi_struct_info_find_field (PyGIBaseInfo *self, PyObject *py_name) { return _get_child_info_by_name ( self, py_name, (GetChildInfoByNameCallback)gi_struct_info_find_field); } static PyMethodDef _PyGIStructInfo_methods[] = { { "get_fields", (PyCFunction)_wrap_gi_struct_info_get_fields, METH_NOARGS }, { "find_field", (PyCFunction)_wrap_gi_struct_info_find_field, METH_O }, { "get_methods", (PyCFunction)_wrap_gi_struct_info_get_methods, METH_NOARGS }, { "find_method", (PyCFunction)_wrap_gi_struct_info_find_method, METH_O }, { "get_size", (PyCFunction)_wrap_gi_struct_info_get_size, METH_NOARGS }, { "get_alignment", (PyCFunction)_wrap_gi_struct_info_get_alignment, METH_NOARGS }, { "is_gtype_struct", (PyCFunction)_wrap_gi_struct_info_is_gtype_struct, METH_NOARGS }, { "is_foreign", (PyCFunction)_wrap_gi_struct_info_is_foreign, METH_NOARGS }, { NULL, NULL, 0 }, }; gboolean pygi_gi_struct_info_is_simple (GIStructInfo *struct_info) { gboolean is_simple; gint n_field_infos; gint i; is_simple = TRUE; n_field_infos = gi_struct_info_get_n_fields (struct_info); for (i = 0; i < n_field_infos && is_simple; i++) { GIFieldInfo *field_info; GITypeInfo *field_type_info; GITypeTag field_type_tag; field_info = gi_struct_info_get_field (struct_info, i); field_type_info = gi_field_info_get_type_info (field_info); field_type_tag = gi_type_info_get_tag (field_type_info); switch (field_type_tag) { case GI_TYPE_TAG_BOOLEAN: case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_UINT8: case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_INT32: case GI_TYPE_TAG_UINT32: case GI_TYPE_TAG_INT64: case GI_TYPE_TAG_UINT64: case GI_TYPE_TAG_FLOAT: case GI_TYPE_TAG_DOUBLE: case GI_TYPE_TAG_UNICHAR: if (gi_type_info_is_pointer (field_type_info)) { is_simple = FALSE; } break; case GI_TYPE_TAG_VOID: case GI_TYPE_TAG_GTYPE: case GI_TYPE_TAG_ERROR: case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_ARRAY: case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_GHASH: is_simple = FALSE; break; case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *info; info = gi_type_info_get_interface (field_type_info); if (GI_IS_STRUCT_INFO (info)) { if (gi_type_info_is_pointer (field_type_info)) { is_simple = FALSE; } else { is_simple = pygi_gi_struct_info_is_simple ((GIStructInfo *)info); } } else if (GI_IS_UNION_INFO (info)) { /* TODO */ is_simple = FALSE; } else if (GI_IS_ENUM_INFO (info)) { if (gi_type_info_is_pointer (field_type_info)) { is_simple = FALSE; } } else if (GI_IS_OBJECT_INFO (info) || GI_IS_CALLBACK_INFO (info) || GI_IS_INTERFACE_INFO (info)) { is_simple = FALSE; } else { g_assert_not_reached (); } gi_base_info_unref (info); break; } default: g_assert_not_reached (); break; } gi_base_info_unref ((GIBaseInfo *)field_type_info); gi_base_info_unref ((GIBaseInfo *)field_info); } return is_simple; } /* EnumInfo */ PYGI_DEFINE_TYPE ("gi.EnumInfo", PyGIEnumInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_enum_info_get_values (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_enum_info_get_n_values, (MakeInfosCallback)gi_enum_info_get_value); } static PyObject * _wrap_gi_enum_info_is_flags (PyGIBaseInfo *self) { if (GI_IS_FLAGS_INFO (self->info)) { /* Check flags before enums: flags are a subtype of enum. */ Py_RETURN_TRUE; } else if (GI_IS_ENUM_INFO (self->info)) { Py_RETURN_FALSE; } else { g_assert_not_reached (); } } static PyObject * _wrap_gi_enum_info_get_methods (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_enum_info_get_n_methods, (MakeInfosCallback)gi_enum_info_get_method); } static PyObject * _wrap_gi_enum_info_get_storage_type (PyGIBaseInfo *self) { return pygi_guint_to_py ( gi_enum_info_get_storage_type (GI_ENUM_INFO (self->info))); } static PyMethodDef _PyGIEnumInfo_methods[] = { { "get_values", (PyCFunction)_wrap_gi_enum_info_get_values, METH_NOARGS }, { "is_flags", (PyCFunction)_wrap_gi_enum_info_is_flags, METH_NOARGS }, { "get_methods", (PyCFunction)_wrap_gi_enum_info_get_methods, METH_NOARGS }, { "get_storage_type", (PyCFunction)_wrap_gi_enum_info_get_storage_type, METH_NOARGS }, { NULL, NULL, 0 }, }; /* ObjectInfo */ PYGI_DEFINE_TYPE ("ObjectInfo", PyGIObjectInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_object_info_get_parent (PyGIBaseInfo *self) { return _get_child_info (self, (GetChildInfoCallback)gi_object_info_get_parent); } static PyObject * _wrap_gi_object_info_get_methods (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_object_info_get_n_methods, (MakeInfosCallback)gi_object_info_get_method); } static PyObject * _wrap_gi_object_info_find_method (PyGIBaseInfo *self, PyObject *py_name) { return _get_child_info_by_name ( self, py_name, (GetChildInfoByNameCallback)gi_object_info_find_method); } static PyObject * _wrap_gi_object_info_get_fields (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_object_info_get_n_fields, (MakeInfosCallback)gi_object_info_get_field); } static PyObject * _wrap_gi_object_info_get_properties (PyGIBaseInfo *self) { return _make_infos_tuple ( self, (GetNInfosCallback)gi_object_info_get_n_properties, (MakeInfosCallback)gi_object_info_get_property); } static PyObject * _wrap_gi_object_info_get_signals (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_object_info_get_n_signals, (MakeInfosCallback)gi_object_info_get_signal); } static PyObject * _wrap_gi_object_info_get_interfaces (PyGIBaseInfo *self) { return _make_infos_tuple ( self, (GetNInfosCallback)gi_object_info_get_n_interfaces, (MakeInfosCallback)gi_object_info_get_interface); } static PyObject * _wrap_gi_object_info_get_constants (PyGIBaseInfo *self) { return _make_infos_tuple ( self, (GetNInfosCallback)gi_object_info_get_n_constants, (MakeInfosCallback)gi_object_info_get_constant); } static PyObject * _wrap_gi_object_info_get_vfuncs (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_object_info_get_n_vfuncs, (MakeInfosCallback)gi_object_info_get_vfunc); } static PyObject * _wrap_gi_object_info_get_abstract (PyGIBaseInfo *self) { gboolean is_abstract = gi_object_info_get_abstract ((GIObjectInfo *)self->info); return pygi_gboolean_to_py (is_abstract); } static PyObject * _wrap_gi_object_info_get_type_name (PyGIBaseInfo *self) { return _get_info_string ( gi_object_info_get_type_name (GI_OBJECT_INFO (self->info))); } static PyObject * _wrap_gi_object_info_get_type_init (PyGIBaseInfo *self) { return _get_info_string (gi_object_info_get_type_init_function_name ( GI_OBJECT_INFO (self->info))); } static PyObject * _wrap_gi_object_info_get_fundamental (PyGIBaseInfo *self) { return pygi_gboolean_to_py ( gi_object_info_get_fundamental ((GIObjectInfo *)self->info)); } static PyObject * _wrap_gi_object_info_get_class_struct (PyGIBaseInfo *self) { return _get_child_info ( self, (GetChildInfoCallback)gi_object_info_get_class_struct); } static PyObject * _wrap_gi_object_info_find_vfunc (PyGIBaseInfo *self, PyObject *py_name) { return _get_child_info_by_name ( self, py_name, (GetChildInfoByNameCallback)gi_object_info_find_vfunc); } static PyObject * _wrap_gi_object_info_get_unref_function (PyGIBaseInfo *self) { return _get_info_string ( gi_object_info_get_unref_function_name (GI_OBJECT_INFO (self->info))); } static PyObject * _wrap_gi_object_info_get_ref_function (PyGIBaseInfo *self) { return _get_info_string ( gi_object_info_get_ref_function_name (GI_OBJECT_INFO (self->info))); } static PyObject * _wrap_gi_object_info_get_set_value_function (PyGIBaseInfo *self) { return _get_info_string (gi_object_info_get_set_value_function_name ( GI_OBJECT_INFO (self->info))); } static PyObject * _wrap_gi_object_info_get_get_value_function (PyGIBaseInfo *self) { return _get_info_string (gi_object_info_get_get_value_function_name ( GI_OBJECT_INFO (self->info))); } static PyMethodDef _PyGIObjectInfo_methods[] = { { "get_parent", (PyCFunction)_wrap_gi_object_info_get_parent, METH_NOARGS }, { "get_methods", (PyCFunction)_wrap_gi_object_info_get_methods, METH_NOARGS }, { "find_method", (PyCFunction)_wrap_gi_object_info_find_method, METH_O }, { "get_fields", (PyCFunction)_wrap_gi_object_info_get_fields, METH_NOARGS }, { "get_properties", (PyCFunction)_wrap_gi_object_info_get_properties, METH_NOARGS }, { "get_signals", (PyCFunction)_wrap_gi_object_info_get_signals, METH_NOARGS }, { "get_interfaces", (PyCFunction)_wrap_gi_object_info_get_interfaces, METH_NOARGS }, { "get_constants", (PyCFunction)_wrap_gi_object_info_get_constants, METH_NOARGS }, { "get_vfuncs", (PyCFunction)_wrap_gi_object_info_get_vfuncs, METH_NOARGS }, { "find_vfunc", (PyCFunction)_wrap_gi_object_info_find_vfunc, METH_O }, { "get_abstract", (PyCFunction)_wrap_gi_object_info_get_abstract, METH_NOARGS }, { "get_type_name", (PyCFunction)_wrap_gi_object_info_get_type_name, METH_NOARGS }, { "get_type_init", (PyCFunction)_wrap_gi_object_info_get_type_init, METH_NOARGS }, { "get_fundamental", (PyCFunction)_wrap_gi_object_info_get_fundamental, METH_NOARGS }, { "get_class_struct", (PyCFunction)_wrap_gi_object_info_get_class_struct, METH_NOARGS }, { "get_unref_function", (PyCFunction)_wrap_gi_object_info_get_unref_function, METH_NOARGS }, { "get_ref_function", (PyCFunction)_wrap_gi_object_info_get_ref_function, METH_NOARGS }, { "get_set_value_function", (PyCFunction)_wrap_gi_object_info_get_set_value_function, METH_NOARGS }, { "get_get_value_function", (PyCFunction)_wrap_gi_object_info_get_get_value_function, METH_NOARGS }, { NULL, NULL, 0 }, }; /* GIInterfaceInfo */ PYGI_DEFINE_TYPE ("InterfaceInfo", PyGIInterfaceInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_interface_info_get_methods (PyGIBaseInfo *self) { return _make_infos_tuple ( self, (GetNInfosCallback)gi_interface_info_get_n_methods, (MakeInfosCallback)gi_interface_info_get_method); } static PyObject * _wrap_gi_interface_info_find_method (PyGIBaseInfo *self, PyObject *py_name) { return _get_child_info_by_name ( self, py_name, (GetChildInfoByNameCallback)gi_interface_info_find_method); } static PyObject * _wrap_gi_interface_info_get_constants (PyGIBaseInfo *self) { return _make_infos_tuple ( self, (GetNInfosCallback)gi_interface_info_get_n_constants, (MakeInfosCallback)gi_interface_info_get_constant); } static PyObject * _wrap_gi_interface_info_get_vfuncs (PyGIBaseInfo *self) { return _make_infos_tuple ( self, (GetNInfosCallback)gi_interface_info_get_n_vfuncs, (MakeInfosCallback)gi_interface_info_get_vfunc); } static PyObject * _wrap_gi_interface_info_find_vfunc (PyGIBaseInfo *self, PyObject *py_name) { return _get_child_info_by_name ( self, py_name, (GetChildInfoByNameCallback)gi_interface_info_find_vfunc); } static PyObject * _wrap_gi_interface_info_get_prerequisites (PyGIBaseInfo *self) { return _make_infos_tuple ( self, (GetNInfosCallback)gi_interface_info_get_n_prerequisites, (MakeInfosCallback)gi_interface_info_get_prerequisite); } static PyObject * _wrap_gi_interface_info_get_properties (PyGIBaseInfo *self) { return _make_infos_tuple ( self, (GetNInfosCallback)gi_interface_info_get_n_properties, (MakeInfosCallback)gi_interface_info_get_property); } static PyObject * _wrap_gi_interface_info_get_iface_struct (PyGIBaseInfo *self) { return _get_child_info ( self, (GetChildInfoCallback)gi_interface_info_get_iface_struct); } static PyObject * _wrap_gi_interface_info_get_signals (PyGIBaseInfo *self) { return _make_infos_tuple ( self, (GetNInfosCallback)gi_interface_info_get_n_signals, (MakeInfosCallback)gi_interface_info_get_signal); } static PyObject * _wrap_gi_interface_info_find_signal (PyGIBaseInfo *self, PyObject *py_name) { return _get_child_info_by_name ( self, py_name, (GetChildInfoByNameCallback)gi_interface_info_find_signal); } static PyMethodDef _PyGIInterfaceInfo_methods[] = { { "get_prerequisites", (PyCFunction)_wrap_gi_interface_info_get_prerequisites, METH_NOARGS }, { "get_properties", (PyCFunction)_wrap_gi_interface_info_get_properties, METH_NOARGS }, { "get_methods", (PyCFunction)_wrap_gi_interface_info_get_methods, METH_NOARGS }, { "find_method", (PyCFunction)_wrap_gi_interface_info_find_method, METH_O }, { "get_signals", (PyCFunction)_wrap_gi_interface_info_get_signals, METH_NOARGS }, { "find_signal", (PyCFunction)_wrap_gi_interface_info_find_signal, METH_O }, { "get_vfuncs", (PyCFunction)_wrap_gi_interface_info_get_vfuncs, METH_NOARGS }, { "get_constants", (PyCFunction)_wrap_gi_interface_info_get_constants, METH_NOARGS }, { "get_iface_struct", (PyCFunction)_wrap_gi_interface_info_get_iface_struct, METH_NOARGS }, { "find_vfunc", (PyCFunction)_wrap_gi_interface_info_find_vfunc, METH_O }, { NULL, NULL, 0 }, }; /* GIConstantInfo */ PYGI_DEFINE_TYPE ("gi.ConstantInfo", PyGIConstantInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_constant_info_get_value (PyGIBaseInfo *self) { GITypeInfo *type_info; GIArgument value = { 0 }; PyObject *py_value; gboolean free_array = FALSE; gi_constant_info_get_value ((GIConstantInfo *)self->info, &value); type_info = gi_constant_info_get_type_info ((GIConstantInfo *)self->info); if (gi_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY) { value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL, NULL, type_info, &free_array); } py_value = _pygi_argument_to_object (&value, type_info, GI_TRANSFER_NOTHING); if (free_array) { g_array_free (value.v_pointer, FALSE); } gi_constant_info_free_value (GI_CONSTANT_INFO (self->info), &value); gi_base_info_unref ((GIBaseInfo *)type_info); return py_value; } static PyMethodDef _PyGIConstantInfo_methods[] = { { "get_value", (PyCFunction)_wrap_gi_constant_info_get_value, METH_NOARGS }, { NULL, NULL, 0 }, }; /* GIValueInfo */ PYGI_DEFINE_TYPE ("gi.ValueInfo", PyGIValueInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_value_info_get_value (PyGIBaseInfo *self) { gint64 value; value = gi_value_info_get_value ((GIValueInfo *)self->info); return pygi_gint64_to_py (value); } static PyMethodDef _PyGIValueInfo_methods[] = { { "get_value", (PyCFunction)_wrap_gi_value_info_get_value, METH_NOARGS }, { NULL, NULL, 0 }, }; /* GIFieldInfo */ PYGI_DEFINE_TYPE ("gi.FieldInfo", PyGIFieldInfo_Type, PyGIBaseInfo); static gssize _struct_field_array_length_marshal (gsize length_index, void *container_ptr, void *struct_data_ptr) { gssize array_len = -1; GIFieldInfo *array_len_field = NULL; GIArgument arg = { 0 }; GIBaseInfo *container_info = (GIBaseInfo *)container_ptr; if (GI_IS_UNION_INFO (container_info)) { array_len_field = gi_union_info_get_field ( (GIUnionInfo *)container_info, (gint)length_index); } else if (GI_IS_STRUCT_INFO (container_info)) { array_len_field = gi_struct_info_get_field ( (GIStructInfo *)container_info, (gint)length_index); } else if (GI_IS_OBJECT_INFO (container_info)) { array_len_field = gi_object_info_get_field ( (GIObjectInfo *)container_info, (gint)length_index); } else { /* Other types don't have fields. */ g_assert_not_reached (); } if (array_len_field == NULL) { return -1; } if (gi_field_info_get_field (array_len_field, struct_data_ptr, &arg)) { GITypeInfo *array_len_type_info; array_len_type_info = gi_field_info_get_type_info (array_len_field); if (array_len_type_info == NULL) { goto out; } if (!pygi_argument_to_gssize ( &arg, gi_type_info_get_tag (array_len_type_info), &array_len)) { array_len = -1; } gi_base_info_unref (array_len_type_info); } out: gi_base_info_unref (array_len_field); return array_len; } static gint _pygi_gi_registered_type_info_check_object (GIRegisteredTypeInfo *info, PyObject *object) { gint retval; GType g_type; PyObject *py_type; gchar *type_name_expected = NULL; if ((GI_IS_STRUCT_INFO (info)) && (gi_struct_info_is_foreign ((GIStructInfo *)info))) { /* TODO: Could we check is the correct foreign type? */ return 1; } g_type = gi_registered_type_info_get_g_type (info); if (g_type != G_TYPE_NONE) { py_type = pygi_type_get_from_g_type (g_type); } else { py_type = pygi_type_import_by_gi_info ((GIBaseInfo *)info); } if (py_type == NULL) { return 0; } g_assert (PyType_Check (py_type)); retval = PyObject_IsInstance (object, py_type); if (!retval) { type_name_expected = _pygi_gi_base_info_get_fullname ((GIBaseInfo *)info); } Py_DECREF (py_type); if (!retval) { PyTypeObject *object_type; if (type_name_expected == NULL) { return -1; } object_type = (PyTypeObject *)PyObject_Type (object); if (object_type == NULL) { g_free (type_name_expected); return -1; } PyErr_Format (PyExc_TypeError, "Must be %s, not %s", type_name_expected, object_type->tp_name); g_free (type_name_expected); } return retval; } static PyObject * _wrap_gi_field_info_get_value (PyGIBaseInfo *self, PyObject *args) { PyObject *instance; GIBaseInfo *container_info; gpointer pointer; GITypeInfo *field_type_info; GIArgument value; PyObject *py_value = NULL; gboolean free_array = FALSE; memset (&value, 0, sizeof (GIArgument)); if (!PyArg_ParseTuple (args, "O:FieldInfo.get_value", &instance)) { return NULL; } container_info = gi_base_info_get_container (self->info); g_assert (container_info != NULL); /* Check the instance. */ if (!_pygi_gi_registered_type_info_check_object ( (GIRegisteredTypeInfo *)container_info, instance)) { _PyGI_ERROR_PREFIX ("argument 1: "); return NULL; } /* Get the pointer to the container. */ if (GI_IS_UNION_INFO (container_info) || GI_IS_STRUCT_INFO (container_info)) { pointer = pyg_boxed_get (instance, void); } else if (GI_IS_OBJECT_INFO (container_info)) { if (pygi_check_fundamental (container_info)) pointer = pygi_fundamental_get (instance); else pointer = pygobject_get (instance); } else { /* Other types don't have fields. */ g_assert_not_reached (); } if (pointer == NULL) { PyErr_Format (PyExc_RuntimeError, "object at %p of type %s is not initialized", instance, Py_TYPE (instance)->tp_name); return NULL; } /* Get the field's value. */ field_type_info = gi_field_info_get_type_info ((GIFieldInfo *)self->info); /* A few types are not handled by gi_field_info_get_field, so do it here. */ if (!gi_type_info_is_pointer (field_type_info) && gi_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) { GIBaseInfo *info; if (!(gi_field_info_get_flags ((GIFieldInfo *)self->info) & GI_FIELD_IS_READABLE)) { PyErr_SetString (PyExc_RuntimeError, "field is not readable"); goto out; } info = gi_type_info_get_interface (field_type_info); if (GI_IS_UNION_INFO (info)) { PyErr_SetString (PyExc_NotImplementedError, "getting an union is not supported yet"); gi_base_info_unref (info); goto out; } else if (GI_IS_STRUCT_INFO (info)) { gsize offset; offset = gi_field_info_get_offset ((GIFieldInfo *)self->info); value.v_pointer = (char *)pointer + offset; gi_base_info_unref (info); goto argument_to_object; } else { gi_base_info_unref (info); /* Fallback. */ } } if (!gi_field_info_get_field ((GIFieldInfo *)self->info, pointer, &value)) { PyErr_SetString (PyExc_RuntimeError, "unable to get the value"); goto out; } if (gi_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) { value.v_pointer = _pygi_argument_to_array ( &value, _struct_field_array_length_marshal, container_info, pointer, field_type_info, &free_array); } argument_to_object: py_value = _pygi_argument_to_object (&value, field_type_info, GI_TRANSFER_NOTHING); if (free_array) { g_array_free (value.v_pointer, FALSE); } out: gi_base_info_unref ((GIBaseInfo *)field_type_info); return py_value; } static PyObject * _wrap_gi_field_info_set_value (PyGIBaseInfo *self, PyObject *args) { PyObject *instance; PyObject *py_value; GIBaseInfo *container_info; gpointer pointer; GITypeInfo *field_type_info; GIArgument value; PyObject *retval = NULL; if (!PyArg_ParseTuple (args, "OO:FieldInfo.set_value", &instance, &py_value)) { return NULL; } container_info = gi_base_info_get_container (self->info); g_assert (container_info != NULL); /* Check the instance. */ if (!_pygi_gi_registered_type_info_check_object ( (GIRegisteredTypeInfo *)container_info, instance)) { _PyGI_ERROR_PREFIX ("argument 1: "); return NULL; } /* Get the pointer to the container. */ if (GI_IS_UNION_INFO (container_info) || GI_IS_STRUCT_INFO (container_info)) { pointer = pyg_boxed_get (instance, void); } else if (GI_IS_OBJECT_INFO (container_info)) { if (pygi_check_fundamental (container_info)) pointer = pygi_fundamental_get (instance); else pointer = pygobject_get (instance); } else { /* Other types don't have fields. */ g_assert_not_reached (); } if (pointer == NULL) { PyErr_Format (PyExc_RuntimeError, "object at %p of type %s is not initialized", instance, Py_TYPE (instance)->tp_name); return NULL; } field_type_info = gi_field_info_get_type_info ((GIFieldInfo *)self->info); /* Set the field's value. */ /* A few types are not handled by gi_field_info_set_field, so do it here. */ if (!gi_type_info_is_pointer (field_type_info) && gi_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) { GIBaseInfo *info; if (!(gi_field_info_get_flags ((GIFieldInfo *)self->info) & GI_FIELD_IS_WRITABLE)) { PyErr_SetString (PyExc_RuntimeError, "field is not writable"); goto out; } info = gi_type_info_get_interface (field_type_info); if (GI_IS_UNION_INFO (info)) { PyErr_SetString (PyExc_NotImplementedError, "setting an union is not supported yet"); goto out; } else if (GI_IS_STRUCT_INFO (info)) { gboolean is_simple; gsize offset; gssize size; is_simple = pygi_gi_struct_info_is_simple ((GIStructInfo *)info); if (!is_simple) { PyErr_SetString (PyExc_TypeError, "cannot set a structure which has no " "well-defined ownership transfer rules"); gi_base_info_unref (info); goto out; } value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_NOTHING); if (PyErr_Occurred ()) { gi_base_info_unref (info); goto out; } offset = gi_field_info_get_offset ((GIFieldInfo *)self->info); size = gi_struct_info_get_size ((GIStructInfo *)info); g_assert (size > 0); memmove ((char *)pointer + offset, value.v_pointer, size); gi_base_info_unref (info); retval = Py_None; goto out; } else { /* Fallback. */ } gi_base_info_unref (info); } else if (gi_type_info_is_pointer (field_type_info) && (gi_type_info_get_tag (field_type_info) == GI_TYPE_TAG_VOID || gi_type_info_get_tag (field_type_info) == GI_TYPE_TAG_UTF8)) { int offset; value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_NOTHING); if (PyErr_Occurred ()) { goto out; } offset = gi_field_info_get_offset ((GIFieldInfo *)self->info); G_STRUCT_MEMBER (gpointer, pointer, offset) = (gpointer)value.v_pointer; retval = Py_None; goto out; } value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_EVERYTHING); if (PyErr_Occurred ()) { goto out; } if (!gi_field_info_set_field ((GIFieldInfo *)self->info, pointer, &value)) { _pygi_argument_release (&value, field_type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); PyErr_SetString (PyExc_RuntimeError, "unable to set value for field"); goto out; } retval = Py_None; out: gi_base_info_unref ((GIBaseInfo *)field_type_info); Py_XINCREF (retval); return retval; } static PyObject * _wrap_gi_field_info_get_flags (PyGIBaseInfo *self) { return pygi_guint_to_py ( gi_field_info_get_flags (GI_FIELD_INFO (self->info))); } static PyObject * _wrap_gi_field_info_get_size (PyGIBaseInfo *self) { return pygi_gint_to_py ( gi_field_info_get_size (GI_FIELD_INFO (self->info))); } static PyObject * _wrap_gi_field_info_get_offset (PyGIBaseInfo *self) { return pygi_gint_to_py ( gi_field_info_get_offset (GI_FIELD_INFO (self->info))); } static PyObject * _wrap_gi_field_info_get_type_info (PyGIBaseInfo *self) { return _get_child_info (self, (GetChildInfoCallback)gi_field_info_get_type_info); } static PyMethodDef _PyGIFieldInfo_methods[] = { { "get_value", (PyCFunction)_wrap_gi_field_info_get_value, METH_VARARGS }, { "set_value", (PyCFunction)_wrap_gi_field_info_set_value, METH_VARARGS }, { "get_flags", (PyCFunction)_wrap_gi_field_info_get_flags, METH_VARARGS }, { "get_size", (PyCFunction)_wrap_gi_field_info_get_size, METH_VARARGS }, { "get_offset", (PyCFunction)_wrap_gi_field_info_get_offset, METH_VARARGS }, { "get_type_info", (PyCFunction)_wrap_gi_field_info_get_type_info, METH_VARARGS }, { NULL, NULL, 0 }, }; /* GIUnresolvedInfo */ PYGI_DEFINE_TYPE ("gi.UnresolvedInfo", PyGIUnresolvedInfo_Type, PyGIBaseInfo); static PyMethodDef _PyGIUnresolvedInfo_methods[] = { { NULL, NULL, 0 }, }; /* GIVFuncInfo */ PYGI_DEFINE_TYPE ("gi.VFuncInfo", PyGIVFuncInfo_Type, PyGICallableInfo); static PyObject * _wrap_gi_vfunc_info_get_flags (PyGIBaseInfo *self) { return pygi_guint_to_py ( gi_vfunc_info_get_flags ((GIVFuncInfo *)self->info)); } static PyObject * _wrap_gi_vfunc_info_get_offset (PyGIBaseInfo *self) { return pygi_gint_to_py ( gi_vfunc_info_get_offset ((GIVFuncInfo *)self->info)); } static PyObject * _wrap_gi_vfunc_info_get_signal (PyGIBaseInfo *self) { return _get_child_info (self, (GetChildInfoCallback)gi_vfunc_info_get_signal); } static PyObject * _wrap_gi_vfunc_info_get_invoker (PyGIBaseInfo *self) { return _get_child_info (self, (GetChildInfoCallback)gi_vfunc_info_get_invoker); } static PyMethodDef _PyGIVFuncInfo_methods[] = { { "get_flags", (PyCFunction)_wrap_gi_vfunc_info_get_flags, METH_NOARGS }, { "get_offset", (PyCFunction)_wrap_gi_vfunc_info_get_offset, METH_NOARGS }, { "get_signal", (PyCFunction)_wrap_gi_vfunc_info_get_signal, METH_NOARGS }, { "get_invoker", (PyCFunction)_wrap_gi_vfunc_info_get_invoker, METH_NOARGS }, { NULL, NULL, 0 }, }; /* GIUnionInfo */ PYGI_DEFINE_TYPE ("gi.UnionInfo", PyGIUnionInfo_Type, PyGIBaseInfo); static PyObject * _wrap_gi_union_info_get_fields (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_union_info_get_n_fields, (MakeInfosCallback)gi_union_info_get_field); } static PyObject * _wrap_gi_union_info_get_methods (PyGIBaseInfo *self) { return _make_infos_tuple (self, (GetNInfosCallback)gi_union_info_get_n_methods, (MakeInfosCallback)gi_union_info_get_method); } static PyObject * _wrap_gi_union_info_get_size (PyGIBaseInfo *self) { return pygi_gsize_to_py ( gi_union_info_get_size (GI_UNION_INFO (self->info))); } static PyObject * _wrap_gi_union_info_get_alignment (PyGIBaseInfo *self) { return pygi_gsize_to_py ( gi_union_info_get_alignment (GI_UNION_INFO (self->info))); } static PyMethodDef _PyGIUnionInfo_methods[] = { { "get_fields", (PyCFunction)_wrap_gi_union_info_get_fields, METH_NOARGS }, { "get_methods", (PyCFunction)_wrap_gi_union_info_get_methods, METH_NOARGS }, { "get_size", (PyCFunction)_wrap_gi_union_info_get_size, METH_NOARGS }, { "get_alignment", (PyCFunction)_wrap_gi_union_info_get_alignment, METH_NOARGS }, { NULL, NULL, 0 }, }; /* Private */ gchar * _pygi_gi_base_info_get_fullname (GIBaseInfo *info) { GIBaseInfo *container_info; gchar *fullname; container_info = gi_base_info_get_container (info); if (container_info != NULL) { fullname = g_strdup_printf ( "%s.%s.%s", gi_base_info_get_namespace (container_info), _safe_base_info_get_name (container_info), _safe_base_info_get_name (info)); } else { fullname = g_strdup_printf ("%s.%s", gi_base_info_get_namespace (info), _safe_base_info_get_name (info)); } if (fullname == NULL) { PyErr_NoMemory (); } return fullname; } /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_info_register_types (PyObject *m) { #define _PyGI_REGISTER_TYPE(m, type, cname, base) \ Py_SET_TYPE (&type, &PyType_Type); \ type.tp_flags |= (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); \ type.tp_weaklistoffset = offsetof (PyGIBaseInfo, inst_weakreflist); \ type.tp_methods = _PyGI##cname##_methods; \ type.tp_base = &base; \ if (PyType_Ready (&type) < 0) return -1; \ Py_INCREF ((PyObject *)&type); \ if (PyModule_AddObject (m, #cname, (PyObject *)&type) < 0) { \ Py_DECREF ((PyObject *)&type); \ return -1; \ }; Py_SET_TYPE (&PyGIBaseInfo_Type, &PyType_Type); PyGIBaseInfo_Type.tp_dealloc = (destructor)_base_info_dealloc; PyGIBaseInfo_Type.tp_repr = (reprfunc)_base_info_repr; PyGIBaseInfo_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); PyGIBaseInfo_Type.tp_weaklistoffset = offsetof (PyGIBaseInfo, inst_weakreflist); PyGIBaseInfo_Type.tp_methods = _PyGIBaseInfo_methods; PyGIBaseInfo_Type.tp_richcompare = (richcmpfunc)_base_info_richcompare; PyGIBaseInfo_Type.tp_getset = _base_info_getsets; PyGIBaseInfo_Type.tp_getattro = (getattrofunc)_base_info_getattro; if (PyType_Ready (&PyGIBaseInfo_Type) < 0) return -1; Py_INCREF ((PyObject *)&PyGIBaseInfo_Type); if (PyModule_AddObject (m, "BaseInfo", (PyObject *)&PyGIBaseInfo_Type) < 0) { Py_DECREF ((PyObject *)&PyGIBaseInfo_Type); return -1; } PyGICallableInfo_Type.tp_dealloc = (destructor)_callable_info_dealloc; PyGICallableInfo_Type.tp_flags |= Py_TPFLAGS_HAVE_VECTORCALL; PyGICallableInfo_Type.tp_vectorcall_offset = offsetof (PyGICallableInfo, vectorcall); PyGICallableInfo_Type.tp_call = PyVectorcall_Call; PyGICallableInfo_Type.tp_repr = (reprfunc)_callable_info_repr; PyGICallableInfo_Type.tp_getset = _PyGICallableInfo_getsets; _PyGI_REGISTER_TYPE (m, PyGICallableInfo_Type, CallableInfo, PyGIBaseInfo_Type); PyGIFunctionInfo_Type.tp_flags |= Py_TPFLAGS_METHOD_DESCRIPTOR; PyGIFunctionInfo_Type.tp_descr_get = (descrgetfunc)_function_info_descr_get; _PyGI_REGISTER_TYPE (m, PyGIFunctionInfo_Type, FunctionInfo, PyGICallableInfo_Type); PyGIVFuncInfo_Type.tp_descr_get = (descrgetfunc)_vfunc_info_descr_get; _PyGI_REGISTER_TYPE (m, PyGIVFuncInfo_Type, VFuncInfo, PyGICallableInfo_Type); _PyGI_REGISTER_TYPE (m, PyGISignalInfo_Type, SignalInfo, PyGICallableInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIUnresolvedInfo_Type, UnresolvedInfo, PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGICallbackInfo_Type, CallbackInfo, PyGICallableInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIRegisteredTypeInfo_Type, RegisteredTypeInfo, PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIStructInfo_Type, StructInfo, PyGIRegisteredTypeInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIEnumInfo_Type, EnumInfo, PyGIRegisteredTypeInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIObjectInfo_Type, ObjectInfo, PyGIRegisteredTypeInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIInterfaceInfo_Type, InterfaceInfo, PyGIRegisteredTypeInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIConstantInfo_Type, ConstantInfo, PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIValueInfo_Type, ValueInfo, PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIFieldInfo_Type, FieldInfo, PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIUnionInfo_Type, UnionInfo, PyGIRegisteredTypeInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIErrorDomainInfo_Type, ErrorDomainInfo, PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIPropertyInfo_Type, PropertyInfo, PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIArgInfo_Type, ArgInfo, PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGITypeInfo_Type, TypeInfo, PyGIBaseInfo_Type); #undef _PyGI_REGISTER_TYPE #define _PyGI_ENUM_BEGIN(name) \ { \ const char *__enum_name = #name; \ PyObject *__enum_value = NULL; \ PyObject *__new_enum_cls = NULL; \ PyObject *__enum_instance_dict = PyDict_New (); \ PyObject *__module_name = PyObject_GetAttrString (m, "__name__"); \ PyDict_SetItemString (__enum_instance_dict, "__module__", \ __module_name); \ Py_DECREF (__module_name); #define _PyGI_ENUM_ADD_VALUE(prefix, name) \ __enum_value = pygi_guint_to_py (prefix##_##name); \ if (PyDict_SetItemString (__enum_instance_dict, #name, __enum_value) \ < 0) { \ Py_DECREF (__enum_instance_dict); \ Py_DECREF (__enum_value); \ return -1; \ } \ Py_DECREF (__enum_value); #define _PyGI_ENUM_END \ __new_enum_cls = PyObject_CallFunction ( \ (PyObject *)&PyType_Type, "s(O)O", __enum_name, \ (PyObject *)&PyType_Type, __enum_instance_dict); \ Py_DECREF (__enum_instance_dict); \ PyModule_AddObject (m, __enum_name, __new_enum_cls); /* steals ref */ \ } /* GIDirection */ _PyGI_ENUM_BEGIN (Direction) _PyGI_ENUM_ADD_VALUE (GI_DIRECTION, IN) _PyGI_ENUM_ADD_VALUE (GI_DIRECTION, OUT) _PyGI_ENUM_ADD_VALUE (GI_DIRECTION, INOUT) _PyGI_ENUM_END /* GITransfer */ _PyGI_ENUM_BEGIN (Transfer) _PyGI_ENUM_ADD_VALUE (GI_TRANSFER, NOTHING) _PyGI_ENUM_ADD_VALUE (GI_TRANSFER, CONTAINER) _PyGI_ENUM_ADD_VALUE (GI_TRANSFER, EVERYTHING) _PyGI_ENUM_END /* GIArrayType */ _PyGI_ENUM_BEGIN (ArrayType) _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, C) _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, ARRAY) _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, PTR_ARRAY) _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, BYTE_ARRAY) _PyGI_ENUM_END /* GIScopeType */ _PyGI_ENUM_BEGIN (ScopeType) _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, INVALID) _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, CALL) _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, ASYNC) _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, NOTIFIED) _PyGI_ENUM_END /* GIVFuncInfoFlags */ _PyGI_ENUM_BEGIN (VFuncInfoFlags) _PyGI_ENUM_ADD_VALUE (GI_VFUNC_MUST, CHAIN_UP) _PyGI_ENUM_ADD_VALUE (GI_VFUNC_MUST, OVERRIDE) _PyGI_ENUM_ADD_VALUE (GI_VFUNC_MUST, NOT_OVERRIDE) _PyGI_ENUM_END /* GIFieldInfoFlags */ _PyGI_ENUM_BEGIN (FieldInfoFlags) _PyGI_ENUM_ADD_VALUE (GI_FIELD, IS_READABLE) _PyGI_ENUM_ADD_VALUE (GI_FIELD, IS_WRITABLE) _PyGI_ENUM_END /* GIFunctionInfoFlags */ _PyGI_ENUM_BEGIN (FunctionInfoFlags) _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_METHOD) _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_CONSTRUCTOR) _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_GETTER) _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_SETTER) _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, WRAPS_VFUNC) _PyGI_ENUM_END /* GITypeTag */ _PyGI_ENUM_BEGIN (TypeTag) /* Basic types */ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, VOID) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, BOOLEAN) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT8) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT8) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT16) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT16) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT32) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT32) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT64) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT64) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, FLOAT) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, DOUBLE) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GTYPE) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UTF8) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, FILENAME) /* Non-basic types; compare with G_TYPE_TAG_IS_BASIC */ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, ARRAY) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INTERFACE) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GLIST) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GSLIST) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GHASH) _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, ERROR) /* Another basic type */ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UNICHAR) _PyGI_ENUM_END #undef _PyGI_ENUM_BEGIN #undef _PyGI_ENUM_ADD_VALUE #undef _PyGI_ENUM_END return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-info.h0000664000000000000000000000523515074673150015024 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2005-2009 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_INFO_H__ #define __PYGI_INFO_H__ #include #include #include "pygi-cache.h" G_BEGIN_DECLS typedef struct { PyObject_HEAD GIBaseInfo *info; PyObject *inst_weakreflist; } PyGIBaseInfo; typedef struct { PyGIBaseInfo base; PyGIFunctionCache *cache; vectorcallfunc vectorcall; } PyGICallableInfo; PyGIFunctionCache *pygi_callable_info_get_cache (PyGICallableInfo *self); gboolean pygi_gi_struct_info_is_simple (GIStructInfo *struct_info); /* Private */ extern PyTypeObject PyGIBaseInfo_Type; extern PyTypeObject PyGICallableInfo_Type; extern PyTypeObject PyGICallbackInfo_Type; extern PyTypeObject PyGIFunctionInfo_Type; extern PyTypeObject PyGIRegisteredTypeInfo_Type; extern PyTypeObject PyGIStructInfo_Type; extern PyTypeObject PyGIEnumInfo_Type; extern PyTypeObject PyGIObjectInfo_Type; extern PyTypeObject PyGIInterfaceInfo_Type; extern PyTypeObject PyGIConstantInfo_Type; extern PyTypeObject PyGIValueInfo_Type; extern PyTypeObject PyGIFieldInfo_Type; extern PyTypeObject PyGIUnresolvedInfo_Type; extern PyTypeObject PyGIVFuncInfo_Type; extern PyTypeObject PyGIUnionInfo_Type; extern PyTypeObject PyGIBoxedInfo_Type; extern PyTypeObject PyGIFundamental_Type; extern PyTypeObject PyGIErrorDomainInfo_Type; extern PyTypeObject PyGISignalInfo_Type; extern PyTypeObject PyGIPropertyInfo_Type; extern PyTypeObject PyGIArgInfo_Type; extern PyTypeObject PyGITypeInfo_Type; PyObject *_pygi_info_new (GIBaseInfo *info); GIBaseInfo *_pygi_object_get_gi_info (PyObject *object, PyTypeObject *type); gchar *_pygi_gi_base_info_get_fullname (GIBaseInfo *info); gsize _pygi_g_type_tag_size (GITypeTag type_tag); gsize _pygi_gi_type_info_size (GITypeInfo *type_info); int pygi_info_register_types (PyObject *m); PyObject *_pygi_is_python_keyword (const gchar *name); G_END_DECLS #endif /* __PYGI_INFO_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-invoke-state-struct.h0000664000000000000000000000363115074673150020022 0ustar00rootroot#ifndef __PYGI_INVOKE_STATE_STRUCT_H__ #define __PYGI_INVOKE_STATE_STRUCT_H__ #include #include G_BEGIN_DECLS typedef struct _PyGIInvokeArgState { /* Holds memory for the C value of arguments marshaled "to" or "from" Python. */ GIArgument arg_value; /* Holds pointers to values in arg_values or a caller allocated chunk of * memory via arg_pointer.v_pointer. */ GIArgument arg_pointer; /* Holds from_py marshaler cleanup data. */ gpointer arg_cleanup_data; /* Holds to_py marshaler cleanup data. */ gpointer to_py_arg_cleanup_data; } PyGIInvokeArgState; typedef struct _PyGIInvokeState { PyObject *py_in_args; gssize n_py_in_args; /* Number of arguments the ffi wrapped C function takes. Used as the exact * count for argument related arrays held in this struct. */ gssize n_args; /* List of arguments passed to ffi. Elements can point directly to values held in * arg_values for "in/from Python" or indirectly via arg_pointers for * "out/inout/to Python". In the latter case, the args[x].arg_pointer.v_pointer * member points to memory for the value storage. */ GIArgument **ffi_args; /* Array of size n_args containing per argument state */ PyGIInvokeArgState *args; /* Memory to receive the result of the C ffi function call. */ GIArgument return_arg; gpointer to_py_return_arg_cleanup_data; /* A GError exception which is indirectly bound into the last position of * the "args" array if the callable caches "throws" member is set. */ GError *error; gboolean failed; /* An awaitable to return for an async function that was called with * default arguments. */ PyObject *py_async; gpointer user_data; /* Function pointer to call with ffi. */ gpointer function_ptr; } PyGIInvokeState; G_END_DECLS #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-invoke.c0000664000000000000000000006675115074673150015371 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2005-2009 Johan Dahlin * Copyright (C) 2011 John (J5) Palimier * * pygi-invoke.c: main invocation function * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-async.h" #include "pygi-boxed.h" #include "pygi-error.h" #include "pygi-foreign.h" #include "pygi-invoke.h" #include "pygi-marshal-cleanup.h" #include "pygi-resulttuple.h" extern PyObject *_PyGIDefaultArgPlaceholder; static PyGIArgCache * next_python_argument (PyGICallableCache *cache, Py_ssize_t i, Py_ssize_t *skipped_args) { PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i + *skipped_args); /* Skip over automatically filled in arguments (e.g. GDestroyNotify) */ while (arg_cache->py_arg_index < 0 || i != arg_cache->py_arg_index) { *skipped_args += 1; g_assert (i + *skipped_args < (Py_ssize_t)cache->args_cache->len); arg_cache = g_ptr_array_index (cache->args_cache, i + *skipped_args); } return arg_cache; } /** * _py_args_combine_and_check_length: * @cache: PyGICallableCache * @py_args: an array of arguments as in the vectorcall protocol * @py_nargsf: the argument count plus flags * @py_kwnames: a tuple of keyword names * * Returns: New value reference to the combined py_args and py_kwargs. */ static PyObject * _py_args_combine_and_check_length (PyGICallableCache *cache, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames) { PyObject *combined_py_args = NULL; Py_ssize_t n_py_args, n_py_kwargs, i, skipped_args = 0; gssize n_expected_args = cache->n_py_args; n_py_args = PyVectorcall_NARGS (py_nargsf); if (py_kwnames == NULL) n_py_kwargs = 0; else n_py_kwargs = PyTuple_GET_SIZE (py_kwnames); if (cache->user_data_varargs_arg == NULL && n_expected_args < n_py_args) { char *full_name = pygi_callable_cache_get_full_name (cache); PyErr_Format (PyExc_TypeError, "%.200s() takes exactly %zd %sargument%s (%zd given)", full_name, n_expected_args, n_py_kwargs > 0 ? "non-keyword " : "", n_expected_args == 1 ? "" : "s", n_py_args); g_free (full_name); return NULL; } if (cache->user_data_varargs_arg != NULL && n_py_kwargs > 0 && n_expected_args < n_py_args) { char *full_name = pygi_callable_cache_get_full_name (cache); PyErr_Format (PyExc_TypeError, "%.200s() cannot use variable user data arguments with " "keyword arguments", full_name); g_free (full_name); return NULL; } /* will hold arguments from both py_args and py_kwargs * when they are combined into a single tuple */ combined_py_args = PyTuple_New (n_expected_args); /* Add the positional arguments */ for (i = 0; i < n_py_args && i < n_expected_args; i++) { PyGIArgCache *arg_cache = next_python_argument (cache, i, &skipped_args); if (arg_cache == cache->user_data_varargs_arg) { PyObject *user_data = PyTuple_New (n_py_args - i); Py_ssize_t j; for (j = i; j < n_py_args; j++) { Py_INCREF (py_args[j]); PyTuple_SET_ITEM (user_data, j - i, py_args[j]); } PyTuple_SET_ITEM (combined_py_args, i, user_data); } else { Py_INCREF (py_args[i]); PyTuple_SET_ITEM (combined_py_args, i, py_args[i]); } } /* Process keyword arguments */ for (i = 0; i < n_py_kwargs; i++) { PyObject *py_kwname, *arg_item; const char *kwname; PyGIArgCache *arg_cache; gboolean is_varargs_user_data; py_kwname = PyTuple_GET_ITEM (py_kwnames, i); kwname = PyUnicode_AsUTF8AndSize (py_kwname, NULL); if (kwname == NULL) { Py_DECREF (combined_py_args); return NULL; } arg_cache = g_hash_table_lookup (cache->arg_name_hash, kwname); if (!arg_cache) { char *full_name = pygi_callable_cache_get_full_name (cache); PyErr_Format ( PyExc_TypeError, "%.200s() got an unexpected keyword argument '%.400s'", full_name, kwname); g_free (full_name); Py_DECREF (combined_py_args); return NULL; } is_varargs_user_data = arg_cache == cache->user_data_varargs_arg; /* Have we already seen this argument? */ arg_item = PyTuple_GET_ITEM (combined_py_args, arg_cache->py_arg_index); if (arg_item != NULL) { char *full_name = pygi_callable_cache_get_full_name (cache); PyErr_Format ( PyExc_TypeError, "%.200s() got multiple values for keyword argument '%.200s'", full_name, kwname); g_free (full_name); Py_DECREF (combined_py_args); return NULL; } arg_item = py_args[n_py_args + i]; if (is_varargs_user_data) { /* Special case where user_data is passed as a keyword * argument (user_data=foo) Wrap the value in a tuple to * represent variable args for marshaling later on. */ PyObject *user_data = Py_BuildValue ("(O)", arg_item, NULL); PyTuple_SET_ITEM (combined_py_args, arg_cache->py_arg_index, user_data); } else { Py_INCREF (arg_item); PyTuple_SET_ITEM (combined_py_args, arg_cache->py_arg_index, arg_item); } } /* Fill in defaults and check for missing arguments */ for (i = n_py_args; i < n_expected_args; i++) { PyObject *arg_item = PyTuple_GET_ITEM (combined_py_args, i); PyGIArgCache *arg_cache; if (arg_item != NULL) continue; arg_cache = next_python_argument (cache, i, &skipped_args); if (arg_cache == cache->user_data_varargs_arg) { /* For varargs user_data, pass an empty tuple when nothing * is given. */ PyTuple_SET_ITEM (combined_py_args, i, PyTuple_New (0)); } else if (arg_cache->allow_none) { /* If the argument supports a default, use a place holder in the * argument tuple, this will be checked later during marshaling. */ Py_INCREF (_PyGIDefaultArgPlaceholder); PyTuple_SET_ITEM (combined_py_args, i, _PyGIDefaultArgPlaceholder); } else { char *full_name = pygi_callable_cache_get_full_name (cache); PyErr_Format ( PyExc_TypeError, "%.200s() takes exactly %zd %sargument%s (%zd given)", full_name, n_expected_args, n_py_kwargs > 0 ? "non-keyword " : "", n_expected_args == 1 ? "" : "s", n_py_args); g_free (full_name); Py_DECREF (combined_py_args); return NULL; } } return combined_py_args; } /* To reduce calls to g_slice_*() we (1) allocate all the memory depended on * the argument count in one go and (2) keep one version per argument count * around for faster reuse. */ #define PyGI_INVOKE_ARG_STATE_SIZE(n) \ (n * (sizeof (PyGIInvokeArgState) + sizeof (GIArgument *))) #define PyGI_INVOKE_ARG_STATE_N_MAX 10 static gpointer free_arg_state[PyGI_INVOKE_ARG_STATE_N_MAX]; /** * _pygi_invoke_arg_state_init: * Sets PyGIInvokeState.args and PyGIInvokeState.ffi_args. * On error returns FALSE and sets an exception. */ gboolean _pygi_invoke_arg_state_init (PyGIInvokeState *state) { gpointer mem; if (state->n_args < PyGI_INVOKE_ARG_STATE_N_MAX && (mem = free_arg_state[state->n_args]) != NULL) { free_arg_state[state->n_args] = NULL; memset (mem, 0, PyGI_INVOKE_ARG_STATE_SIZE (state->n_args)); } else { mem = g_slice_alloc0 (PyGI_INVOKE_ARG_STATE_SIZE (state->n_args)); } if (mem == NULL && state->n_args != 0) { PyErr_NoMemory (); return FALSE; } if (mem != NULL) { state->args = mem; state->ffi_args = (gpointer)((gchar *)mem + state->n_args * sizeof (PyGIInvokeArgState)); } return TRUE; } /** * _pygi_invoke_arg_state_free: * Frees PyGIInvokeState.args and PyGIInvokeState.ffi_args */ void _pygi_invoke_arg_state_free (PyGIInvokeState *state) { if (state->n_args < PyGI_INVOKE_ARG_STATE_N_MAX && free_arg_state[state->n_args] == NULL) { free_arg_state[state->n_args] = state->args; return; } g_slice_free1 (PyGI_INVOKE_ARG_STATE_SIZE (state->n_args), state->args); } static gboolean _invoke_state_init_from_cache (PyGIInvokeState *state, PyGIFunctionCache *function_cache, PyObject *const *py_args, size_t py_nargsf, PyObject *kwnames) { PyGICallableCache *cache = (PyGICallableCache *)function_cache; state->n_args = _pygi_callable_cache_args_len (cache); if (cache->throws) { state->n_args++; } /* Copy the function pointer to the state for the normal case. For vfuncs, * this has already been filled out based on the implementor's GType. */ if (state->function_ptr == NULL) state->function_ptr = function_cache->invoker.native_address; state->py_in_args = _py_args_combine_and_check_length (cache, py_args, py_nargsf, kwnames); if (state->py_in_args == NULL) { return FALSE; } state->n_py_in_args = PyTuple_Size (state->py_in_args); if (!_pygi_invoke_arg_state_init (state)) { return FALSE; } state->error = NULL; if (cache->throws) { gssize error_index = state->n_args - 1; /* The ffi argument for GError needs to be a triple pointer. */ state->args[error_index].arg_pointer.v_pointer = &state->error; state->ffi_args[error_index] = &(state->args[error_index].arg_pointer); } return TRUE; } static void _invoke_state_clear (PyGIInvokeState *state, PyGIFunctionCache *function_cache) { _pygi_invoke_arg_state_free (state); Py_XDECREF (state->py_in_args); Py_XDECREF (state->py_async); } static gboolean _caller_alloc (PyGIArgCache *arg_cache, GIArgument *arg) { if (arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; arg->v_pointer = NULL; if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) { arg->v_pointer = pygi_boxed_alloc ( GI_BASE_INFO (iface_cache->interface_info), NULL); } else if (iface_cache->g_type == G_TYPE_VALUE) { arg->v_pointer = g_slice_new0 (GValue); } else if (iface_cache->is_foreign) { PyObject *foreign_struct = pygi_struct_foreign_convert_from_g_argument ( iface_cache->interface_info, GI_TRANSFER_NOTHING, NULL); pygi_struct_foreign_convert_to_g_argument ( foreign_struct, iface_cache->interface_info, GI_TRANSFER_EVERYTHING, arg); } else { gssize size = gi_struct_info_get_size ( (GIStructInfo *)iface_cache->interface_info); arg->v_pointer = g_malloc0 (size); } } else if (arg_cache->type_tag == GI_TYPE_TAG_ARRAY) { PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache; arg->v_pointer = g_array_new (TRUE, TRUE, (guint)array_cache->item_size); } else { return FALSE; } if (arg->v_pointer == NULL) return FALSE; return TRUE; } /* pygi_invoke_marshal_in_args: * * Fills out the state struct argument lists. arg_values will always hold * actual values marshaled either to or from Python and C. arg_pointers will * hold pointers (via v_pointer) to auxilary value storage. This will normally * point to values stored in arg_values. In the case of caller allocated * out args, arg_pointers[x].v_pointer will point to newly allocated memory. * arg_pointers inserts a level of pointer indirection between arg_values * and the argument list ffi receives when dealing with non-caller allocated * out arguments. * * For example: * [[ * void callee (int *i, int j) { *i = 50 - j; } * void caller () { * int i = 0; * callee (&i, 8); * } * * args[0] == &arg_pointers[0]; * arg_pointers[0].v_pointer == &arg_values[0]; * arg_values[0].v_int == 42; * * args[1] == &arg_values[1]; * arg_values[1].v_int == 8; * ]] * */ static gboolean _invoke_marshal_in_args (PyGIInvokeState *state, PyGIFunctionCache *function_cache) { PyGICallableCache *cache = (PyGICallableCache *)function_cache; gssize i; if (state->n_py_in_args > cache->n_py_args) { char *full_name = pygi_callable_cache_get_full_name (cache); PyErr_Format (PyExc_TypeError, "%s() takes exactly %zd argument(s) (%zd given)", full_name, cache->n_py_args, state->n_py_in_args); g_free (full_name); return FALSE; } if (function_cache->async_finish && function_cache->async_callback && function_cache->async_callback->py_arg_index < state->n_py_in_args && PyTuple_GET_ITEM (state->py_in_args, function_cache->async_callback->py_arg_index) == _PyGIDefaultArgPlaceholder) { /* We are dealing with an async call that returns an awaitable */ PyObject *cancellable = NULL; /* Try to resolve any passed GCancellable. */ if (function_cache->async_cancellable && function_cache->async_cancellable->py_arg_index < state->n_py_in_args) cancellable = PyTuple_GET_ITEM ( state->py_in_args, function_cache->async_cancellable->py_arg_index); if (cancellable == _PyGIDefaultArgPlaceholder) cancellable = NULL; state->py_async = pygi_async_new (function_cache->async_finish, cancellable); } for (i = 0; (gsize)i < _pygi_callable_cache_args_len (cache); i++) { GIArgument *c_arg = &state->args[i].arg_value; PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i); PyObject *py_arg = NULL; gboolean marshal = TRUE; switch (arg_cache->direction) { case PYGI_DIRECTION_FROM_PYTHON: /* The ffi argument points directly at memory in arg_values. */ state->ffi_args[i] = c_arg; if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CLOSURE) { state->ffi_args[i]->v_pointer = state->user_data; continue; } else if (arg_cache->meta_type != PYGI_META_ARG_TYPE_PARENT) continue; if (arg_cache->py_arg_index >= state->n_py_in_args) { char *full_name = pygi_callable_cache_get_full_name (cache); PyErr_Format (PyExc_TypeError, "%s() takes exactly %zd argument(s) (%zd given)", full_name, cache->n_py_args, state->n_py_in_args); g_free (full_name); /* clean up all of the args we have already marshalled, * since invoke will not be called */ pygi_marshal_cleanup_args_from_py_parameter_fail (state, cache, i); return FALSE; } py_arg = PyTuple_GET_ITEM (state->py_in_args, arg_cache->py_arg_index); break; case PYGI_DIRECTION_BIDIRECTIONAL: if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD) { if (arg_cache->py_arg_index >= state->n_py_in_args) { char *full_name = pygi_callable_cache_get_full_name (cache); PyErr_Format ( PyExc_TypeError, "%s() takes exactly %zd argument(s) (%zd given)", full_name, cache->n_py_args, state->n_py_in_args); g_free (full_name); pygi_marshal_cleanup_args_from_py_parameter_fail ( state, cache, i); return FALSE; } py_arg = PyTuple_GET_ITEM (state->py_in_args, arg_cache->py_arg_index); } /* Fall through */ case PYGI_DIRECTION_TO_PYTHON: /* arg_pointers always stores a pointer to the data to be marshaled "to python" * even in cases where arg_pointers is not being used as indirection between * ffi and arg_values. This gives a guarantee that out argument marshaling * (_invoke_marshal_out_args) can always rely on arg_pointers pointing to * the correct chunk of memory to marshal. */ state->args[i].arg_pointer.v_pointer = c_arg; if (arg_cache->is_caller_allocates) { /* In the case of caller allocated out args, we don't use * an extra level of indirection and state->args will point * directly at the data to be marshaled. However, as noted * above, arg_pointers will also point to this caller allocated * chunk of memory used by out argument marshaling. */ state->ffi_args[i] = c_arg; if (!_caller_alloc (arg_cache, c_arg)) { char *full_name = pygi_callable_cache_get_full_name (cache); PyErr_Format (PyExc_TypeError, "Could not caller allocate argument %zd of " "callable %s", i, full_name); g_free (full_name); pygi_marshal_cleanup_args_from_py_parameter_fail ( state, cache, i); return FALSE; } } else { /* Non-caller allocated out args will use arg_pointers as an * extra level of indirection */ state->ffi_args[i] = &state->args[i].arg_pointer; } break; default: g_assert_not_reached (); break; } if (py_arg == _PyGIDefaultArgPlaceholder) { /* If this is the cancellable, then we may override it later if we * detect an async call. */ marshal = FALSE; if (state->py_async && arg_cache->async_context == PYGI_ASYNC_CONTEXT_CANCELLABLE) { marshal = TRUE; py_arg = ((PyGIAsync *)state->py_async)->cancellable; } else if (state->py_async && arg_cache->async_context == PYGI_ASYNC_CONTEXT_CALLBACK) { marshal = TRUE; } else { c_arg->v_pointer = NULL; } } if (marshal && arg_cache->from_py_marshaller != NULL && arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD) { gboolean success; gpointer cleanup_data = NULL; if (!arg_cache->allow_none && Py_IsNone (py_arg)) { PyErr_Format (PyExc_TypeError, "Argument %zd does not allow None as a value", i); pygi_marshal_cleanup_args_from_py_parameter_fail (state, cache, i); return FALSE; } success = arg_cache->from_py_marshaller ( state, cache, arg_cache, py_arg, c_arg, &cleanup_data); state->args[i].arg_cleanup_data = cleanup_data; if (!success) { pygi_marshal_cleanup_args_from_py_parameter_fail (state, cache, i); return FALSE; } } } return TRUE; } static PyObject * _invoke_marshal_out_args (PyGIInvokeState *state, PyGIFunctionCache *function_cache) { PyGICallableCache *cache = (PyGICallableCache *)function_cache; PyObject *py_out = NULL; PyObject *py_return = NULL; gssize n_out_args = cache->n_to_py_args - cache->n_to_py_child_args; if (cache->return_cache) { if (!cache->return_cache->is_skipped) { gpointer cleanup_data = NULL; py_return = cache->return_cache->to_py_marshaller ( state, cache, cache->return_cache, &state->return_arg, &cleanup_data); state->to_py_return_arg_cleanup_data = cleanup_data; if (py_return == NULL) { pygi_marshal_cleanup_args_return_fail (state, cache); return NULL; } } else { if (cache->return_cache->transfer == GI_TRANSFER_EVERYTHING) { PyGIMarshalToPyCleanupFunc to_py_cleanup = cache->return_cache->to_py_cleanup; if (to_py_cleanup != NULL) to_py_cleanup (state, cache->return_cache, NULL, &state->return_arg, FALSE); } } } /* Return the async future if we have one. */ if (state->py_async) { /* We must have no return value */ g_assert (n_out_args == 0); g_assert (cache->return_cache->is_skipped || cache->return_cache->type_tag == GI_TYPE_TAG_VOID); Py_DECREF (py_return); return Py_NewRef (state->py_async); } if (n_out_args == 0) { if (cache->return_cache->is_skipped && state->error == NULL) { /* we skip the return value and have no (out) arguments to return, * so py_return should be NULL. But we must not return NULL, * otherwise Python will expect an exception. */ g_assert (py_return == NULL); py_return = Py_NewRef (Py_None); } py_out = py_return; } else if (!cache->has_return && n_out_args == 1) { /* if we get here there is one out arg an no return */ PyGIArgCache *arg_cache = (PyGIArgCache *)cache->to_py_args->data; gpointer cleanup_data = NULL; py_out = arg_cache->to_py_marshaller ( state, cache, arg_cache, state->args[arg_cache->c_arg_index].arg_pointer.v_pointer, &cleanup_data); state->args[arg_cache->c_arg_index].to_py_arg_cleanup_data = cleanup_data; if (py_out == NULL) { pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, 0); return NULL; } } else { /* return a tuple */ gssize py_arg_index = 0; GSList *cache_item = cache->to_py_args; gssize tuple_len = cache->has_return + n_out_args; py_out = pygi_resulttuple_new (cache->resulttuple_type, tuple_len); if (py_out == NULL) { pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, py_arg_index); return NULL; } if (cache->has_return) { PyTuple_SET_ITEM (py_out, py_arg_index, py_return); py_arg_index++; } for (; py_arg_index < tuple_len; py_arg_index++) { PyGIArgCache *arg_cache = (PyGIArgCache *)cache_item->data; gpointer cleanup_data = NULL; PyObject *py_obj = arg_cache->to_py_marshaller ( state, cache, arg_cache, state->args[arg_cache->c_arg_index].arg_pointer.v_pointer, &cleanup_data); state->args[arg_cache->c_arg_index].to_py_arg_cleanup_data = cleanup_data; if (py_obj == NULL) { if (cache->has_return) py_arg_index--; pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, py_arg_index); Py_DECREF (py_out); return NULL; } PyTuple_SET_ITEM (py_out, py_arg_index, py_obj); cache_item = cache_item->next; } } return py_out; } PyObject * pygi_invoke_c_callable (PyGIFunctionCache *function_cache, PyGIInvokeState *state, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames) { PyGICallableCache *cache = (PyGICallableCache *)function_cache; GIFFIReturnValue ffi_return_value = { 0 }; PyObject *ret = NULL; if (Py_EnterRecursiveCall (" while calling a GICallable")) return NULL; ; if (!_invoke_state_init_from_cache (state, function_cache, py_args, py_nargsf, py_kwnames)) goto err; if (!_invoke_marshal_in_args (state, function_cache)) goto err; Py_BEGIN_ALLOW_THREADS; ffi_call (&function_cache->invoker.cif, state->function_ptr, (void *)&ffi_return_value, (void **)state->ffi_args); Py_END_ALLOW_THREADS; /* If the callable throws, the address of state->error will be bound into * the state->args as the last value. When the callee sets an error using * the state->args passed, it will have the side effect of setting * state->error allowing for easy checking here. */ if (state->error != NULL) { if (pygi_error_check (&state->error)) { /* even though we errored out, the call itself was successful, so we assume the call processed all of the parameters */ pygi_marshal_cleanup_args_from_py_marshal_success (state, cache); goto err; } } if (cache->return_cache) { gi_type_info_extract_ffi_return_value (cache->return_cache->type_info, &ffi_return_value, &state->return_arg); } ret = _invoke_marshal_out_args (state, function_cache); pygi_marshal_cleanup_args_from_py_marshal_success (state, cache); if (ret != NULL) pygi_marshal_cleanup_args_to_py_marshal_success (state, cache); err: _invoke_state_clear (state, function_cache); Py_LeaveRecursiveCall (); return ret; } PyObject * pygi_callable_info_invoke (PyGICallableInfo *self, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames) { PyGIFunctionCache *cache = pygi_callable_info_get_cache (self); if (cache == NULL) return NULL; return pygi_function_cache_invoke (cache, py_args, py_nargsf, py_kwnames); } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-invoke.h0000664000000000000000000000315715074673150015365 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2005-2009 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_INVOKE_H__ #define __PYGI_INVOKE_H__ #include #include #include "pygi-info.h" #include "pygi-invoke-state-struct.h" G_BEGIN_DECLS PyObject *pygi_invoke_c_callable (PyGIFunctionCache *function_cache, PyGIInvokeState *state, PyObject *const *py_args, size_t py_nargsf, PyObject *py_kwnames); PyObject *pygi_callable_info_invoke (PyGICallableInfo *self, PyObject *const *py_args, size_t py_nargsf, PyObject *kwnames); gboolean _pygi_invoke_arg_state_init (PyGIInvokeState *state); void _pygi_invoke_arg_state_free (PyGIInvokeState *state); G_END_DECLS #endif /* __PYGI_INVOKE_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-list.c0000664000000000000000000003461215074673150015040 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-list.h" #include "pygi-argument.h" #include "pygi-util.h" typedef PyGISequenceCache PyGIArgGList; /* * GList and GSList from Python */ static gboolean _pygi_marshal_from_py_glist (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { PyGIMarshalFromPyFunc from_py_marshaller; int i; Py_ssize_t length; GList *list_ = NULL; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; if (Py_IsNone (py_arg)) { arg->v_pointer = NULL; return TRUE; } if (!PySequence_Check (py_arg)) { PyErr_Format (PyExc_TypeError, "Must be sequence, not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } length = PySequence_Length (py_arg); if (length < 0) return FALSE; from_py_marshaller = sequence_cache->item_cache->from_py_marshaller; for (i = 0; i < length; i++) { GIArgument item = { 0 }; gpointer item_cleanup_data = NULL; PyObject *py_item = PySequence_GetItem (py_arg, i); if (py_item == NULL) goto err; if (!from_py_marshaller (state, callable_cache, sequence_cache->item_cache, py_item, &item, &item_cleanup_data)) goto err; Py_DECREF (py_item); list_ = g_list_prepend ( list_, _pygi_arg_to_hash_pointer ( &item, sequence_cache->item_cache->type_info)); continue; err: /* FIXME: clean up list if (sequence_cache->item_cache->from_py_cleanup != NULL) { PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup; } */ Py_XDECREF (py_item); g_list_free (list_); _PyGI_ERROR_PREFIX ("Item %i: ", i); return FALSE; } arg->v_pointer = g_list_reverse (list_); if (arg_cache->transfer == GI_TRANSFER_NOTHING) { /* Free everything in cleanup. */ *cleanup_data = arg->v_pointer; } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) { /* Make a shallow copy so we can free the elements later in cleanup * because it is possible invoke will free the list before our cleanup. */ *cleanup_data = g_list_copy (arg->v_pointer); } else { /* GI_TRANSFER_EVERYTHING */ /* No cleanup, everything is given to the callee. */ *cleanup_data = NULL; } return TRUE; } static gboolean _pygi_marshal_from_py_gslist (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { PyGIMarshalFromPyFunc from_py_marshaller; int i; Py_ssize_t length; GSList *list_ = NULL; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; if (Py_IsNone (py_arg)) { arg->v_pointer = NULL; return TRUE; } if (!PySequence_Check (py_arg)) { PyErr_Format (PyExc_TypeError, "Must be sequence, not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } length = PySequence_Length (py_arg); if (length < 0) return FALSE; from_py_marshaller = sequence_cache->item_cache->from_py_marshaller; for (i = 0; i < length; i++) { GIArgument item = { 0 }; gpointer item_cleanup_data = NULL; PyObject *py_item = PySequence_GetItem (py_arg, i); if (py_item == NULL) goto err; if (!from_py_marshaller (state, callable_cache, sequence_cache->item_cache, py_item, &item, &item_cleanup_data)) goto err; Py_DECREF (py_item); list_ = g_slist_prepend ( list_, _pygi_arg_to_hash_pointer ( &item, sequence_cache->item_cache->type_info)); continue; err: /* FIXME: Clean up list if (sequence_cache->item_cache->from_py_cleanup != NULL) { PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup; } */ Py_XDECREF (py_item); g_slist_free (list_); _PyGI_ERROR_PREFIX ("Item %i: ", i); return FALSE; } arg->v_pointer = g_slist_reverse (list_); if (arg_cache->transfer == GI_TRANSFER_NOTHING) { /* Free everything in cleanup. */ *cleanup_data = arg->v_pointer; } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) { /* Make a shallow copy so we can free the elements later in cleanup * because it is possible invoke will free the list before our cleanup. */ *cleanup_data = g_slist_copy (arg->v_pointer); } else { /* GI_TRANSFER_EVERYTHING */ /* No cleanup, everything is given to the callee. */ *cleanup_data = NULL; } return TRUE; } static void _pygi_marshal_cleanup_from_py_glist (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed) { if (was_processed) { GSList *list_; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; list_ = (GSList *)data; /* clean up items first */ if (sequence_cache->item_cache->from_py_cleanup != NULL) { PyGIMarshalCleanupFunc cleanup_func = sequence_cache->item_cache->from_py_cleanup; GSList *node = list_; gsize i = 0; while (node != NULL) { PyObject *py_item = PySequence_GetItem (py_arg, i); cleanup_func (state, sequence_cache->item_cache, py_item, node->data, TRUE); Py_XDECREF (py_item); node = node->next; i++; } } if (arg_cache->type_tag == GI_TYPE_TAG_GLIST) { g_list_free ((GList *)list_); } else if (arg_cache->type_tag == GI_TYPE_TAG_GSLIST) { g_slist_free (list_); } else { g_assert_not_reached (); } } } /* * GList and GSList to Python */ static PyObject * _pygi_marshal_to_py_glist (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { GList *list_; guint length; guint i; GPtrArray *item_cleanups; PyGIMarshalToPyFunc item_to_py_marshaller; PyGIArgCache *item_arg_cache; PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache; PyObject *py_obj = NULL; list_ = arg->v_pointer; length = g_list_length (list_); py_obj = PyList_New (length); if (py_obj == NULL) return NULL; item_cleanups = g_ptr_array_sized_new (length); *cleanup_data = item_cleanups; item_arg_cache = seq_cache->item_cache; item_to_py_marshaller = item_arg_cache->to_py_marshaller; for (i = 0; list_ != NULL; list_ = g_list_next (list_), i++) { GIArgument item_arg; PyObject *py_item; gpointer item_cleanup_data = NULL; item_arg.v_pointer = list_->data; _pygi_hash_pointer_to_arg (&item_arg, item_arg_cache->type_info); py_item = item_to_py_marshaller (state, callable_cache, item_arg_cache, &item_arg, &item_cleanup_data); g_ptr_array_index (item_cleanups, i) = item_cleanup_data; if (py_item == NULL) { Py_CLEAR (py_obj); _PyGI_ERROR_PREFIX ("Item %u: ", i); g_ptr_array_unref (item_cleanups); return NULL; } PyList_SET_ITEM (py_obj, i, py_item); } return py_obj; } static PyObject * _pygi_marshal_to_py_gslist (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { GSList *list_; guint length; guint i; GPtrArray *item_cleanups; PyGIMarshalToPyFunc item_to_py_marshaller; PyGIArgCache *item_arg_cache; PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache; PyObject *py_obj = NULL; list_ = arg->v_pointer; length = g_slist_length (list_); py_obj = PyList_New (length); if (py_obj == NULL) return NULL; item_cleanups = g_ptr_array_sized_new (length); *cleanup_data = item_cleanups; item_arg_cache = seq_cache->item_cache; item_to_py_marshaller = item_arg_cache->to_py_marshaller; for (i = 0; list_ != NULL; list_ = g_slist_next (list_), i++) { GIArgument item_arg; PyObject *py_item; gpointer item_cleanup_data = NULL; item_arg.v_pointer = list_->data; _pygi_hash_pointer_to_arg (&item_arg, item_arg_cache->type_info); py_item = item_to_py_marshaller (state, callable_cache, item_arg_cache, &item_arg, &item_cleanup_data); g_ptr_array_index (item_cleanups, i) = item_cleanup_data; if (py_item == NULL) { Py_CLEAR (py_obj); _PyGI_ERROR_PREFIX ("Item %u: ", i); g_ptr_array_unref (item_cleanups); return NULL; } PyList_SET_ITEM (py_obj, i, py_item); } return py_obj; } static void _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state, PyGIArgCache *arg_cache, gpointer cleanup_data, gpointer data, gboolean was_processed) { GPtrArray *item_cleanups = (GPtrArray *)cleanup_data; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; GSList *list_ = (GSList *)data; if (sequence_cache->item_cache->to_py_cleanup != NULL) { PyGIMarshalToPyCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup; GSList *node = list_; guint i = 0; while (node != NULL) { cleanup_func (state, sequence_cache->item_cache, g_ptr_array_index (item_cleanups, i), node->data, was_processed); node = node->next; i++; } } if (arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->transfer == GI_TRANSFER_CONTAINER) { if (arg_cache->type_tag == GI_TYPE_TAG_GLIST) { g_list_free ((GList *)list_); } else if (arg_cache->type_tag == GI_TYPE_TAG_GSLIST) { g_slist_free (list_); } else { g_assert_not_reached (); } } g_ptr_array_unref (item_cleanups); } static void _arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache, GITransfer transfer) { arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist; arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist; } static void _arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache, GITransfer transfer) { arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist; arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist; } static void _arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache, GITransfer transfer) { arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist; arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist; } static void _arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache, GITransfer transfer) { arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist; arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist; } /* * GList/GSList Interface */ static gboolean pygi_arg_glist_setup_from_info (PyGIArgCache *arg_cache, GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache) { GITypeTag type_tag = gi_type_info_get_tag (type_info); if (!pygi_arg_sequence_setup ((PyGISequenceCache *)arg_cache, type_info, arg_info, transfer, direction, callable_cache)) return FALSE; switch (type_tag) { case GI_TYPE_TAG_GLIST: { if (direction & PYGI_DIRECTION_FROM_PYTHON) _arg_cache_from_py_glist_setup (arg_cache, transfer); if (direction & PYGI_DIRECTION_TO_PYTHON) _arg_cache_to_py_glist_setup (arg_cache, transfer); break; } case GI_TYPE_TAG_GSLIST: { if (direction & PYGI_DIRECTION_FROM_PYTHON) _arg_cache_from_py_gslist_setup (arg_cache, transfer); if (direction & PYGI_DIRECTION_TO_PYTHON) _arg_cache_to_py_gslist_setup (arg_cache, transfer); break; } default: g_assert_not_reached (); } return TRUE; } PyGIArgCache * pygi_arg_glist_new_from_info (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache) { gboolean res = FALSE; PyGIArgCache *arg_cache = (PyGIArgCache *)g_slice_new0 (PyGIArgGList); if (arg_cache == NULL) return NULL; res = pygi_arg_glist_setup_from_info (arg_cache, type_info, arg_info, transfer, direction, callable_cache); if (res) { return arg_cache; } else { pygi_arg_cache_free (arg_cache); return NULL; } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-list.h0000664000000000000000000000242215074673150015037 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_LIST_H__ #define __PYGI_LIST_H__ #include #include "pygi-cache.h" G_BEGIN_DECLS PyGIArgCache *pygi_arg_glist_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache); /* Internally dispatches GList and GSList */ #define pygi_arg_gslist_new_from_info pygi_arg_glist_new_from_info G_END_DECLS #endif /*__PYGI_LIST_H__*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-marshal-cleanup.c0000664000000000000000000002100015074673150017124 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri , Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include "pygi-marshal-cleanup.h" #include #include "pygi-foreign.h" static inline void _cleanup_caller_allocates (PyGIInvokeState *state, PyGIArgCache *cache, PyObject *py_obj, gpointer data, gboolean was_processed) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)cache; /* check GValue first because GValue is also a boxed sub-type */ if (g_type_is_a (iface_cache->g_type, G_TYPE_VALUE)) { if (was_processed) g_value_unset (data); g_slice_free (GValue, data); } else if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) { gsize size; if (was_processed) return; /* will be cleaned up at deallocation */ size = gi_struct_info_get_size ( GI_STRUCT_INFO (iface_cache->interface_info)); g_slice_free1 (size, data); } else if (iface_cache->is_foreign) { if (was_processed) return; /* will be cleaned up at deallocation */ pygi_struct_foreign_release ( GI_BASE_INFO (iface_cache->interface_info), data); } else { if (was_processed) return; /* will be cleaned up at deallocation */ g_free (data); } } /** * Cleanup during invoke can happen in multiple * stages, each of which can be the result of a * successful compleation of that stage or an error * occured which requires partial cleanup. * * For the most part, either the C interface being * invoked or the python object which wraps the * parameters, handle their lifecycles but in some * cases, where we have intermediate objects, * or when we fail processing a parameter, we need * to handle the clean up manually. * * There are two argument processing stages. * They are the in stage, where we process python * parameters into their C counterparts, and the out * stage, where we process out C parameters back * into python objects. The in stage also sets up * temporary out structures for caller allocated * parameters which need to be cleaned up either on * in stage failure or at the completion of the out * stage (either success or failure) * * The in stage must call one of these cleanup functions: * - pygi_marshal_cleanup_args_from_py_marshal_success * (continue to out stage) * - pygi_marshal_cleanup_args_from_py_parameter_fail * (final, exit from invoke) * * The out stage must call one of these cleanup functions which are all final: * - pygi_marshal_cleanup_args_to_py_marshal_success * - pygi_marshal_cleanup_args_return_fail * - pygi_marshal_cleanup_args_to_py_parameter_fail * **/ void pygi_marshal_cleanup_args_from_py_marshal_success (PyGIInvokeState *state, PyGICallableCache *cache) { guint i; PyObject *error_type, *error_value, *error_traceback; gboolean have_error = !!PyErr_Occurred (); if (have_error) PyErr_Fetch (&error_type, &error_value, &error_traceback); for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) { PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i); PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup; gpointer cleanup_data = state->args[i].arg_cleanup_data; /* Only cleanup using args_cleanup_data when available. * It is the responsibility of the various "from_py" marshalers to return * cleanup_data which is then passed into their respective cleanup function. * PyGIInvokeState.args_cleanup_data stores this data (via _invoke_marshal_in_args) * for the duration of the invoke up until this point. */ if (cleanup_func && cleanup_data != NULL && arg_cache->py_arg_index >= 0 && arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) { PyObject *py_arg = PyTuple_GET_ITEM (state->py_in_args, arg_cache->py_arg_index); cleanup_func (state, arg_cache, py_arg, cleanup_data, TRUE); state->args[i].arg_cleanup_data = NULL; } } if (have_error) PyErr_Restore (error_type, error_value, error_traceback); } void pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState *state, PyGICallableCache *cache) { GSList *cache_item; PyObject *error_type, *error_value, *error_traceback; gboolean have_error = !!PyErr_Occurred (); if (have_error) PyErr_Fetch (&error_type, &error_value, &error_traceback); /* clean up the return if available */ if (cache->return_cache != NULL) { PyGIMarshalToPyCleanupFunc cleanup_func = cache->return_cache->to_py_cleanup; if (cleanup_func && state->return_arg.v_pointer != NULL) cleanup_func (state, cache->return_cache, state->to_py_return_arg_cleanup_data, state->return_arg.v_pointer, TRUE); } /* Now clean up args */ cache_item = cache->to_py_args; while (cache_item) { PyGIArgCache *arg_cache = (PyGIArgCache *)cache_item->data; PyGIMarshalToPyCleanupFunc cleanup_func = arg_cache->to_py_cleanup; gpointer data = state->args[arg_cache->c_arg_index].arg_value.v_pointer; if (cleanup_func != NULL && data != NULL) cleanup_func ( state, arg_cache, state->args[arg_cache->c_arg_index].to_py_arg_cleanup_data, data, TRUE); else if (arg_cache->is_caller_allocates && data != NULL) { _cleanup_caller_allocates ( state, arg_cache, state->args[arg_cache->c_arg_index].to_py_arg_cleanup_data, data, TRUE); } cache_item = cache_item->next; } if (have_error) PyErr_Restore (error_type, error_value, error_traceback); } void pygi_marshal_cleanup_args_from_py_parameter_fail (PyGIInvokeState *state, PyGICallableCache *cache, gssize failed_arg_index) { guint i; PyObject *error_type, *error_value, *error_traceback; gboolean have_error = !!PyErr_Occurred (); if (have_error) PyErr_Fetch (&error_type, &error_value, &error_traceback); state->failed = TRUE; for (i = 0; i < _pygi_callable_cache_args_len (cache) && i <= (guint)failed_arg_index; i++) { PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i); PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup; gpointer cleanup_data = state->args[i].arg_cleanup_data; PyObject *py_arg = NULL; if (arg_cache->py_arg_index < 0) { continue; } py_arg = PyTuple_GET_ITEM (state->py_in_args, arg_cache->py_arg_index); if (cleanup_func && cleanup_data != NULL && arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON) { cleanup_func (state, arg_cache, py_arg, cleanup_data, i < (guint)failed_arg_index); } else if (arg_cache->is_caller_allocates && cleanup_data != NULL) { _cleanup_caller_allocates (state, arg_cache, py_arg, cleanup_data, FALSE); } state->args[i].arg_cleanup_data = NULL; } if (have_error) PyErr_Restore (error_type, error_value, error_traceback); } void pygi_marshal_cleanup_args_return_fail (PyGIInvokeState *state, PyGICallableCache *cache) { state->failed = TRUE; } void pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState *state, PyGICallableCache *cache, gssize failed_to_py_arg_index) { state->failed = TRUE; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-marshal-cleanup.h0000664000000000000000000000324615074673150017145 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri , Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_MARSHAL_CLEANUP_H__ #define __PYGI_MARSHAL_CLEANUP_H__ #include "pygi-struct.h" #include "pygi-invoke-state-struct.h" #include "pygi-cache.h" G_BEGIN_DECLS void pygi_marshal_cleanup_args_from_py_marshal_success ( PyGIInvokeState *state, PyGICallableCache *cache); void pygi_marshal_cleanup_args_from_py_parameter_fail ( PyGIInvokeState *state, PyGICallableCache *cache, gssize failed_arg_index); void pygi_marshal_cleanup_args_to_py_marshal_success ( PyGIInvokeState *state, PyGICallableCache *cache); void pygi_marshal_cleanup_args_return_fail (PyGIInvokeState *state, PyGICallableCache *cache); void pygi_marshal_cleanup_args_to_py_parameter_fail ( PyGIInvokeState *state, PyGICallableCache *cache, gssize failed_to_py_arg_index); G_END_DECLS #endif /* __PYGI_MARSHAL_CLEANUP_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-object.c0000664000000000000000000003206615074673150015334 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-fundamental.h" #include "pygi-object.h" #include "pygobject-object.h" /* * GObject from Python */ typedef gboolean (*PyGIObjectMarshalFromPyFunc) (PyObject *py_arg, GIArgument *arg, GITransfer transfer); /* pygi_marshal_from_py_object: * py_arg: (in): * arg: (out): */ gboolean pygi_marshal_from_py_object (PyObject *py_arg, /*in*/ GIArgument *arg, /*out*/ GITransfer transfer) { GObject *gobj; if (Py_IsNone (py_arg)) { arg->v_pointer = NULL; return TRUE; } if (PyObject_TypeCheck (py_arg, &PyGIFundamental_Type)) { arg->v_pointer = pygi_fundamental_get (py_arg); if (transfer == GI_TRANSFER_EVERYTHING) { pygi_fundamental_ref ((PyGIFundamental *)py_arg); } return TRUE; } if (!pygobject_check (py_arg, &PyGObject_Type)) { PyObject *repr = PyObject_Repr (py_arg); PyErr_Format (PyExc_TypeError, "expected GObject but got %s", PyUnicode_AsUTF8 (repr)); Py_DECREF (repr); return FALSE; } gobj = pygobject_get (py_arg); if (gobj == NULL) { PyErr_Format (PyExc_RuntimeError, "object at %p of type %s is not initialized", py_arg, Py_TYPE (py_arg)->tp_name); return FALSE; } if (transfer == GI_TRANSFER_EVERYTHING) { /* For transfer everything, add a new ref that the callee will take ownership of. * Pythons existing ref to the GObject will be managed with the PyGObject wrapper. */ g_object_ref (gobj); } arg->v_pointer = gobj; return TRUE; } /* pygi_arg_gobject_out_arg_from_py: * py_arg: (in): * arg: (out): * * A specialization for marshaling Python GObjects used for out/return values * from a Python implemented vfuncs, signals, or an assignment to a GObject property. */ gboolean pygi_arg_gobject_out_arg_from_py (PyObject *py_arg, /* in */ GIArgument *arg, /* out */ GITransfer transfer) { GObject *gobj; if (!pygi_marshal_from_py_object (py_arg, arg, transfer)) { return FALSE; } /* HACK: At this point the basic marshaling of the GObject was successful * but we add some special case hacks for vfunc returns due to buggy APIs: * https://bugzilla.gnome.org/show_bug.cgi?id=693393 */ gobj = arg->v_pointer; // In Python 3.13 the py_arg refcount is 3, in 3.14 only 1 if (Py_REFCNT (py_arg) == 1 && gobj->ref_count == 1) { /* If both object ref counts are only 1 at this point (the reference held * in a return tuple), we assume the GObject will be free'd before reaching * its target and become invalid. So instead of getting invalid object errors * we add a new GObject ref. */ g_object_ref (gobj); if (((PyGObject *)py_arg)->private_flags.flags & PYGOBJECT_GOBJECT_WAS_FLOATING) { /* * We want to re-float instances that were floating and the Python * wrapper assumed ownership. With the additional caveat that there * are not any strong references beyond the return tuple. */ g_object_force_floating (gobj); } else { // This may no longer be true, due to differences in refcounting PyObject *repr = PyObject_Repr (py_arg); gchar *msg = g_strdup_printf ( "Expecting to marshal a borrowed reference for %s, " "but nothing in Python is holding a reference to this object. " "See: https://bugzilla.gnome.org/show_bug.cgi?id=687522", PyUnicode_AsUTF8 (repr)); Py_DECREF (repr); if (PyErr_WarnEx (PyExc_RuntimeWarning, msg, 2)) { g_free (msg); return FALSE; } g_free (msg); } } return TRUE; } static gboolean _pygi_marshal_from_py_interface_object (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data, PyGIObjectMarshalFromPyFunc func) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; if (Py_IsNone (py_arg)) { arg->v_pointer = NULL; return TRUE; } if (PyObject_IsInstance (py_arg, iface_cache->py_type) || (pygobject_check (py_arg, &PyGObject_Type) && g_type_is_a (G_OBJECT_TYPE (pygobject_get (py_arg)), iface_cache->g_type))) { gboolean res; res = func (py_arg, arg, arg_cache->transfer); *cleanup_data = arg->v_pointer; return res; } else { PyObject *module = PyObject_GetAttrString (py_arg, "__module__"); PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s", arg_cache->arg_name ? arg_cache->arg_name : "self", ((PyGIInterfaceCache *)arg_cache)->type_name, module ? PyUnicode_AsUTF8 (module) : "", module ? "." : "", Py_TYPE (py_arg)->tp_name); if (module) Py_DECREF (module); return FALSE; } } static gboolean _pygi_marshal_from_py_called_from_c_interface_object ( PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { return _pygi_marshal_from_py_interface_object ( state, callable_cache, arg_cache, py_arg, arg, cleanup_data, pygi_arg_gobject_out_arg_from_py); } static gboolean _pygi_marshal_from_py_called_from_py_interface_object ( PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { return _pygi_marshal_from_py_interface_object ( state, callable_cache, arg_cache, py_arg, arg, cleanup_data, pygi_marshal_from_py_object); } static void _pygi_marshal_cleanup_from_py_interface_object (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed) { /* If we processed the parameter but fail before invoking the method, we need to remove the ref we added */ if (was_processed && state->failed && data != NULL && arg_cache->transfer == GI_TRANSFER_EVERYTHING) g_object_unref (G_OBJECT (data)); } /* * GObject to Python */ static PyObject * pygi_arg_object_to_py (GIArgument *arg, GITransfer transfer) { PyObject *pyobj; if (arg->v_pointer == NULL) { pyobj = Py_None; Py_INCREF (pyobj); } else if (G_IS_OBJECT (arg->v_pointer)) { pyobj = pygobject_new_full (arg->v_pointer, /*steal=*/transfer == GI_TRANSFER_EVERYTHING, /*type=*/NULL); } else { pyobj = pygi_fundamental_new (arg->v_pointer); if (pyobj && transfer == GI_TRANSFER_EVERYTHING) pygi_fundamental_unref ((PyGIFundamental *)pyobj); } return pyobj; } PyObject * pygi_arg_object_to_py_called_from_c (GIArgument *arg, GITransfer transfer) { PyObject *object; /* HACK: * The following hack is to work around GTK sending signals which * contain floating widgets in them. This assumes control of how * references are added by the PyGObject wrapper and avoids the sink * behavior by explicitly passing GI_TRANSFER_EVERYTHING as the transfer * mode and then re-forcing the object as floating afterwards. * * See: https://bugzilla.gnome.org/show_bug.cgi?id=693400 */ if (arg->v_pointer != NULL && transfer == GI_TRANSFER_NOTHING && G_IS_OBJECT (arg->v_pointer) && g_object_is_floating (arg->v_pointer)) { g_object_ref (arg->v_pointer); object = pygi_arg_object_to_py (arg, GI_TRANSFER_EVERYTHING); g_object_force_floating (arg->v_pointer); } else { object = pygi_arg_object_to_py (arg, transfer); } return object; } static PyObject * _pygi_marshal_to_py_called_from_c_interface_object_cache_adapter ( PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { return pygi_arg_object_to_py_called_from_c (arg, arg_cache->transfer); } static PyObject * _pygi_marshal_to_py_called_from_py_interface_object_cache_adapter ( PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { return pygi_arg_object_to_py (arg, arg_cache->transfer); } static void _pygi_marshal_cleanup_to_py_interface_object (PyGIInvokeState *state, PyGIArgCache *arg_cache, gpointer cleanup_data, gpointer data, gboolean was_processed) { if (was_processed && state->failed && data != NULL && arg_cache->transfer == GI_TRANSFER_EVERYTHING) { if (G_IS_OBJECT (data)) { g_object_unref (G_OBJECT (data)); } else { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; GIObjectInfoUnrefFunction unref_func; unref_func = gi_object_info_get_unref_function_pointer ( (GIObjectInfo *)iface_cache->interface_info); if (unref_func) unref_func (data); } } } static gboolean pygi_arg_gobject_setup_from_info (PyGIArgCache *arg_cache, GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache) { /* NOTE: usage of pygi_arg_interface_new_from_info already calls * pygi_arg_interface_setup so no need to do it here. */ if (direction & PYGI_DIRECTION_FROM_PYTHON) { if (callable_cache->calling_context == PYGI_CALLING_CONTEXT_IS_FROM_C) { arg_cache->from_py_marshaller = _pygi_marshal_from_py_called_from_c_interface_object; } else { arg_cache->from_py_marshaller = _pygi_marshal_from_py_called_from_py_interface_object; } arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object; } if (direction & PYGI_DIRECTION_TO_PYTHON) { if (callable_cache->calling_context == PYGI_CALLING_CONTEXT_IS_FROM_C) { arg_cache->to_py_marshaller = _pygi_marshal_to_py_called_from_c_interface_object_cache_adapter; } else { arg_cache->to_py_marshaller = _pygi_marshal_to_py_called_from_py_interface_object_cache_adapter; } arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object; } return TRUE; } PyGIArgCache * pygi_arg_gobject_new_from_info (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, GIRegisteredTypeInfo *iface_info, PyGICallableCache *callable_cache) { gboolean res = FALSE; PyGIArgCache *cache = NULL; cache = pygi_arg_interface_new_from_info (type_info, arg_info, transfer, direction, iface_info); if (cache == NULL) return NULL; res = pygi_arg_gobject_setup_from_info ( cache, type_info, arg_info, transfer, direction, callable_cache); if (res) { return cache; } else { pygi_arg_cache_free (cache); return NULL; } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-object.h0000664000000000000000000000334015074673150015332 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_OBJECT_H__ #define __PYGI_OBJECT_H__ #include #include "pygi-cache.h" G_BEGIN_DECLS gboolean pygi_marshal_from_py_object (PyObject *py_arg, /* in */ GIArgument *arg, /* out */ GITransfer transfer); gboolean pygi_arg_gobject_out_arg_from_py (PyObject *py_arg, /* in */ GIArgument *arg, /* out */ GITransfer transfer); PyObject *pygi_arg_object_to_py_called_from_c (GIArgument *arg, GITransfer transfer); PyGIArgCache *pygi_arg_gobject_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, GIRegisteredTypeInfo *iface_info, PyGICallableCache *callable_cache); G_END_DECLS #endif /*__PYGI_OBJECT_H__*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-property.c0000664000000000000000000003123015074673150015742 0ustar00rootroot/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* * Copyright (c) 2010 Collabora Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include #include "pygi-argument.h" #include "pygi-fundamental.h" #include "pygi-property.h" #include "pygi-repository.h" #include "pygi-type.h" #include "pygi-value.h" static GIPropertyInfo * lookup_property_from_object_info (GIObjectInfo *info, const gchar *attr_name) { gssize n_infos; gint i; n_infos = gi_object_info_get_n_properties (info); for (i = 0; i < n_infos; i++) { GIPropertyInfo *property_info; property_info = gi_object_info_get_property (info, i); g_assert (info != NULL); if (strcmp (attr_name, gi_base_info_get_name (GI_BASE_INFO (property_info))) == 0) { return property_info; } gi_base_info_unref (property_info); } return NULL; } static GIPropertyInfo * lookup_property_from_interface_info (GIInterfaceInfo *info, const gchar *attr_name) { gssize n_infos; gint i; n_infos = gi_interface_info_get_n_properties (info); for (i = 0; i < n_infos; i++) { GIPropertyInfo *property_info; property_info = gi_interface_info_get_property (info, i); g_assert (info != NULL); if (strcmp (attr_name, gi_base_info_get_name (GI_BASE_INFO (property_info))) == 0) { return property_info; } gi_base_info_unref (property_info); } return NULL; } static GIPropertyInfo * _pygi_lookup_property_from_g_type (GType g_type, const gchar *attr_name) { GIPropertyInfo *ret = NULL; GIRepository *repository; GIBaseInfo *info; repository = pygi_repository_get_default (); info = gi_repository_find_by_gtype (repository, g_type); if (info == NULL) return NULL; if (GI_IS_OBJECT_INFO (info)) ret = lookup_property_from_object_info ((GIObjectInfo *)info, attr_name); else if (GI_IS_INTERFACE_INFO (info)) ret = lookup_property_from_interface_info ((GIInterfaceInfo *)info, attr_name); gi_base_info_unref (info); return ret; } PyObject * pygi_call_do_get_property (PyObject *instance, GParamSpec *pspec) { PyObject *py_pspec; PyObject *retval; py_pspec = pygi_fundamental_new (pspec); retval = PyObject_CallMethod (instance, "do_get_property", "O", py_pspec); Py_DECREF (py_pspec); return retval; } PyObject * pygi_get_property_value (PyGObject *instance, GParamSpec *pspec) { GIPropertyInfo *property_info = NULL; GValue value = { 0, }; PyObject *py_value = NULL; GType fundamental; gboolean handled; if (!(pspec->flags & G_PARAM_READABLE)) { PyErr_Format (PyExc_TypeError, "property %s is not readable", g_param_spec_get_name (pspec)); return NULL; } /* Fast path which calls the Python getter implementation directly. * See: https://bugzilla.gnome.org/show_bug.cgi?id=723872 */ if (pyg_gtype_is_custom (pspec->owner_type)) { return pygi_call_do_get_property ((PyObject *)instance, pspec); } Py_BEGIN_ALLOW_THREADS; g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); g_object_get_property (instance->obj, pspec->name, &value); fundamental = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (&value)); Py_END_ALLOW_THREADS; /* Fast path basic types which don't need GI type info. */ py_value = pygi_value_to_py_basic_type (&value, fundamental, &handled); if (handled) { goto out; } /* Attempt to marshal through GI. * The owner_type of the pspec gives us the exact type that introduced the * property, even if it is a parent class of the instance in question. */ property_info = _pygi_lookup_property_from_g_type (pspec->owner_type, pspec->name); if (property_info) { GITypeInfo *type_info = NULL; gboolean free_array = FALSE; GIArgument arg = { 0, }; GITransfer transfer = GI_TRANSFER_NOTHING; type_info = gi_property_info_get_type_info (property_info); arg = _pygi_argument_from_g_value (&value, type_info); /* Arrays are special cased, see note in _pygi_argument_to_array. */ if (gi_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY) { arg.v_pointer = _pygi_argument_to_array (&arg, NULL, NULL, NULL, type_info, &free_array); } else if (g_type_is_a (pspec->value_type, G_TYPE_BOXED)) { arg.v_pointer = g_value_dup_boxed (&value); transfer = GI_TRANSFER_EVERYTHING; } py_value = _pygi_argument_to_object (&arg, type_info, transfer); if (free_array) { g_array_free (arg.v_pointer, FALSE); } gi_base_info_unref (type_info); gi_base_info_unref (property_info); if (PyErr_Occurred ()) { return NULL; } } /* Fallback to GValue marshalling. */ if (py_value == NULL) { py_value = pyg_param_gvalue_as_pyobject (&value, TRUE, pspec); } out: g_value_unset (&value); return py_value; } PyObject * pygi_get_property_value_by_name (PyGObject *self, gchar *param_name) { GParamSpec *pspec; pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (self->obj), param_name); if (!pspec) { PyErr_Format (PyExc_TypeError, "object of type `%s' does not have property `%s'", g_type_name (G_OBJECT_TYPE (self->obj)), param_name); return NULL; } return pygi_get_property_value (self, pspec); } gint pygi_set_property_value (PyGObject *instance, GParamSpec *pspec, PyObject *py_value) { GIPropertyInfo *property_info = NULL; GITypeInfo *type_info = NULL; GIBaseInfo *info = NULL; GITypeTag type_tag; GITransfer transfer; GValue value = { 0, }; GIArgument arg = { 0, }; gint ret_value = -1; /* The owner_type of the pspec gives us the exact type that introduced the * property, even if it is a parent class of the instance in question. */ property_info = _pygi_lookup_property_from_g_type (pspec->owner_type, pspec->name); if (property_info == NULL) goto out; if (!(pspec->flags & G_PARAM_WRITABLE)) goto out; type_info = gi_property_info_get_type_info (property_info); transfer = gi_property_info_get_ownership_transfer (property_info); arg = _pygi_argument_from_object (py_value, type_info, transfer); if (PyErr_Occurred ()) goto out; g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); /* FIXME: Lots of types still unhandled */ type_tag = gi_type_info_get_tag (type_info); switch (type_tag) { case GI_TYPE_TAG_INTERFACE: { GType type; info = gi_type_info_get_interface (type_info); type = gi_registered_type_info_get_g_type ( GI_REGISTERED_TYPE_INFO (info)); if (GI_IS_FLAGS_INFO (info)) { /* Check flags before enums: flags are a subtype of enum. */ g_value_set_flags (&value, arg.v_uint); } else if (GI_IS_ENUM_INFO (info)) { g_value_set_enum (&value, arg.v_int); } else if (GI_IS_INTERFACE_INFO (info) || GI_IS_OBJECT_INFO (info)) { if (arg.v_pointer == NULL || G_IS_OBJECT (arg.v_pointer)) { g_value_set_object (&value, arg.v_pointer); } else if (!pygi_fundamental_set_value (&value, arg.v_pointer)) { PyErr_Format ( PyExc_NotImplementedError, "Setting properties of type '%s' is not implemented", g_type_name (type)); goto out; } } else if (GI_IS_STRUCT_INFO (info) || GI_IS_UNION_INFO (info)) { if (g_type_is_a (type, G_TYPE_BOXED)) { g_value_set_boxed (&value, arg.v_pointer); } else if (g_type_is_a (type, G_TYPE_VARIANT)) { g_value_set_variant (&value, arg.v_pointer); } else { PyErr_Format ( PyExc_NotImplementedError, "Setting properties of type '%s' is not implemented", g_type_name (type)); goto out; } } else { PyErr_Format (PyExc_NotImplementedError, "Setting properties of type '%s' is not implemented", g_type_name (type)); goto out; } break; } case GI_TYPE_TAG_BOOLEAN: g_value_set_boolean (&value, arg.v_boolean); break; case GI_TYPE_TAG_INT8: g_value_set_schar (&value, arg.v_int8); break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_INT32: if (G_VALUE_HOLDS_LONG (&value)) g_value_set_long (&value, arg.v_long); else g_value_set_int (&value, arg.v_int); break; case GI_TYPE_TAG_INT64: if (G_VALUE_HOLDS_LONG (&value)) g_value_set_long (&value, arg.v_long); else g_value_set_int64 (&value, arg.v_int64); break; case GI_TYPE_TAG_UINT8: g_value_set_uchar (&value, arg.v_uint8); break; case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_UINT32: if (G_VALUE_HOLDS_ULONG (&value)) g_value_set_ulong (&value, arg.v_ulong); else g_value_set_uint (&value, arg.v_uint); break; case GI_TYPE_TAG_UINT64: if (G_VALUE_HOLDS_ULONG (&value)) g_value_set_ulong (&value, arg.v_ulong); else g_value_set_uint64 (&value, arg.v_uint64); break; case GI_TYPE_TAG_FLOAT: g_value_set_float (&value, arg.v_float); break; case GI_TYPE_TAG_DOUBLE: g_value_set_double (&value, arg.v_double); break; case GI_TYPE_TAG_GTYPE: g_value_set_gtype (&value, arg.v_size); break; case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: g_value_set_string (&value, arg.v_string); break; case GI_TYPE_TAG_GHASH: g_value_set_boxed (&value, arg.v_pointer); break; case GI_TYPE_TAG_GLIST: if (G_VALUE_HOLDS_BOXED (&value)) g_value_set_boxed (&value, arg.v_pointer); else g_value_set_pointer (&value, arg.v_pointer); break; case GI_TYPE_TAG_ARRAY: { /* This is assumes GI_TYPE_TAG_ARRAY is always a GStrv * https://bugzilla.gnome.org/show_bug.cgi?id=688232 */ GArray *arg_items = (GArray *)arg.v_pointer; gchar **strings; guint i; if (arg_items == NULL) goto out; strings = g_new0 (char *, arg_items->len + 1); for (i = 0; i < arg_items->len; ++i) { strings[i] = g_array_index (arg_items, GIArgument, i).v_string; } strings[arg_items->len] = NULL; g_value_take_boxed (&value, strings); g_array_free (arg_items, TRUE); break; } default: PyErr_Format ( PyExc_NotImplementedError, "Setting properties of type %s is not implemented", gi_type_tag_to_string (gi_type_info_get_tag (type_info))); goto out; } g_object_set_property (instance->obj, pspec->name, &value); g_value_unset (&value); ret_value = 0; out: if (property_info != NULL) gi_base_info_unref (property_info); if (type_info != NULL) gi_base_info_unref (type_info); if (info != NULL) gi_base_info_unref (info); return ret_value; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-property.h0000664000000000000000000000334715074673150015757 0ustar00rootroot/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* * Copyright (c) 2010 Collabora Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #ifndef __PYGI_PROPERTY_H__ #define __PYGI_PROPERTY_H__ #include #include #include "pygobject-internal.h" PyObject *pygi_get_property_value (PyGObject *instance, GParamSpec *pspec); PyObject *pygi_get_property_value_by_name (PyGObject *self, gchar *param_name); PyObject *pygi_call_do_get_property (PyObject *instance, GParamSpec *pspec); gint pygi_set_property_value (PyGObject *instance, GParamSpec *pspec, PyObject *py_value); #endif /* __PYGI_PROPERTY_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-repository.c0000664000000000000000000003432715074673150016307 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2005-2009 Johan Dahlin * * pygi-repository.c: GIRepository wrapper. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include "pygi-basictype.h" #include "pygi-info.h" #include "pygi-repository.h" #include "pygi-util.h" PyObject *PyGIRepositoryError; PYGI_DEFINE_TYPE ("gi.Repository", PyGIRepository_Type, PyGIRepository); GIRepository * pygi_repository_get_default (void) { static GIRepository *default_repository = NULL; if (default_repository == NULL) #if GLIB_CHECK_VERSION(2, 85, 0) default_repository = gi_repository_dup_default (); #else default_repository = gi_repository_new (); #endif return default_repository; } static PyObject * _wrap_pygi_repository_get_default (PyObject *self) { static PyGIRepository *repository = NULL; if (!repository) { repository = (PyGIRepository *)PyObject_New (PyGIRepository, &PyGIRepository_Type); if (repository == NULL) { return NULL; } repository->repository = pygi_repository_get_default (); } Py_INCREF ((PyObject *)repository); return (PyObject *)repository; } static PyObject * _wrap_gi_repository_prepend_library_path (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "directory", NULL }; const char *directory; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:Repository.prepend_library_path", kwlist, &directory)) { return NULL; } gi_repository_prepend_library_path (self->repository, directory); Py_RETURN_NONE; } static PyObject * _wrap_gi_repository_prepend_search_path (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "directory", NULL }; const char *directory; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:Repository.prepend_search_path", kwlist, &directory)) { return NULL; } gi_repository_prepend_search_path (self->repository, directory); Py_RETURN_NONE; } static PyObject * _wrap_gi_repository_enumerate_versions (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "namespace", NULL }; const char *namespace_; char **versions = NULL; PyObject *ret = NULL; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:Repository.enumerate_versions", kwlist, &namespace_)) { return NULL; } versions = gi_repository_enumerate_versions (self->repository, namespace_, NULL); ret = PyList_New (0); for (size_t i = 0; versions[i] != NULL; i++) { char *version = g_steal_pointer (&versions[i]); PyObject *py_version = pygi_utf8_to_py (version); PyList_Append (ret, py_version); Py_DECREF (py_version); g_free (version); } g_free (versions); return ret; } static PyObject * _wrap_gi_repository_require (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "namespace", "version", "lazy", NULL }; const char *namespace_; const char *version = NULL; PyObject *lazy = NULL; GIRepositoryLoadFlags flags = 0; GError *error; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s|zO:Repository.require", kwlist, &namespace_, &version, &lazy)) { return NULL; } if (lazy != NULL && PyObject_IsTrue (lazy)) { flags |= GI_REPOSITORY_LOAD_FLAG_LAZY; } error = NULL; gi_repository_require (self->repository, namespace_, version, flags, &error); if (error != NULL) { PyErr_SetString (PyGIRepositoryError, error->message); g_error_free (error); return NULL; } Py_RETURN_NONE; } static PyObject * _wrap_gi_repository_is_registered (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "namespace", "version", NULL }; const char *namespace_; const char *version = NULL; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s|z:Repository.is_registered", kwlist, &namespace_, &version)) { return NULL; } return pygi_gboolean_to_py ( gi_repository_is_registered (self->repository, namespace_, version)); } static PyObject * _wrap_gi_repository_find_by_name (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "namespace", "name", NULL }; const char *namespace_; const char *name; GIBaseInfo *info; PyObject *py_info; size_t len; char *trimmed_name = NULL; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "ss:Repository.find_by_name", kwlist, &namespace_, &name)) { return NULL; } /* If the given name ends with an underscore, it might be due to usage * as an accessible replacement for something in GI with the same name * as a Python keyword. Test for this and trim it out if necessary. */ len = strlen (name); if (len > 0 && name[len - 1] == '_') { PyObject *is_keyword; trimmed_name = g_strndup (name, len - 1); is_keyword = _pygi_is_python_keyword (trimmed_name); if (!is_keyword) return NULL; if (PyObject_IsTrue (is_keyword)) name = trimmed_name; Py_DECREF (is_keyword); } info = gi_repository_find_by_name (self->repository, namespace_, name); g_free (trimmed_name); if (info == NULL) { Py_RETURN_NONE; } py_info = _pygi_info_new (info); gi_base_info_unref (info); return py_info; } static PyObject * _wrap_gi_repository_get_infos (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "namespace", NULL }; const char *namespace_; gssize n_infos; PyObject *infos; gint i; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:Repository.get_infos", kwlist, &namespace_)) { return NULL; } n_infos = gi_repository_get_n_infos (self->repository, namespace_); if (n_infos < 0) { PyErr_Format (PyExc_RuntimeError, "Namespace '%s' not loaded", namespace_); return NULL; } infos = PyTuple_New (n_infos); for (i = 0; i < n_infos; i++) { GIBaseInfo *info; PyObject *py_info; info = gi_repository_get_info (self->repository, namespace_, i); g_assert (info != NULL); py_info = _pygi_info_new (info); gi_base_info_unref (info); if (py_info == NULL) { Py_CLEAR (infos); break; } PyTuple_SET_ITEM (infos, i, py_info); } return infos; } static PyObject * _wrap_gi_repository_get_typelib_path (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "namespace", NULL }; const char *namespace_; const gchar *typelib_path; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:Repository.get_typelib_path", kwlist, &namespace_)) { return NULL; } typelib_path = gi_repository_get_typelib_path (self->repository, namespace_); if (typelib_path == NULL) { PyErr_Format (PyExc_RuntimeError, "Namespace '%s' not loaded", namespace_); return NULL; } return pygi_filename_to_py (typelib_path); } static PyObject * _wrap_gi_repository_get_version (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "namespace", NULL }; const char *namespace_; const gchar *version; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:Repository.get_version", kwlist, &namespace_)) { return NULL; } version = gi_repository_get_version (self->repository, namespace_); if (version == NULL) { PyErr_Format (PyExc_RuntimeError, "Namespace '%s' not loaded", namespace_); return NULL; } return pygi_utf8_to_py (version); } static PyObject * _wrap_gi_repository_get_loaded_namespaces (PyGIRepository *self) { char **namespaces; PyObject *py_namespaces; gssize i; namespaces = gi_repository_get_loaded_namespaces (self->repository, NULL); py_namespaces = PyList_New (0); for (i = 0; namespaces[i] != NULL; i++) { PyObject *py_namespace = pygi_utf8_to_py (namespaces[i]); PyList_Append (py_namespaces, py_namespace); Py_DECREF (py_namespace); g_free (namespaces[i]); } g_free (namespaces); return py_namespaces; } static PyObject * _wrap_gi_repository_get_dependencies (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "namespace", NULL }; const char *namespace_; char **namespaces; PyObject *py_namespaces; gssize i; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:Repository.get_dependencies", kwlist, &namespace_)) { return NULL; } py_namespaces = PyList_New (0); /* Returns NULL in case of no dependencies */ namespaces = gi_repository_get_dependencies (self->repository, namespace_, NULL); if (namespaces == NULL) { return py_namespaces; } for (i = 0; namespaces[i] != NULL; i++) { PyObject *py_namespace = pygi_utf8_to_py (namespaces[i]); PyList_Append (py_namespaces, py_namespace); Py_DECREF (py_namespace); } g_strfreev (namespaces); return py_namespaces; } static PyObject * _wrap_gi_repository_get_immediate_dependencies (PyGIRepository *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "namespace", NULL }; const char *namespace_; char **namespaces; PyObject *py_namespaces; gssize i; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "s:Repository.get_immediate_dependencies", kwlist, &namespace_)) { return NULL; } py_namespaces = PyList_New (0); namespaces = gi_repository_get_immediate_dependencies (self->repository, namespace_, NULL); for (i = 0; namespaces[i] != NULL; i++) { PyObject *py_namespace = pygi_utf8_to_py (namespaces[i]); PyList_Append (py_namespaces, py_namespace); Py_DECREF (py_namespace); } g_strfreev (namespaces); return py_namespaces; } static PyMethodDef _PyGIRepository_methods[] = { { "get_default", (PyCFunction)_wrap_pygi_repository_get_default, METH_NOARGS | METH_STATIC }, { "enumerate_versions", (PyCFunction)_wrap_gi_repository_enumerate_versions, METH_VARARGS | METH_KEYWORDS }, { "require", (PyCFunction)_wrap_gi_repository_require, METH_VARARGS | METH_KEYWORDS }, { "get_infos", (PyCFunction)_wrap_gi_repository_get_infos, METH_VARARGS | METH_KEYWORDS }, { "find_by_name", (PyCFunction)_wrap_gi_repository_find_by_name, METH_VARARGS | METH_KEYWORDS }, { "get_typelib_path", (PyCFunction)_wrap_gi_repository_get_typelib_path, METH_VARARGS | METH_KEYWORDS }, { "get_version", (PyCFunction)_wrap_gi_repository_get_version, METH_VARARGS | METH_KEYWORDS }, { "get_loaded_namespaces", (PyCFunction)_wrap_gi_repository_get_loaded_namespaces, METH_NOARGS }, { "get_dependencies", (PyCFunction)_wrap_gi_repository_get_dependencies, METH_VARARGS | METH_KEYWORDS }, { "get_immediate_dependencies", (PyCFunction)_wrap_gi_repository_get_immediate_dependencies, METH_VARARGS | METH_KEYWORDS }, { "is_registered", (PyCFunction)_wrap_gi_repository_is_registered, METH_VARARGS | METH_KEYWORDS }, { "prepend_library_path", (PyCFunction)_wrap_gi_repository_prepend_library_path, METH_VARARGS | METH_KEYWORDS }, { "prepend_search_path", (PyCFunction)_wrap_gi_repository_prepend_search_path, METH_VARARGS | METH_KEYWORDS }, { NULL, NULL, 0 }, }; /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_repository_register_types (PyObject *m) { Py_SET_TYPE (&PyGIRepository_Type, &PyType_Type); PyGIRepository_Type.tp_flags = Py_TPFLAGS_DEFAULT; PyGIRepository_Type.tp_methods = _PyGIRepository_methods; if (PyType_Ready (&PyGIRepository_Type) < 0) return -1; Py_INCREF ((PyObject *)&PyGIRepository_Type); if (PyModule_AddObject (m, "Repository", (PyObject *)&PyGIRepository_Type) < 0) { Py_DECREF ((PyObject *)&PyGIRepository_Type); return -1; } PyGIRepositoryError = PyErr_NewException ("gi.RepositoryError", NULL, NULL); if (PyGIRepositoryError == NULL) return -1; Py_INCREF (PyGIRepositoryError); if (PyModule_AddObject (m, "RepositoryError", PyGIRepositoryError) < 0) { Py_DECREF (PyGIRepositoryError); return -1; } return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-repository.h0000664000000000000000000000241515074673150016305 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2005-2009 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_REPOSITORY_H__ #define __PYGI_REPOSITORY_H__ #include #include G_BEGIN_DECLS typedef struct { PyObject_HEAD GIRepository *repository; } PyGIRepository; /* Private */ extern PyTypeObject PyGIRepository_Type; extern PyObject *PyGIRepositoryError; GIRepository *pygi_repository_get_default (void); int pygi_repository_register_types (PyObject *m); G_END_DECLS #endif /* __PYGI_REPOSITORY_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-resulttuple.c0000664000000000000000000002632115074673150016453 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2015 Christoph Reiter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-resulttuple.h" #include "pygi-util.h" static char repr_format_key[] = "__repr_format"; static char tuple_indices_key[] = "__tuple_indices"; #define PYGI_USE_FREELIST #ifdef PYPY_VERSION #undef PYGI_USE_FREELIST #endif #ifdef PYGI_USE_FREELIST /* A free list similar to the one used for the CPython tuple. Difference * is that zero length tuples aren't cached (as we don't need them) * and that the freelist is smaller as we don't free it with the cyclic GC * as CPython does. This wastes 21kB max. */ #define PyGIResultTuple_MAXSAVESIZE 10 #define PyGIResultTuple_MAXFREELIST 100 static PyObject *free_list[PyGIResultTuple_MAXSAVESIZE]; static int numfree[PyGIResultTuple_MAXSAVESIZE]; #endif PYGI_DEFINE_TYPE ("gi._gi.ResultTuple", PyGIResultTuple_Type, PyTupleObject) /** * ResultTuple.__repr__() implementation. * Takes the _ResultTuple.__repr_format format string and applies the tuple * values to it. */ static PyObject * resulttuple_repr (PyObject *self) { PyObject *format, *repr, *format_attr; format_attr = PyUnicode_FromString (repr_format_key); format = PyTuple_Type.tp_getattro (self, format_attr); Py_DECREF (format_attr); if (format == NULL) return NULL; repr = PyUnicode_Format (format, self); Py_DECREF (format); return repr; } /** * PyGIResultTuple_Type.tp_getattro implementation. * Looks up the tuple index in _ResultTuple.__tuple_indices and returns the * tuple item. */ static PyObject * resulttuple_getattro (PyObject *self, PyObject *name) { PyObject *mapping, *index, *mapping_attr, *item; mapping_attr = PyUnicode_FromString (tuple_indices_key); mapping = PyTuple_Type.tp_getattro (self, mapping_attr); Py_DECREF (mapping_attr); if (mapping == NULL) return NULL; g_assert (PyDict_Check (mapping)); index = PyDict_GetItem (mapping, name); if (index != NULL) { item = PyTuple_GET_ITEM (self, PyLong_AsSsize_t (index)); if (item == NULL) Py_RETURN_NONE; Py_INCREF (item); } else { item = PyTuple_Type.tp_getattro (self, name); } Py_DECREF (mapping); return item; } /** * ResultTuple.__reduce__() implementation. * Always returns (tuple, tuple(self)) * Needed so that pickling doesn't depend on our tuple subclass and unpickling * works without it. As a result unpickle will give back in a normal tuple. */ static PyObject * resulttuple_reduce (PyObject *self) { PyObject *tuple = PySequence_Tuple (self); if (tuple == NULL) return NULL; return Py_BuildValue ("(O, (N))", &PyTuple_Type, tuple); } /** * Extends __dir__ with the extra attributes accessible through * resulttuple_getattro() */ static PyObject * resulttuple_dir (PyObject *self) { PyObject *mapping_attr; PyObject *items = NULL; PyObject *mapping = NULL; PyObject *mapping_values = NULL; PyObject *result = NULL; mapping_attr = PyUnicode_FromString (tuple_indices_key); mapping = PyTuple_Type.tp_getattro (self, mapping_attr); Py_DECREF (mapping_attr); if (mapping == NULL) goto error; items = PyObject_Dir ((PyObject *)Py_TYPE (self)); if (items == NULL) goto error; mapping_values = PyDict_Keys (mapping); if (mapping_values == NULL) goto error; result = PySequence_InPlaceConcat (items, mapping_values); error: Py_XDECREF (items); Py_XDECREF (mapping); Py_XDECREF (mapping_values); return result; } /** * resulttuple_new_type: * @args: one list object containing tuple item names and None * * Exposes pygi_resulttuple_new_type() as ResultTuple._new_type() * to allow creation of result types for unit tests. * * Returns: A new PyTypeObject which is a subclass of PyGIResultTuple_Type * or %NULL in case of an error. */ static PyObject * resulttuple_new_type (PyObject *self, PyObject *args) { PyObject *tuple_names, *new_type; if (!PyArg_ParseTuple (args, "O:ResultTuple._new_type", &tuple_names)) return NULL; if (!PyList_Check (tuple_names)) { PyErr_SetString (PyExc_TypeError, "not a list"); return NULL; } new_type = (PyObject *)pygi_resulttuple_new_type (tuple_names); return new_type; } static PyMethodDef resulttuple_methods[] = { { "__reduce__", (PyCFunction)resulttuple_reduce, METH_NOARGS }, { "__dir__", (PyCFunction)resulttuple_dir, METH_NOARGS }, { "_new_type", (PyCFunction)resulttuple_new_type, METH_VARARGS | METH_STATIC }, { NULL, NULL, 0 }, }; /** * pygi_resulttuple_new_type: * @tuple_names: A python list containing str or None items. * * Similar to namedtuple() creates a new tuple subclass which * allows to access items by name and have a pretty __repr__. * Each item in the passed name list corresponds to an item with * the same index in the tuple class. If the name is None the item/index * is unnamed. * * Returns: A new PyTypeObject which is a subclass of PyGIResultTuple_Type * or %NULL in case of an error. */ PyTypeObject * pygi_resulttuple_new_type (PyObject *tuple_names) { PyTypeObject *new_type; PyObject *class_dict, *format_string, *empty_format, *named_format, *format_list, *sep, *index_dict, *slots, *paren_format, *new_type_args, *paren_string; Py_ssize_t len, i; g_assert (PyList_Check (tuple_names)); class_dict = PyDict_New (); /* To save some memory don't use an instance dict */ slots = PyTuple_New (0); PyDict_SetItemString (class_dict, "__slots__", slots); Py_DECREF (slots); format_list = PyList_New (0); index_dict = PyDict_New (); empty_format = PyUnicode_FromString ("%r"); named_format = PyUnicode_FromString ("%s=%%r"); len = PyList_Size (tuple_names); for (i = 0; i < len; i++) { PyObject *item, *named_args, *named_build, *index; item = PyList_GET_ITEM (tuple_names, i); if (Py_IsNone (item)) { PyList_Append (format_list, empty_format); } else { named_args = Py_BuildValue ("(O)", item); named_build = PyUnicode_Format (named_format, named_args); Py_DECREF (named_args); PyList_Append (format_list, named_build); Py_DECREF (named_build); index = PyLong_FromSsize_t (i); PyDict_SetItem (index_dict, item, index); Py_DECREF (index); } } Py_DECREF (empty_format); Py_DECREF (named_format); sep = PyUnicode_FromString (", "); format_string = PyObject_CallMethod (sep, "join", "O", format_list); Py_DECREF (sep); Py_DECREF (format_list); paren_format = PyUnicode_FromString ("(%s)"); paren_string = PyUnicode_Format (paren_format, format_string); Py_DECREF (paren_format); Py_DECREF (format_string); PyDict_SetItemString (class_dict, repr_format_key, paren_string); Py_DECREF (paren_string); PyDict_SetItemString (class_dict, tuple_indices_key, index_dict); Py_DECREF (index_dict); new_type_args = Py_BuildValue ("s(O)O", "_ResultTuple", &PyGIResultTuple_Type, class_dict); new_type = (PyTypeObject *)PyType_Type.tp_new (&PyType_Type, new_type_args, NULL); Py_DECREF (new_type_args); Py_DECREF (class_dict); if (new_type != NULL) { /* disallow subclassing as that would break the free list caching * since we assume that all subclasses use PyTupleObject */ new_type->tp_flags &= ~Py_TPFLAGS_BASETYPE; } return new_type; } /** * pygi_resulttuple_new: * @subclass: A PyGIResultTuple_Type subclass which will be the type of the * returned instance. * @len: Length of the returned tuple * * Like PyTuple_New(). Return an uninitialized tuple of the given @length. * * Returns: An instance of @subclass or %NULL on error. */ PyObject * pygi_resulttuple_new (PyTypeObject *subclass, Py_ssize_t len) { #ifdef PYGI_USE_FREELIST PyObject *self; Py_ssize_t i; /* Check the free list for a tuple object with the needed size; * clear it and change the class to ours. */ if (len > 0 && len < PyGIResultTuple_MAXSAVESIZE) { self = free_list[len]; if (self != NULL) { free_list[len] = PyTuple_GET_ITEM (self, 0); numfree[len]--; for (i = 0; i < len; i++) { PyTuple_SET_ITEM (self, i, NULL); } Py_SET_TYPE (self, subclass); Py_INCREF (subclass); _Py_NewReference (self); PyObject_GC_Track (self); return self; } } #endif /* For zero length tuples and in case the free list is empty, alloc * as usual. */ return subclass->tp_alloc (subclass, len); } #ifdef PYGI_USE_FREELIST static void resulttuple_dealloc (PyObject *self) { Py_ssize_t i, len; PyObject_GC_UnTrack (self); CPy_TRASHCAN_BEGIN (self, resulttuple_dealloc) /* Free the tuple items and, if there is space, save the tuple object * pointer to the front of the free list for its size. Otherwise free it. */ len = Py_SIZE (self); if (len > 0) { for (i = 0; i < len; i++) { Py_XDECREF (PyTuple_GET_ITEM (self, i)); } if (len < PyGIResultTuple_MAXSAVESIZE && numfree[len] < PyGIResultTuple_MAXFREELIST) { PyTuple_SET_ITEM (self, 0, free_list[len]); numfree[len]++; free_list[len] = self; goto done; } } Py_TYPE (self)->tp_free (self); done: CPy_TRASHCAN_END (self) } #endif /** * pygi_resulttuple_register_types: * @module: A Python modules to which ResultTuple gets added to. * * Initializes the ResultTuple class and adds it to the passed @module. * * Returns: -1 on error, 0 on success. */ int pygi_resulttuple_register_types (PyObject *module) { PyGIResultTuple_Type.tp_base = &PyTuple_Type; PyGIResultTuple_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; PyGIResultTuple_Type.tp_repr = (reprfunc)resulttuple_repr; PyGIResultTuple_Type.tp_getattro = (getattrofunc)resulttuple_getattro; PyGIResultTuple_Type.tp_methods = resulttuple_methods; #ifdef PYGI_USE_FREELIST PyGIResultTuple_Type.tp_dealloc = (destructor)resulttuple_dealloc; #endif if (PyType_Ready (&PyGIResultTuple_Type) < 0) return -1; Py_INCREF (&PyGIResultTuple_Type); if (PyModule_AddObject (module, "ResultTuple", (PyObject *)&PyGIResultTuple_Type) < 0) { Py_DECREF (&PyGIResultTuple_Type); return -1; } return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-resulttuple.h0000664000000000000000000000216215074673150016455 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2015 Christoph Reiter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_RESULTTUPLE_H__ #define __PYGI_RESULTTUPLE_H__ #include "Python.h" int pygi_resulttuple_register_types (PyObject *d); PyTypeObject *pygi_resulttuple_new_type (PyObject *tuple_names); PyObject *pygi_resulttuple_new (PyTypeObject *subclass, Py_ssize_t len); #endif /* __PYGI_RESULTTUPLE_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-signal-closure.c0000664000000000000000000002413415074673150017012 0ustar00rootroot/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* * Copyright (c) 2011 Laszlo Pandy * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-signal-closure.h" #include "pygi-argument.h" #include "pygi-boxed.h" #include "pygi-repository.h" #include "pygi-value.h" static GISignalInfo * _pygi_lookup_signal_from_g_type (GType g_type, const gchar *signal_name) { GIRepository *repository; GIBaseInfo *info; GISignalInfo *signal_info = NULL; repository = pygi_repository_get_default (); info = gi_repository_find_by_gtype (repository, g_type); if (info == NULL) return NULL; if (GI_IS_OBJECT_INFO (info)) signal_info = gi_object_info_find_signal (GI_OBJECT_INFO (info), signal_name); else if (GI_IS_INTERFACE_INFO (info)) signal_info = gi_interface_info_find_signal (GI_INTERFACE_INFO (info), signal_name); gi_base_info_unref (info); return signal_info; } static void pygi_signal_closure_invalidate (gpointer data, GClosure *closure) { PyGClosure *pc = (PyGClosure *)closure; PyGILState_STATE state; state = PyGILState_Ensure (); Py_XDECREF (pc->callback); Py_XDECREF (pc->extra_args); Py_XDECREF (pc->swap_data); PyGILState_Release (state); pc->callback = NULL; pc->extra_args = NULL; pc->swap_data = NULL; gi_base_info_unref (((PyGISignalClosure *)pc)->signal_info); ((PyGISignalClosure *)pc)->signal_info = NULL; } static void pygi_signal_closure_marshal (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data) { PyGILState_STATE state; PyGClosure *pc = (PyGClosure *)closure; PyObject *params, *ret = NULL; guint i; GISignalInfo *signal_info; gint n_sig_info_args; gint sig_info_highest_arg; GSList *list_item = NULL; GSList *pass_by_ref_structs = NULL; state = PyGILState_Ensure (); signal_info = ((PyGISignalClosure *)closure)->signal_info; n_sig_info_args = gi_callable_info_get_n_args (GI_CALLABLE_INFO (signal_info)); g_assert_cmpint (n_sig_info_args, >=, 0); /* the first argument to a signal callback is instance, but instance is not counted in the introspection data */ sig_info_highest_arg = n_sig_info_args + 1; g_assert_cmpint (sig_info_highest_arg, ==, n_param_values); /* construct Python tuple for the parameter values */ params = PyTuple_New (n_param_values); for (i = 0; i < n_param_values; i++) { /* swap in a different initial data for connect_object() */ if (i == 0 && G_CCLOSURE_SWAP_DATA (closure)) { g_return_if_fail (pc->swap_data != NULL); Py_INCREF (pc->swap_data); PyTuple_SetItem (params, 0, pc->swap_data); } else if (i == 0) { PyObject *item = pyg_value_as_pyobject (¶m_values[i], FALSE); if (!item) { goto out; } PyTuple_SetItem (params, i, item); } else if (i < (guint)sig_info_highest_arg) { GIArgInfo arg_info; GITypeInfo type_info; GITypeTag type_tag; GIArgument arg = { 0, }; PyObject *item = NULL; gboolean free_array = FALSE; gboolean pass_struct_by_ref = FALSE; gi_callable_info_load_arg (GI_CALLABLE_INFO (signal_info), i - 1, &arg_info); gi_arg_info_load_type_info (&arg_info, &type_info); arg = _pygi_argument_from_g_value (¶m_values[i], &type_info); type_tag = gi_type_info_get_tag (&type_info); if (type_tag == GI_TYPE_TAG_ARRAY) { /* Skip the self argument of param_values */ arg.v_pointer = _pygi_argument_to_array ( &arg, _pygi_argument_array_length_marshal, (void *)(param_values + 1), signal_info, &type_info, &free_array); } /* Hack to ensure struct arguments are passed-by-reference allowing * callback implementors to modify the struct values. This is needed * for keeping backwards compatibility and should be removed in future * versions which support signal output arguments as return values. * See: https://bugzilla.gnome.org/show_bug.cgi?id=735486 * * Note the logic here must match the logic path taken in _pygi_argument_to_object. */ if (type_tag == GI_TYPE_TAG_INTERFACE) { GIBaseInfo *info = gi_type_info_get_interface (&type_info); if (GI_IS_STRUCT_INFO (info) || GI_IS_UNION_INFO (info)) { GType gtype = gi_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)info); gboolean is_foreign = (GI_IS_STRUCT_INFO (info)) && (gi_struct_info_is_foreign ((GIStructInfo *)info)); if (!is_foreign && !g_type_is_a (gtype, G_TYPE_VALUE) && g_type_is_a (gtype, G_TYPE_BOXED)) { pass_struct_by_ref = TRUE; } } gi_base_info_unref (info); } if (pass_struct_by_ref) { /* transfer everything will ensure the struct is not copied when wrapped. */ item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_EVERYTHING); if (item && PyObject_IsInstance (item, (PyObject *)&PyGIBoxed_Type)) { ((PyGBoxed *)item)->free_on_dealloc = FALSE; pass_by_ref_structs = g_slist_prepend (pass_by_ref_structs, item); } } else { item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_NOTHING); } if (free_array) { g_array_free (arg.v_pointer, FALSE); } if (item == NULL) { PyErr_Print (); goto out; } PyTuple_SetItem (params, i, item); } } /* params passed to function may have extra arguments */ if (pc->extra_args) { PyObject *tuple = params; params = PySequence_Concat (tuple, pc->extra_args); Py_DECREF (tuple); } ret = PyObject_CallObject (pc->callback, params); if (ret == NULL) { if (pc->exception_handler) pc->exception_handler (return_value, n_param_values, param_values); else PyErr_Print (); goto out; } if (G_IS_VALUE (return_value) && pyg_value_from_pyobject (return_value, ret) != 0) { PyErr_SetString (PyExc_TypeError, "can't convert return value to desired type"); if (pc->exception_handler) pc->exception_handler (return_value, n_param_values, param_values); else PyErr_Print (); } Py_DECREF (ret); /* Run through the list of structs which have been passed by reference and * check if they are being held longer than the duration of the callback * execution. This is determined if the ref count is greater than 1. * A single ref is held by the argument list and any more would mean the callback * stored a ref somewhere else. In this case we make an internal copy of * the boxed struct so Python can own the memory to it. */ list_item = pass_by_ref_structs; while (list_item) { PyObject *item = list_item->data; if (Py_REFCNT (item) > 1) { pygi_boxed_copy_in_place ((PyGIBoxed *)item); } list_item = g_slist_next (list_item); } out: g_slist_free (pass_by_ref_structs); Py_DECREF (params); PyGILState_Release (state); } GClosure * pygi_signal_closure_new (PyGObject *instance, GType g_type, const gchar *signal_name, PyObject *callback, PyObject *extra_args, PyObject *swap_data) { GClosure *closure = NULL; PyGISignalClosure *pygi_closure = NULL; GISignalInfo *signal_info = NULL; g_return_val_if_fail (callback != NULL, NULL); signal_info = _pygi_lookup_signal_from_g_type (g_type, signal_name); if (signal_info == NULL) return NULL; closure = g_closure_new_simple (sizeof (PyGISignalClosure), NULL); g_closure_add_invalidate_notifier (closure, NULL, pygi_signal_closure_invalidate); g_closure_set_marshal (closure, pygi_signal_closure_marshal); pygi_closure = (PyGISignalClosure *)closure; pygi_closure->signal_info = signal_info; pygi_closure->pyg_closure.callback = Py_NewRef (callback); if (extra_args != NULL && !Py_IsNone (extra_args)) { Py_INCREF (extra_args); if (!PyTuple_Check (extra_args)) { PyObject *tmp = PyTuple_New (1); PyTuple_SetItem (tmp, 0, extra_args); extra_args = tmp; } pygi_closure->pyg_closure.extra_args = extra_args; } if (swap_data) { pygi_closure->pyg_closure.swap_data = Py_NewRef (swap_data); closure->derivative_flag = TRUE; } return closure; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-signal-closure.h0000664000000000000000000000341615074673150017017 0ustar00rootroot/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* * Copyright (c) 2011 Laszlo Pandy * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #ifndef __PYGI_SIGNAL_CLOSURE_H__ #define __PYGI_SIGNAL_CLOSURE_H__ #include #include #include "pygobject-internal.h" G_BEGIN_DECLS /* Private */ typedef struct _PyGISignalClosure { PyGClosure pyg_closure; GISignalInfo *signal_info; } PyGISignalClosure; GClosure *pygi_signal_closure_new (PyGObject *instance, GType g_type, const gchar *sig_name, PyObject *callback, PyObject *extra_args, PyObject *swap_data); G_END_DECLS #endif /* __PYGI_SIGNAL_CLOSURE_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-source.c0000664000000000000000000001562715074673150015372 0ustar00rootroot/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 1998-2003 James Henstridge * Copyright (C) 2005 Oracle * Copyright (c) 2012 Canonical Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include #include "pygi-type.h" #include "pygboxed.h" #include "pygi-basictype.h" #include "pygi-boxed.h" #include "pygi-info.h" #include "pygi-source.h" typedef struct { GSource source; PyObject *obj; } PyGRealSource; static gboolean source_prepare (GSource *source, gint *timeout) { PyGRealSource *pysource = (PyGRealSource *)source; PyObject *t; gboolean ret = FALSE; gboolean got_err = TRUE; PyGILState_STATE state; state = PyGILState_Ensure (); t = PyObject_CallMethod (pysource->obj, "prepare", NULL); if (t == NULL) { goto bail; } else if (!PyObject_IsTrue (t)) { got_err = FALSE; goto bail; } else if (!PyTuple_Check (t)) { PyErr_SetString ( PyExc_TypeError, "source prepare function must return a tuple or False"); goto bail; } else if (PyTuple_Size (t) != 2) { PyErr_SetString ( PyExc_TypeError, "source prepare function return tuple must be exactly " "2 elements long"); goto bail; } if (!pygi_gboolean_from_py (PyTuple_GET_ITEM (t, 0), &ret)) { ret = FALSE; goto bail; } if (!pygi_gint_from_py (PyTuple_GET_ITEM (t, 1), timeout)) { ret = FALSE; goto bail; } got_err = FALSE; bail: if (got_err) PyErr_Print (); Py_XDECREF (t); PyGILState_Release (state); return ret; } static gboolean source_check (GSource *source) { PyGRealSource *pysource = (PyGRealSource *)source; PyObject *t; gboolean ret; PyGILState_STATE state; state = PyGILState_Ensure (); t = PyObject_CallMethod (pysource->obj, "check", NULL); if (t == NULL) { PyErr_Print (); ret = FALSE; } else { ret = PyObject_IsTrue (t); Py_DECREF (t); } PyGILState_Release (state); return ret; } static gboolean source_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { PyGRealSource *pysource = (PyGRealSource *)source; PyObject *func, *args, *tuple, *t; gboolean ret; PyGILState_STATE state; state = PyGILState_Ensure (); if (callback) { tuple = user_data; func = PyTuple_GetItem (tuple, 0); args = PyTuple_GetItem (tuple, 1); } else { func = Py_None; args = Py_None; } t = PyObject_CallMethod (pysource->obj, "dispatch", "OO", func, args); if (t == NULL) { PyErr_Print (); ret = FALSE; } else { ret = PyObject_IsTrue (t); Py_DECREF (t); } PyGILState_Release (state); return ret; } static GSourceFuncs pyg_source_funcs = { source_prepare, source_check, source_dispatch, NULL, }; /** * _pyglib_destroy_notify: * @user_data: a PyObject pointer. * * A function that can be used as a GDestroyNotify callback that will * call Py_DECREF on the data. */ static void destroy_notify (gpointer user_data) { PyObject *obj = (PyObject *)user_data; PyGILState_STATE state; state = PyGILState_Ensure (); Py_DECREF (obj); PyGILState_Release (state); } static gboolean handler_marshal (gpointer user_data) { PyObject *tuple, *ret; gboolean res; PyGILState_STATE state; g_return_val_if_fail (user_data != NULL, FALSE); state = PyGILState_Ensure (); tuple = (PyObject *)user_data; ret = PyObject_CallObject (PyTuple_GetItem (tuple, 0), PyTuple_GetItem (tuple, 1)); if (!ret) { PyErr_Print (); res = FALSE; } else { res = PyObject_IsTrue (ret); Py_DECREF (ret); } PyGILState_Release (state); return res; } PyObject * pygi_source_set_callback (PyGObject *self_module, PyObject *args) { PyObject *self, *first, *callback, *cbargs = NULL, *data; Py_ssize_t len; len = PyTuple_Size (args); if (len < 2) { PyErr_SetString (PyExc_TypeError, "set_callback requires at least 2 arguments"); return NULL; } first = PySequence_GetSlice (args, 0, 2); if (!PyArg_ParseTuple (first, "OO:set_callback", &self, &callback)) { Py_DECREF (first); return NULL; } Py_DECREF (first); if (!pyg_boxed_check (self, G_TYPE_SOURCE)) { PyErr_SetString (PyExc_TypeError, "first argument is not a GLib.Source"); return NULL; } if (!PyCallable_Check (callback)) { PyErr_SetString (PyExc_TypeError, "second argument not callable"); return NULL; } cbargs = PySequence_GetSlice (args, 2, len); if (cbargs == NULL) return NULL; data = Py_BuildValue ("(ON)", callback, cbargs); if (data == NULL) return NULL; g_source_set_callback (pyg_boxed_get (self, GSource), handler_marshal, data, destroy_notify); Py_RETURN_NONE; } /** * pygi_source_new: * * Wrap the un-bindable g_source_new() and provide wrapper callbacks in the * GSourceFuncs which call back to Python. * * Returns NULL on error and sets an exception. */ PyObject * pygi_source_new (PyObject *self, PyObject *args) { PyGRealSource *source; PyObject *py_type, *boxed; g_assert (args == NULL); py_type = pygi_type_import_by_name ("GLib", "Source"); if (!py_type) return NULL; source = (PyGRealSource *)g_source_new (&pyg_source_funcs, sizeof (PyGRealSource)); /* g_source_new uses malloc, not slices */ boxed = pygi_boxed_new ((PyTypeObject *)py_type, source, TRUE, 0); Py_DECREF (py_type); if (!boxed) { g_source_unref ((GSource *)source); return NULL; } source->obj = boxed; return source->obj; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-source.h0000664000000000000000000000257015074673150015370 0ustar00rootroot/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* * Copyright (c) 2012 Canonical Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #ifndef __PYGI_SOURCE_H__ #define __PYGI_SOURCE_H__ PyObject *pygi_source_new (PyObject *self, PyObject *args); PyObject *pygi_source_set_callback (PyGObject *self, PyObject *args); #endif /* __PYGI_SOURCE_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-struct-marshal.c0000664000000000000000000005132415074673150017035 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-struct-marshal.h" #include "pygboxed.h" #include "pygi-boxed.h" #include "pygi-foreign.h" #include "pygi-info.h" #include "pygi-struct.h" #include "pygi-type.h" #include "pygi-value.h" #include "pygpointer.h" /* * _is_union_member - check to see if the py_arg is actually a member of the * expected C union */ static gboolean _is_union_member (GIRegisteredTypeInfo *interface_info, PyObject *py_arg) { gint i; gint n_fields; GIUnionInfo *union_info; gboolean is_member = FALSE; if (!GI_IS_UNION_INFO (interface_info)) return FALSE; union_info = (GIUnionInfo *)interface_info; n_fields = gi_union_info_get_n_fields (union_info); for (i = 0; i < n_fields; i++) { GIFieldInfo *field_info; GITypeInfo *field_type_info; field_info = gi_union_info_get_field (union_info, i); field_type_info = gi_field_info_get_type_info (field_info); /* we can only check if the members are interfaces */ if (gi_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) { GIBaseInfo *field_iface_info; PyObject *py_type; field_iface_info = gi_type_info_get_interface (field_type_info); py_type = pygi_type_import_by_gi_info (field_iface_info); if (py_type != NULL && PyObject_IsInstance (py_arg, py_type)) { is_member = TRUE; } Py_XDECREF (py_type); gi_base_info_unref (field_iface_info); } gi_base_info_unref ((GIBaseInfo *)field_type_info); gi_base_info_unref ((GIBaseInfo *)field_info); if (is_member) break; } return is_member; } /* * GValue from Python */ /* pygi_arg_gvalue_from_py_marshal: * py_arg: (in): * arg: (out): * transfer: * copy_reference: TRUE if arg should use the pointer reference held by py_arg * when it is already holding a GValue vs. copying the value. */ gboolean pygi_arg_gvalue_from_py_marshal (PyObject *py_arg, GIArgument *arg, GITransfer transfer, gboolean copy_reference) { GValue *value; GType object_type; object_type = pyg_type_from_object_strict ((PyObject *)Py_TYPE (py_arg), FALSE); if (object_type == G_TYPE_INVALID) { PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType"); return FALSE; } /* if already a gvalue, use that, else marshal into gvalue */ if (object_type == G_TYPE_VALUE) { GValue *source_value = pyg_boxed_get (py_arg, GValue); if (copy_reference) { value = source_value; } else { value = g_slice_new0 (GValue); g_value_init (value, G_VALUE_TYPE (source_value)); g_value_copy (source_value, value); } } else { value = g_slice_new0 (GValue); g_value_init (value, object_type); if (pyg_value_from_pyobject_with_error (value, py_arg) < 0) { g_slice_free (GValue, value); return FALSE; } } arg->v_pointer = value; return TRUE; } void pygi_arg_gvalue_from_py_cleanup (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed) { /* Note py_arg can be NULL for hash table which is a bug. */ if (was_processed && py_arg != NULL) { GType py_object_type = pyg_type_from_object_strict ((PyObject *)Py_TYPE (py_arg), FALSE); /* When a GValue was not passed, it means the marshalers created a new * one to pass in, clean this up. */ if (py_object_type != G_TYPE_VALUE) { g_value_unset ((GValue *)data); g_slice_free (GValue, data); } } } /* pygi_arg_gclosure_from_py_marshal: * py_arg: (in): * arg: (out): */ static gboolean pygi_arg_gclosure_from_py_marshal (PyObject *py_arg, GIArgument *arg, GITransfer transfer) { GClosure *closure; GType object_gtype = pyg_type_from_object_strict (py_arg, FALSE); if (!(PyCallable_Check (py_arg) || g_type_is_a (object_gtype, G_TYPE_CLOSURE))) { PyErr_Format (PyExc_TypeError, "Must be callable, not %s", Py_TYPE (py_arg)->tp_name); return FALSE; } if (g_type_is_a (object_gtype, G_TYPE_CLOSURE)) { closure = (GClosure *)pyg_boxed_get (py_arg, void); /* Make sure we own a ref which is held until cleanup. */ if (closure != NULL) { g_closure_ref (closure); } } else { PyObject *functools; PyObject *partial = NULL; functools = PyImport_ImportModule ("functools"); if (functools) { partial = PyObject_GetAttrString (functools, "partial"); Py_DECREF (functools); } if (partial && PyObject_IsInstance (py_arg, partial) > 0 && PyObject_HasAttrString (py_arg, "__gtk_template__")) { PyObject *partial_func; PyObject *partial_args; PyObject *partial_keywords; PyObject *swap_data; partial_func = PyObject_GetAttrString (py_arg, "func"); partial_args = PyObject_GetAttrString (py_arg, "args"); partial_keywords = PyObject_GetAttrString (py_arg, "keywords"); swap_data = PyDict_GetItemString (partial_keywords, "swap_data"); closure = pyg_closure_new (partial_func, partial_args, swap_data); Py_DECREF (partial_func); Py_DECREF (partial_args); Py_DECREF (partial_keywords); g_closure_ref (closure); g_closure_sink (closure); } else { closure = pyg_closure_new (py_arg, NULL, NULL); g_closure_ref (closure); g_closure_sink (closure); } if (partial) { Py_DECREF (partial); } } if (closure == NULL) { PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed"); return FALSE; } /* Add an additional ref when transfering everything to the callee. */ if (transfer == GI_TRANSFER_EVERYTHING) { g_closure_ref (closure); } arg->v_pointer = closure; return TRUE; } static void arg_gclosure_from_py_cleanup (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer cleanup_data, gboolean was_processed) { if (cleanup_data != NULL) { g_closure_unref (cleanup_data); } } /* pygi_arg_struct_from_py_marshal: * * Dispatcher to various sub marshalers */ gboolean pygi_arg_struct_from_py_marshal (PyObject *py_arg, GIArgument *arg, const gchar *arg_name, GIRegisteredTypeInfo *interface_info, GType g_type, PyObject *py_type, GITransfer transfer, gboolean copy_reference, gboolean is_foreign, gboolean is_pointer) { gboolean is_union = FALSE; if (Py_IsNone (py_arg)) { arg->v_pointer = NULL; return TRUE; } /* FIXME: handle this large if statement in the cache * and set the correct marshaller */ if (g_type_is_a (g_type, G_TYPE_CLOSURE)) { return pygi_arg_gclosure_from_py_marshal (py_arg, arg, transfer); } else if (g_type_is_a (g_type, G_TYPE_VALUE)) { return pygi_arg_gvalue_from_py_marshal (py_arg, arg, transfer, copy_reference); } else if (is_foreign) { PyObject *success; success = pygi_struct_foreign_convert_to_g_argument ( py_arg, GI_REGISTERED_TYPE_INFO (interface_info), transfer, arg); return (Py_IsNone (success)); } else if (!PyObject_IsInstance (py_arg, py_type)) { /* first check to see if this is a member of the expected union */ is_union = _is_union_member (GI_REGISTERED_TYPE_INFO (interface_info), py_arg); if (!is_union) { goto type_error; } } if (g_type_is_a (g_type, G_TYPE_BOXED)) { /* Additionally use pyg_type_from_object to pull the stashed __gtype__ * attribute off of the input argument for type checking. This is needed * to work around type discrepancies in cases with aliased (typedef) types. * e.g. GtkAllocation, GdkRectangle. * See: https://bugzilla.gnomethere are .org/show_bug.cgi?id=707140 */ if (is_union || pyg_boxed_check (py_arg, g_type) || g_type_is_a (pyg_type_from_object (py_arg), g_type)) { arg->v_pointer = pyg_boxed_get (py_arg, void); if (transfer == GI_TRANSFER_EVERYTHING) { arg->v_pointer = g_boxed_copy (g_type, arg->v_pointer); } } else { goto type_error; } } else if (g_type_is_a (g_type, G_TYPE_POINTER) || g_type_is_a (g_type, G_TYPE_VARIANT) || g_type == G_TYPE_NONE) { g_warn_if_fail (g_type_is_a (g_type, G_TYPE_VARIANT) || !is_pointer || transfer == GI_TRANSFER_NOTHING); if (g_type_is_a (g_type, G_TYPE_VARIANT) && pyg_type_from_object (py_arg) != G_TYPE_VARIANT) { PyErr_SetString (PyExc_TypeError, "expected GLib.Variant"); return FALSE; } arg->v_pointer = pyg_pointer_get (py_arg, void); if (transfer == GI_TRANSFER_EVERYTHING) { g_variant_ref ((GVariant *)arg->v_pointer); } } else { PyErr_Format (PyExc_NotImplementedError, "structure type '%s' is not supported yet", g_type_name (g_type)); return FALSE; } return TRUE; type_error: { gchar *type_name = _pygi_gi_base_info_get_fullname (GI_BASE_INFO (interface_info)); PyObject *module = PyObject_GetAttrString (py_arg, "__module__"); PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s", arg_name ? arg_name : "self", type_name, module ? PyUnicode_AsUTF8 (module) : "", module ? "." : "", Py_TYPE (py_arg)->tp_name); if (module) Py_DECREF (module); g_free (type_name); return FALSE; } } static gboolean arg_struct_from_py_marshal_adapter (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; gboolean res = pygi_arg_struct_from_py_marshal ( py_arg, arg, arg_cache->arg_name, GI_REGISTERED_TYPE_INFO (iface_cache->interface_info), iface_cache->g_type, iface_cache->py_type, arg_cache->transfer, TRUE, /*copy_reference*/ iface_cache->is_foreign, arg_cache->is_pointer); /* Assume struct marshaling is always a pointer and assign cleanup_data * here rather than passing it further down the chain. */ *cleanup_data = arg->v_pointer; return res; } static void arg_foreign_from_py_cleanup (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed) { if (state->failed && was_processed) { pygi_struct_foreign_release ( GI_BASE_INFO (((PyGIInterfaceCache *)arg_cache)->interface_info), data); } } static PyObject * pygi_arg_struct_to_py_marshaller (GIArgument *arg, GIRegisteredTypeInfo *interface_info, GType g_type, PyObject *py_type, GITransfer transfer, gboolean is_allocated, gboolean is_foreign) { PyObject *py_obj = NULL; if (arg->v_pointer == NULL) { Py_RETURN_NONE; } if (g_type_is_a (g_type, G_TYPE_VALUE)) { py_obj = pyg_value_as_pyobject (arg->v_pointer, is_allocated); } else if (is_foreign) { py_obj = pygi_struct_foreign_convert_from_g_argument ( interface_info, transfer, arg->v_pointer); } else if (g_type_is_a (g_type, G_TYPE_BOXED)) { if (py_type) { py_obj = pygi_boxed_new ( (PyTypeObject *)py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING || is_allocated, is_allocated ? gi_struct_info_get_size (GI_STRUCT_INFO (interface_info)) : 0); } } else if (g_type_is_a (g_type, G_TYPE_POINTER)) { if (py_type == NULL || !PyType_IsSubtype ((PyTypeObject *)py_type, &PyGIStruct_Type)) { g_warn_if_fail (transfer == GI_TRANSFER_NOTHING); py_obj = pyg_pointer_new (g_type, arg->v_pointer); } else { py_obj = pygi_struct_new ((PyTypeObject *)py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING); } } else if (g_type_is_a (g_type, G_TYPE_VARIANT)) { /* Note: sink the variant (add a ref) only if we are not transfered ownership. * GLib.Variant overrides __del__ which will then call "g_variant_unref" for * cleanup in either case. */ if (py_type) { if (transfer == GI_TRANSFER_NOTHING) { g_variant_ref_sink (arg->v_pointer); } py_obj = pygi_struct_new ((PyTypeObject *)py_type, arg->v_pointer, FALSE); } } else if (g_type == G_TYPE_NONE) { if (py_type) { py_obj = pygi_struct_new ( (PyTypeObject *)py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING || is_allocated); } } else { PyErr_Format (PyExc_NotImplementedError, "structure type '%s' is not supported yet", g_type_name (g_type)); } return py_obj; } PyObject * pygi_arg_struct_to_py_marshal (GIArgument *arg, GIRegisteredTypeInfo *interface_info, GType g_type, PyObject *py_type, GITransfer transfer, gboolean is_allocated, gboolean is_foreign) { PyObject *ret = pygi_arg_struct_to_py_marshaller (arg, interface_info, g_type, py_type, transfer, is_allocated, is_foreign); if (ret && PyObject_IsInstance (ret, (PyObject *)&PyGIBoxed_Type) && transfer == GI_TRANSFER_NOTHING) pygi_boxed_copy_in_place ((PyGIBoxed *)ret); return ret; } static PyObject * arg_struct_to_py_marshal_adapter (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; PyObject *ret; ret = pygi_arg_struct_to_py_marshaller ( arg, iface_cache->interface_info, iface_cache->g_type, iface_cache->py_type, arg_cache->transfer, arg_cache->is_caller_allocates, iface_cache->is_foreign); *cleanup_data = ret; return ret; } static void arg_foreign_to_py_cleanup (PyGIInvokeState *state, PyGIArgCache *arg_cache, gpointer cleanup_data, gpointer data, gboolean was_processed) { if (!was_processed && arg_cache->transfer == GI_TRANSFER_EVERYTHING) { pygi_struct_foreign_release ( GI_BASE_INFO (((PyGIInterfaceCache *)arg_cache)->interface_info), data); } } static void arg_boxed_to_py_cleanup (PyGIInvokeState *state, PyGIArgCache *arg_cache, gpointer cleanup_data, gpointer data, gboolean was_processed) { if (arg_cache->transfer == GI_TRANSFER_NOTHING) pygi_boxed_copy_in_place ((PyGIBoxed *)cleanup_data); } static gboolean arg_type_class_from_py_marshal (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data) { GType gtype = pyg_type_from_object (py_arg); if (G_TYPE_IS_CLASSED (gtype)) { arg->v_pointer = g_type_class_ref (gtype); *cleanup_data = arg->v_pointer; return TRUE; } else { PyErr_Format (PyExc_TypeError, "Unable to retrieve a GObject type class from \"%s\".", Py_TYPE (py_arg)->tp_name); return FALSE; } } static void arg_type_class_from_py_cleanup (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed) { if (was_processed) { g_type_class_unref (data); } } static void arg_struct_from_py_setup (PyGIArgCache *arg_cache, GIRegisteredTypeInfo *iface_info, GITransfer transfer) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; if (gi_struct_info_is_gtype_struct ((GIStructInfo *)iface_info)) { arg_cache->from_py_marshaller = arg_type_class_from_py_marshal; /* Since we always add a ref in the marshalling, only unref the * GTypeClass when we don't transfer ownership. */ if (transfer == GI_TRANSFER_NOTHING) { arg_cache->from_py_cleanup = arg_type_class_from_py_cleanup; } } else { arg_cache->from_py_marshaller = arg_struct_from_py_marshal_adapter; if (g_type_is_a (iface_cache->g_type, G_TYPE_CLOSURE)) { arg_cache->from_py_cleanup = arg_gclosure_from_py_cleanup; } else if (iface_cache->g_type == G_TYPE_VALUE) { arg_cache->from_py_cleanup = pygi_arg_gvalue_from_py_cleanup; } else if (iface_cache->is_foreign) { arg_cache->from_py_cleanup = arg_foreign_from_py_cleanup; } } } static void arg_struct_to_py_setup (PyGIArgCache *arg_cache, GIRegisteredTypeInfo *iface_info, GITransfer transfer) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; if (arg_cache->to_py_marshaller == NULL) { arg_cache->to_py_marshaller = arg_struct_to_py_marshal_adapter; } iface_cache->is_foreign = gi_struct_info_is_foreign ((GIStructInfo *)iface_info); if (iface_cache->is_foreign) arg_cache->to_py_cleanup = arg_foreign_to_py_cleanup; else if (!g_type_is_a (iface_cache->g_type, G_TYPE_VALUE) && iface_cache->py_type && g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) arg_cache->to_py_cleanup = arg_boxed_to_py_cleanup; } PyGIArgCache * pygi_arg_struct_new_from_info (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, GIRegisteredTypeInfo *iface_info) { PyGIArgCache *cache = NULL; PyGIInterfaceCache *iface_cache; cache = pygi_arg_interface_new_from_info (type_info, arg_info, transfer, direction, iface_info); if (cache == NULL) return NULL; iface_cache = (PyGIInterfaceCache *)cache; iface_cache->is_foreign = (GI_IS_STRUCT_INFO ((GIBaseInfo *)iface_info)) && (gi_struct_info_is_foreign ((GIStructInfo *)iface_info)); if (direction & PYGI_DIRECTION_FROM_PYTHON) { arg_struct_from_py_setup (cache, iface_info, transfer); } if (direction & PYGI_DIRECTION_TO_PYTHON) { arg_struct_to_py_setup (cache, iface_info, transfer); } return cache; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-struct-marshal.h0000664000000000000000000000473115074673150017042 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2014 Simon Feltman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_STRUCT_MARSHAL_H__ #define __PYGI_STRUCT_MARSHAL_H__ #include #include "pygi-cache.h" G_BEGIN_DECLS PyGIArgCache *pygi_arg_struct_new_from_info ( GITypeInfo *type_info, GIArgInfo *arg_info, /* may be null */ GITransfer transfer, PyGIDirection direction, GIRegisteredTypeInfo *iface_info); gboolean pygi_arg_gvalue_from_py_marshal (PyObject *py_arg, /*in*/ GIArgument *arg, /*out*/ GITransfer transfer, gboolean is_allocated); gboolean pygi_arg_struct_from_py_marshal ( PyObject *py_arg, GIArgument *arg, const gchar *arg_name, GIRegisteredTypeInfo *interface_info, GType g_type, PyObject *py_type, GITransfer transfer, gboolean is_allocated, gboolean is_foreign, gboolean is_pointer); PyObject *pygi_arg_struct_to_py_marshal (GIArgument *arg, GIRegisteredTypeInfo *interface_info, GType g_type, PyObject *py_type, GITransfer transfer, gboolean is_allocated, gboolean is_foreign); /* Needed for hack in pygi-arg-garray.c */ void pygi_arg_gvalue_from_py_cleanup (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed); G_END_DECLS #endif /*__PYGI_STRUCT_MARSHAL_H__*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-struct.c0000664000000000000000000001507215074673150015410 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2009 Simon van der Linden * * pygi-struct.c: wrapper to handle non-registered structures. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include "pygi-struct.h" #include "pygi-foreign.h" #include "pygi-info.h" #include "pygi-type.h" #include "pygi-util.h" #include "pygpointer.h" #include static GIBaseInfo * struct_get_info (PyTypeObject *type) { PyObject *py_info; GIBaseInfo *info = NULL; py_info = PyObject_GetAttrString ((PyObject *)type, "__info__"); if (py_info == NULL) { return NULL; } if (!PyObject_TypeCheck (py_info, &PyGIStructInfo_Type) && !PyObject_TypeCheck (py_info, &PyGIUnionInfo_Type)) { PyErr_Format (PyExc_TypeError, "attribute '__info__' must be %s or %s, not %s", PyGIStructInfo_Type.tp_name, PyGIUnionInfo_Type.tp_name, Py_TYPE (py_info)->tp_name); goto out; } info = ((PyGIBaseInfo *)py_info)->info; gi_base_info_ref (info); out: Py_DECREF (py_info); return info; } static void struct_dealloc (PyGIStruct *self) { GIBaseInfo *info; PyObject *error_type, *error_value, *error_traceback; gboolean have_error = !!PyErr_Occurred (); if (have_error) PyErr_Fetch (&error_type, &error_value, &error_traceback); info = struct_get_info (Py_TYPE (self)); if (info != NULL && gi_struct_info_is_foreign ((GIStructInfo *)info)) { pygi_struct_foreign_release (info, pyg_pointer_get_ptr (self)); } else if (self->free_on_dealloc) { g_free (pyg_pointer_get_ptr (self)); } if (info != NULL) { gi_base_info_unref (info); } if (have_error) PyErr_Restore (error_type, error_value, error_traceback); Py_TYPE (self)->tp_free ((PyObject *)self); } static PyObject * struct_new (PyTypeObject *type, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { NULL }; GIBaseInfo *info; gsize size; gpointer pointer; PyObject *self = NULL; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "", kwlist)) { return NULL; } info = struct_get_info (type); if (info == NULL) { if (PyErr_ExceptionMatches (PyExc_AttributeError)) { PyErr_Format (PyExc_TypeError, "missing introspection information"); } return NULL; } size = gi_struct_info_get_size ((GIStructInfo *)info); if (size == 0) { PyErr_Format (PyExc_TypeError, "struct cannot be created directly; try using a " "constructor, see: help(%s.%s)", gi_base_info_get_namespace (info), gi_base_info_get_name (info)); goto out; } pointer = g_try_malloc0 (size); if (pointer == NULL) { PyErr_NoMemory (); goto out; } self = pygi_struct_new (type, pointer, TRUE); if (self == NULL) { g_free (pointer); } out: gi_base_info_unref (info); return (PyObject *)self; } static int struct_init (PyObject *self, PyObject *args, PyObject *kwargs) { /* Don't call PyGPointer's init, which raises an exception. */ return 0; } PYGI_DEFINE_TYPE ("gi.Struct", PyGIStruct_Type, PyGIStruct); PyObject * pygi_struct_new_from_g_type (GType g_type, gpointer pointer, gboolean free_on_dealloc) { PyGIStruct *self; PyTypeObject *type; type = (PyTypeObject *)pygi_type_import_by_g_type (g_type); if (!type) type = (PyTypeObject *)&PyGIStruct_Type; /* fallback */ if (!PyType_IsSubtype (type, &PyGIStruct_Type)) { PyErr_SetString (PyExc_TypeError, "must be a subtype of gi.Struct"); return NULL; } self = (PyGIStruct *)type->tp_alloc (type, 0); if (self == NULL) { return NULL; } pyg_pointer_set_ptr (self, pointer); ((PyGPointer *)self)->gtype = g_type; self->free_on_dealloc = free_on_dealloc; return (PyObject *)self; } PyObject * pygi_struct_new (PyTypeObject *type, gpointer pointer, gboolean free_on_dealloc) { PyGIStruct *self; GType g_type; if (!PyType_IsSubtype (type, &PyGIStruct_Type)) { PyErr_SetString (PyExc_TypeError, "must be a subtype of gi.Struct"); return NULL; } self = (PyGIStruct *)type->tp_alloc (type, 0); if (self == NULL) { return NULL; } g_type = pyg_type_from_object ((PyObject *)type); pyg_pointer_set_ptr (self, pointer); ((PyGPointer *)self)->gtype = g_type; self->free_on_dealloc = free_on_dealloc; return (PyObject *)self; } static PyObject * struct_repr (PyGIStruct *self) { PyObject *repr; GIBaseInfo *info; PyGPointer *pointer = (PyGPointer *)self; info = struct_get_info (Py_TYPE (self)); if (info == NULL) return NULL; repr = PyUnicode_FromFormat ( "<%s.%s object at %p (%s at %p)>", gi_base_info_get_namespace (info), gi_base_info_get_name (info), self, g_type_name (pointer->gtype), pointer->pointer); gi_base_info_unref (info); return repr; } /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_struct_register_types (PyObject *m) { Py_SET_TYPE (&PyGIStruct_Type, &PyType_Type); g_assert (Py_TYPE (&PyGPointer_Type) != NULL); PyGIStruct_Type.tp_base = &PyGPointer_Type; PyGIStruct_Type.tp_new = (newfunc)struct_new; PyGIStruct_Type.tp_init = (initproc)struct_init; PyGIStruct_Type.tp_dealloc = (destructor)struct_dealloc; PyGIStruct_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); PyGIStruct_Type.tp_repr = (reprfunc)struct_repr; if (PyType_Ready (&PyGIStruct_Type) < 0) return -1; Py_INCREF ((PyObject *)&PyGIStruct_Type); if (PyModule_AddObject (m, "Struct", (PyObject *)&PyGIStruct_Type) < 0) { Py_DECREF ((PyObject *)&PyGIStruct_Type); return -1; } return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-struct.h0000664000000000000000000000262515074673150015415 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2009 Simon van der Linden * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_STRUCT_H__ #define __PYGI_STRUCT_H__ #include #include G_BEGIN_DECLS typedef struct { PyGPointer base; gboolean free_on_dealloc; } PyGIStruct; extern PyTypeObject PyGIStruct_Type; PyObject *pygi_struct_new (PyTypeObject *type, gpointer pointer, gboolean free_on_dealloc); PyObject *pygi_struct_new_from_g_type (GType g_type, gpointer pointer, gboolean free_on_dealloc); int pygi_struct_register_types (PyObject *m); G_END_DECLS #endif /* __PYGI_STRUCT_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-type.c0000664000000000000000000011617215074673150015050 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygobject-object.h" #include "pygboxed.h" #include "pygenum.h" #include "pygflags.h" #include "pygi-basictype.h" #include "pygi-repository.h" #include "pygi-type.h" #include "pygi-util.h" #include "pygi-value.h" #include "pyginterface.h" #include "pygpointer.h" PyObject * pygi_type_import_by_name (const char *namespace_, const char *name) { gchar *module_name; PyObject *py_module; PyObject *py_object; module_name = g_strconcat ("gi.repository.", namespace_, NULL); py_module = PyImport_ImportModule (module_name); g_free (module_name); if (py_module == NULL) { return NULL; } py_object = PyObject_GetAttrString (py_module, name); Py_DECREF (py_module); return py_object; } PyObject * pygi_type_import_by_g_type (GType g_type) { GIRepository *repository; GIBaseInfo *info; PyObject *type; repository = pygi_repository_get_default (); info = gi_repository_find_by_gtype (repository, g_type); if (info == NULL) { return NULL; } type = pygi_type_import_by_gi_info (info); gi_base_info_unref (info); return type; } PyObject * pygi_type_import_by_gi_info (GIBaseInfo *info) { return pygi_type_import_by_name (gi_base_info_get_namespace (info), gi_base_info_get_name (info)); } PyObject * pygi_type_get_from_g_type (GType g_type) { PyObject *py_g_type; PyObject *py_type; py_g_type = pyg_type_wrapper_new (g_type); if (py_g_type == NULL) { return NULL; } py_type = PyObject_GetAttrString (py_g_type, "pytype"); if (Py_IsNone (py_type)) { py_type = pygi_type_import_by_g_type (g_type); } Py_DECREF (py_g_type); return py_type; } /* -------------- __gtype__ objects ---------------------------- */ typedef struct { PyObject_HEAD GType type; } PyGTypeWrapper; PYGI_DEFINE_TYPE ("gobject.GType", PyGTypeWrapper_Type, PyGTypeWrapper); static PyObject * generic_gsize_richcompare (gsize a, gsize b, int op) { PyObject *res; switch (op) { case Py_EQ: res = (a == b) ? Py_True : Py_False; Py_INCREF (res); break; case Py_NE: res = (a != b) ? Py_True : Py_False; Py_INCREF (res); break; case Py_LT: res = (a < b) ? Py_True : Py_False; Py_INCREF (res); break; case Py_LE: res = (a <= b) ? Py_True : Py_False; Py_INCREF (res); break; case Py_GT: res = (a > b) ? Py_True : Py_False; Py_INCREF (res); break; case Py_GE: res = (a >= b) ? Py_True : Py_False; Py_INCREF (res); break; default: res = Py_NewRef (Py_NotImplemented); break; } return res; } static PyObject * pyg_type_wrapper_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE (self) == Py_TYPE (other) && Py_TYPE (self) == &PyGTypeWrapper_Type) return generic_gsize_richcompare (((PyGTypeWrapper *)self)->type, ((PyGTypeWrapper *)other)->type, op); else { Py_RETURN_NOTIMPLEMENTED; } } static long pyg_type_wrapper_hash (PyGTypeWrapper *self) { return (long)self->type; } static PyObject * pyg_type_wrapper_repr (PyGTypeWrapper *self) { char buf[80]; const gchar *name = g_type_name (self->type); g_snprintf (buf, sizeof (buf), "", name ? name : "invalid", (unsigned long int)self->type); return PyUnicode_FromString (buf); } static void pyg_type_wrapper_dealloc (PyGTypeWrapper *self) { PyObject_Free (self); } static GQuark _pyg_type_key (GType type) { GQuark key; if (g_type_is_a (type, G_TYPE_INTERFACE)) { key = pyginterface_type_key; } else if (g_type_is_a (type, G_TYPE_ENUM)) { key = pygenum_class_key; } else if (g_type_is_a (type, G_TYPE_FLAGS)) { key = pygflags_class_key; } else if (g_type_is_a (type, G_TYPE_POINTER)) { key = pygpointer_class_key; } else if (g_type_is_a (type, G_TYPE_BOXED)) { key = pygboxed_type_key; } else { key = pygobject_class_key; } return key; } static PyObject * _wrap_g_type_wrapper__get_pytype (PyGTypeWrapper *self, void *closure) { GQuark key; PyObject *py_type; key = _pyg_type_key (self->type); py_type = g_type_get_qdata (self->type, key); if (!py_type) py_type = Py_None; return Py_NewRef (py_type); } static int _wrap_g_type_wrapper__set_pytype (PyGTypeWrapper *self, PyObject *value, void *closure) { GQuark key; PyObject *py_type; key = _pyg_type_key (self->type); py_type = g_type_get_qdata (self->type, key); Py_CLEAR (py_type); if (Py_IsNone (value)) g_type_set_qdata (self->type, key, NULL); else if (PyType_Check (value)) { Py_INCREF (value); g_type_set_qdata (self->type, key, value); } else { PyErr_SetString (PyExc_TypeError, "Value must be None or a type object"); return -1; } return 0; } static PyObject * _wrap_g_type_wrapper__get_name (PyGTypeWrapper *self, void *closure) { const char *name = g_type_name (self->type); return PyUnicode_FromString (name ? name : "invalid"); } static PyObject * _wrap_g_type_wrapper__get_parent (PyGTypeWrapper *self, void *closure) { return pyg_type_wrapper_new (g_type_parent (self->type)); } static PyObject * _wrap_g_type_wrapper__get_fundamental (PyGTypeWrapper *self, void *closure) { return pyg_type_wrapper_new (g_type_fundamental (self->type)); } static PyObject * _wrap_g_type_wrapper__get_children (PyGTypeWrapper *self, void *closure) { guint n_children, i; GType *children; PyObject *retval; children = g_type_children (self->type, &n_children); retval = PyList_New (n_children); for (i = 0; i < n_children; i++) PyList_SetItem (retval, i, pyg_type_wrapper_new (children[i])); g_free (children); return retval; } static PyObject * _wrap_g_type_wrapper__get_interfaces (PyGTypeWrapper *self, void *closure) { guint n_interfaces, i; GType *interfaces; PyObject *retval; interfaces = g_type_interfaces (self->type, &n_interfaces); retval = PyList_New (n_interfaces); for (i = 0; i < n_interfaces; i++) PyList_SetItem (retval, i, pyg_type_wrapper_new (interfaces[i])); g_free (interfaces); return retval; } static PyObject * _wrap_g_type_wrapper__get_depth (PyGTypeWrapper *self, void *closure) { return pygi_guint_to_py (g_type_depth (self->type)); } static PyGetSetDef _PyGTypeWrapper_getsets[] = { { "pytype", (getter)_wrap_g_type_wrapper__get_pytype, (setter)_wrap_g_type_wrapper__set_pytype }, { "name", (getter)_wrap_g_type_wrapper__get_name, (setter)0 }, { "fundamental", (getter)_wrap_g_type_wrapper__get_fundamental, (setter)0 }, { "parent", (getter)_wrap_g_type_wrapper__get_parent, (setter)0 }, { "children", (getter)_wrap_g_type_wrapper__get_children, (setter)0 }, { "interfaces", (getter)_wrap_g_type_wrapper__get_interfaces, (setter)0 }, { "depth", (getter)_wrap_g_type_wrapper__get_depth, (setter)0 }, { NULL, (getter)0, (setter)0 }, }; static PyObject * _wrap_g_type_is_interface (PyGTypeWrapper *self) { return pygi_gboolean_to_py (G_TYPE_IS_INTERFACE (self->type)); } static PyObject * _wrap_g_type_is_classed (PyGTypeWrapper *self) { return pygi_gboolean_to_py (G_TYPE_IS_CLASSED (self->type)); } static PyObject * _wrap_g_type_is_instantiatable (PyGTypeWrapper *self) { return pygi_gboolean_to_py (G_TYPE_IS_INSTANTIATABLE (self->type)); } static PyObject * _wrap_g_type_is_derivable (PyGTypeWrapper *self) { return pygi_gboolean_to_py (G_TYPE_IS_DERIVABLE (self->type)); } static PyObject * _wrap_g_type_is_deep_derivable (PyGTypeWrapper *self) { return pygi_gboolean_to_py (G_TYPE_IS_DEEP_DERIVABLE (self->type)); } static PyObject * _wrap_g_type_is_abstract (PyGTypeWrapper *self) { return pygi_gboolean_to_py (G_TYPE_IS_ABSTRACT (self->type)); } static PyObject * _wrap_g_type_is_value_abstract (PyGTypeWrapper *self) { return pygi_gboolean_to_py (G_TYPE_IS_VALUE_ABSTRACT (self->type)); } static PyObject * _wrap_g_type_is_value_type (PyGTypeWrapper *self) { return pygi_gboolean_to_py (G_TYPE_IS_VALUE_TYPE (self->type)); } static PyObject * _wrap_g_type_has_value_table (PyGTypeWrapper *self) { return pygi_gboolean_to_py (G_TYPE_HAS_VALUE_TABLE (self->type)); } static PyObject * _wrap_g_type_from_name (PyGTypeWrapper *_, PyObject *args) { char *type_name; GType type; if (!PyArg_ParseTuple (args, "s:GType.from_name", &type_name)) return NULL; type = g_type_from_name (type_name); if (type == 0) { PyErr_SetString (PyExc_RuntimeError, "unknown type name"); return NULL; } return pyg_type_wrapper_new (type); } static PyObject * _wrap_g_type_is_a (PyGTypeWrapper *self, PyObject *args) { PyObject *gparent; GType parent; if (!PyArg_ParseTuple (args, "O:GType.is_a", &gparent)) return NULL; else if ((parent = pyg_type_from_object (gparent)) == 0) return NULL; return pygi_gboolean_to_py (g_type_is_a (self->type, parent)); } static PyMethodDef _PyGTypeWrapper_methods[] = { { "is_interface", (PyCFunction)_wrap_g_type_is_interface, METH_NOARGS }, { "is_classed", (PyCFunction)_wrap_g_type_is_classed, METH_NOARGS }, { "is_instantiatable", (PyCFunction)_wrap_g_type_is_instantiatable, METH_NOARGS }, { "is_derivable", (PyCFunction)_wrap_g_type_is_derivable, METH_NOARGS }, { "is_deep_derivable", (PyCFunction)_wrap_g_type_is_deep_derivable, METH_NOARGS }, { "is_abstract", (PyCFunction)_wrap_g_type_is_abstract, METH_NOARGS }, { "is_value_abstract", (PyCFunction)_wrap_g_type_is_value_abstract, METH_NOARGS }, { "is_value_type", (PyCFunction)_wrap_g_type_is_value_type, METH_NOARGS }, { "has_value_table", (PyCFunction)_wrap_g_type_has_value_table, METH_NOARGS }, { "from_name", (PyCFunction)_wrap_g_type_from_name, METH_VARARGS | METH_STATIC }, { "is_a", (PyCFunction)_wrap_g_type_is_a, METH_VARARGS }, { NULL, 0, 0 }, }; static int pyg_type_wrapper_init (PyGTypeWrapper *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "object", NULL }; PyObject *py_object; GType type; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O:GType.__init__", kwlist, &py_object)) return -1; if (!(type = pyg_type_from_object (py_object))) return -1; self->type = type; return 0; } /** * pyg_type_wrapper_new: * type: a GType * * Creates a Python wrapper for a GType. * * Returns: the Python wrapper. */ PyObject * pyg_type_wrapper_new (GType type) { PyGTypeWrapper *self; g_assert (Py_TYPE (&PyGTypeWrapper_Type) != NULL); self = (PyGTypeWrapper *)PyObject_New (PyGTypeWrapper, &PyGTypeWrapper_Type); if (self == NULL) return NULL; self->type = type; return (PyObject *)self; } /** * pyg_type_from_object_strict: * obj: a Python object * strict: if set to TRUE, raises an exception if it can't perform the * conversion * * converts a python object to a GType. If strict is set, raises an * exception if it can't perform the conversion, otherwise returns * PY_TYPE_OBJECT. * * Returns: the corresponding GType, or 0 on error. */ GType pyg_type_from_object_strict (PyObject *obj, gboolean strict) { PyObject *gtype; GType type; /* NULL check */ if (!obj) { PyErr_SetString (PyExc_TypeError, "can't get type from NULL object"); return 0; } /* map some standard types to primitive GTypes ... */ if (Py_IsNone (obj)) return G_TYPE_NONE; if (PyType_Check (obj)) { PyTypeObject *tp = (PyTypeObject *)obj; if (tp == &PyLong_Type) return G_TYPE_INT; else if (tp == &PyBool_Type) return G_TYPE_BOOLEAN; else if (tp == &PyFloat_Type) return G_TYPE_DOUBLE; else if (tp == &PyUnicode_Type) return G_TYPE_STRING; else if (tp == &PyBaseObject_Type) return PY_TYPE_OBJECT; } if (Py_TYPE (obj) == &PyGTypeWrapper_Type) { return ((PyGTypeWrapper *)obj)->type; } /* handle strings */ if (PyUnicode_Check (obj)) { gchar *name = PyUnicode_AsUTF8 (obj); type = g_type_from_name (name); if (type != 0) { return type; } } /* finally, look for a __gtype__ attribute on the object */ gtype = PyObject_GetAttrString (obj, "__gtype__"); if (gtype) { if (Py_TYPE (gtype) == &PyGTypeWrapper_Type) { type = ((PyGTypeWrapper *)gtype)->type; Py_DECREF (gtype); return type; } Py_DECREF (gtype); } PyErr_Clear (); /* Some API like those that take GValues can hold a python object as * a pointer. This is potentially dangerous becuase everything is * passed in as a PyObject so we can't actually type check it. Only * fallback to PY_TYPE_OBJECT if strict checking is disabled */ if (!strict) return PY_TYPE_OBJECT; PyErr_SetString (PyExc_TypeError, "could not get typecode from object"); return 0; } /** * pyg_type_from_object: * obj: a Python object * * converts a python object to a GType. Raises an exception if it * can't perform the conversion. * * Returns: the corresponding GType, or 0 on error. */ GType pyg_type_from_object (PyObject *obj) { /* Legacy call always defaults to strict type checking */ return pyg_type_from_object_strict (obj, TRUE); } /** * pyg_enum_get_value: * @enum_type: the GType of the flag. * @obj: a Python object representing the flag value * @val: a pointer to the location to store the integer representation of the flag. * * Converts a Python object to the integer equivalent. The conversion * will depend on the type of the Python object. If the object is an * integer, it is passed through directly. If it is a string, it will * be treated as a full or short enum name as defined in the GType. * * Returns: 0 on success or -1 on failure */ gint pyg_enum_get_value (GType enum_type, PyObject *obj, gint *val) { GEnumClass *eclass = NULL; gint res = -1; g_return_val_if_fail (val != NULL, -1); if (!obj) { *val = 0; res = 0; } else if (PyLong_Check (obj)) { if (!pygi_gint_from_py (obj, val)) res = -1; else res = 0; res = pyg_enum_check_type (obj, enum_type); } else if (PyUnicode_Check (obj)) { GEnumValue *info; char *str = PyUnicode_AsUTF8 (obj); if (enum_type != G_TYPE_NONE) eclass = G_ENUM_CLASS (g_type_class_ref (enum_type)); else { PyErr_SetString (PyExc_TypeError, "could not convert string to enum because there " "is no GType associated to look up the value"); res = -1; } info = g_enum_get_value_by_name (eclass, str); g_type_class_unref (eclass); if (!info) info = g_enum_get_value_by_nick (eclass, str); if (info) { *val = info->value; res = 0; } else { PyErr_SetString (PyExc_TypeError, "could not convert string"); res = -1; } } else { PyErr_SetString (PyExc_TypeError, "enum values must be strings or ints"); res = -1; } return res; } /** * pyg_flags_get_value: * @flag_type: the GType of the flag. * @obj: a Python object representing the flag value * @val: a pointer to the location to store the integer representation of the flag. * * Converts a Python object to the integer equivalent. The conversion * will depend on the type of the Python object. If the object is an * integer, it is passed through directly. If it is a string, it will * be treated as a full or short flag name as defined in the GType. * If it is a tuple, then the items are treated as strings and ORed * together. * * Returns: 0 on success or -1 on failure */ gint pyg_flags_get_value (GType flag_type, PyObject *obj, guint *val) { GFlagsClass *fclass = NULL; gint res = -1; g_return_val_if_fail (val != NULL, -1); if (!obj) { *val = 0; res = 0; } else if (PyLong_Check (obj)) { if (pygi_guint_from_py (obj, val)) res = 0; } else if (PyUnicode_Check (obj)) { GFlagsValue *info; char *str = PyUnicode_AsUTF8 (obj); if (flag_type != G_TYPE_NONE) fclass = G_FLAGS_CLASS (g_type_class_ref (flag_type)); else { PyErr_SetString (PyExc_TypeError, "could not convert string to flag because there " "is no GType associated to look up the value"); res = -1; } info = g_flags_get_value_by_name (fclass, str); g_type_class_unref (fclass); if (!info) info = g_flags_get_value_by_nick (fclass, str); if (info) { *val = info->value; res = 0; } else { PyErr_SetString (PyExc_TypeError, "could not convert string"); res = -1; } } else if (PyTuple_Check (obj)) { Py_ssize_t i, len; len = PyTuple_Size (obj); *val = 0; res = 0; if (flag_type != G_TYPE_NONE) fclass = G_FLAGS_CLASS (g_type_class_ref (flag_type)); else { PyErr_SetString (PyExc_TypeError, "could not convert string to flag because there " "is no GType associated to look up the value"); res = -1; } for (i = 0; i < len; i++) { PyObject *item = PyTuple_GetItem (obj, i); char *str = PyUnicode_AsUTF8 (item); GFlagsValue *info = g_flags_get_value_by_name (fclass, str); if (!info) info = g_flags_get_value_by_nick (fclass, str); if (info) { *val |= info->value; } else { PyErr_SetString (PyExc_TypeError, "could not convert string"); res = -1; break; } } g_type_class_unref (fclass); } else { PyErr_SetString ( PyExc_TypeError, "flag values must be strings, ints, longs, or tuples"); res = -1; } return res; } static GQuark pyg_type_marshal_key = 0; static GQuark pyg_type_marshal_helper_key = 0; typedef enum _marshal_helper_data_e marshal_helper_data_e; enum _marshal_helper_data_e { MARSHAL_HELPER_NONE = 0, MARSHAL_HELPER_RETURN_NULL, MARSHAL_HELPER_IMPORT_DONE, }; PyGTypeMarshal * pyg_type_lookup (GType type) { GType ptype = type; PyGTypeMarshal *tm = NULL; marshal_helper_data_e marshal_helper; if (type == G_TYPE_INVALID) return NULL; marshal_helper = GPOINTER_TO_INT (g_type_get_qdata (type, pyg_type_marshal_helper_key)); /* If we called this function before with @type and nothing was found, * return NULL early to not spend time in the loop below */ if (marshal_helper == MARSHAL_HELPER_RETURN_NULL) return NULL; /* Otherwise do recursive type lookup */ do { if (marshal_helper == MARSHAL_HELPER_IMPORT_DONE) pygi_type_import_by_g_type (ptype); if ((tm = g_type_get_qdata (ptype, pyg_type_marshal_key)) != NULL) break; ptype = g_type_parent (ptype); } while (ptype); if (marshal_helper == MARSHAL_HELPER_NONE) { marshal_helper = (tm == NULL) ? MARSHAL_HELPER_RETURN_NULL : MARSHAL_HELPER_IMPORT_DONE; g_type_set_qdata (type, pyg_type_marshal_helper_key, GINT_TO_POINTER (marshal_helper)); } return tm; } /** * pyg_register_gtype_custom: * @gtype: the GType for the new type * @from_func: a function to convert GValues to Python objects * @to_func: a function to convert Python objects to GValues * * In order to handle specific conversion of gboxed types or new * fundamental types, you may use this function to register conversion * handlers. */ void pyg_register_gtype_custom (GType gtype, fromvaluefunc from_func, tovaluefunc to_func) { PyGTypeMarshal *tm; if (!pyg_type_marshal_key) { pyg_type_marshal_key = g_quark_from_static_string ("PyGType::marshal"); pyg_type_marshal_helper_key = g_quark_from_static_string ("PyGType::marshal-helper"); } tm = g_new (PyGTypeMarshal, 1); tm->fromvalue = from_func; tm->tovalue = to_func; g_type_set_qdata (gtype, pyg_type_marshal_key, tm); } /* -------------- PyGClosure ----------------- */ static void pyg_closure_invalidate (gpointer data, GClosure *closure) { PyGClosure *pc = (PyGClosure *)closure; PyGILState_STATE state; state = PyGILState_Ensure (); Py_XDECREF (pc->callback); Py_XDECREF (pc->extra_args); Py_XDECREF (pc->swap_data); PyGILState_Release (state); pc->callback = NULL; pc->extra_args = NULL; pc->swap_data = NULL; } static void pyg_closure_marshal (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data) { PyGILState_STATE state; PyGClosure *pc = (PyGClosure *)closure; PyObject *params, *ret; guint i; state = PyGILState_Ensure (); /* construct Python tuple for the parameter values */ params = PyTuple_New (n_param_values); for (i = 0; i < n_param_values; i++) { /* swap in a different initial data for connect_object() */ if (i == 0 && G_CCLOSURE_SWAP_DATA (closure)) { g_return_if_fail (pc->swap_data != NULL); Py_INCREF (pc->swap_data); PyTuple_SetItem (params, 0, pc->swap_data); } else { PyObject *item = pyg_value_as_pyobject (¶m_values[i], FALSE); /* error condition */ if (!item) { if (!PyErr_Occurred ()) PyErr_SetString ( PyExc_TypeError, "can't convert parameter to desired type"); if (pc->exception_handler) pc->exception_handler (return_value, n_param_values, param_values); else PyErr_Print (); goto out; } PyTuple_SetItem (params, i, item); } } /* params passed to function may have extra arguments */ if (pc->extra_args) { PyObject *tuple = params; params = PySequence_Concat (tuple, pc->extra_args); Py_DECREF (tuple); } ret = PyObject_CallObject (pc->callback, params); if (ret == NULL) { if (pc->exception_handler) pc->exception_handler (return_value, n_param_values, param_values); else PyErr_Print (); goto out; } if (G_IS_VALUE (return_value) && pyg_value_from_pyobject (return_value, ret) != 0) { /* If we already have an exception set, use that, otherwise set a * generic one */ if (!PyErr_Occurred ()) PyErr_SetString (PyExc_TypeError, "can't convert return value to desired type"); if (pc->exception_handler) pc->exception_handler (return_value, n_param_values, param_values); else PyErr_Print (); } Py_DECREF (ret); out: Py_DECREF (params); PyGILState_Release (state); } /** * pyg_closure_new: * callback: a Python callable object * extra_args: a tuple of extra arguments, or None/NULL. * swap_data: an alternative python object to pass first. * * Creates a GClosure wrapping a Python callable and optionally a set * of additional function arguments. This is needed to attach python * handlers to signals, for instance. * * Returns: the new closure. */ GClosure * pyg_closure_new (PyObject *callback, PyObject *extra_args, PyObject *swap_data) { GClosure *closure; g_return_val_if_fail (callback != NULL, NULL); closure = g_closure_new_simple (sizeof (PyGClosure), NULL); g_closure_add_invalidate_notifier (closure, NULL, pyg_closure_invalidate); g_closure_set_marshal (closure, pyg_closure_marshal); Py_INCREF (callback); ((PyGClosure *)closure)->callback = callback; if (extra_args && !Py_IsNone (extra_args)) { Py_INCREF (extra_args); if (!PyTuple_Check (extra_args)) { PyObject *tmp = PyTuple_New (1); PyTuple_SetItem (tmp, 0, extra_args); extra_args = tmp; } ((PyGClosure *)closure)->extra_args = extra_args; } if (swap_data) { Py_INCREF (swap_data); ((PyGClosure *)closure)->swap_data = swap_data; closure->derivative_flag = TRUE; } return closure; } /** * pyg_closure_set_exception_handler: * @closure: a closure created with pyg_closure_new() * @handler: the handler to call when an exception occurs or NULL for none * * Sets the handler to call when an exception occurs during closure invocation. * The handler is responsible for providing a proper return value to the * closure invocation. If @handler is %NULL, the default handler will be used. * The default handler prints the exception to stderr and doesn't touch the * closure's return value. */ void pyg_closure_set_exception_handler (GClosure *closure, PyClosureExceptionHandler handler) { PyGClosure *pygclosure; g_return_if_fail (closure != NULL); pygclosure = (PyGClosure *)closure; pygclosure->exception_handler = handler; } /* -------------- PySignalClassClosure ----------------- */ /* a closure used for the `class closure' of a signal. As this gets * all the info from the first argument to the closure and the * invocation hint, we can have a single closure that handles all * class closure cases. We call a method by the name of the signal * with "do_" prepended. * * We also remove the first argument from the * param list, as it is * the instance object, which is passed * implicitly to the method * object. */ static void pyg_signal_class_closure_marshal (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data) { PyGILState_STATE state; GObject *object; PyObject *object_wrapper; GSignalInvocationHint *hint = (GSignalInvocationHint *)invocation_hint; gchar *method_name, *tmp; PyObject *method; PyObject *params, *ret; Py_ssize_t py_len; guint i, len; state = PyGILState_Ensure (); g_return_if_fail (invocation_hint != NULL); /* get the object passed as the first argument to the closure */ object = g_value_get_object (¶m_values[0]); g_return_if_fail (object != NULL && G_IS_OBJECT (object)); /* get the wrapper for this object */ object_wrapper = pygobject_new (object); g_return_if_fail (object_wrapper != NULL); /* construct method name for this class closure */ method_name = g_strconcat ("do_", g_signal_name (hint->signal_id), NULL); /* convert dashes to underscores. For some reason, g_signal_name * seems to convert all the underscores in the signal name to dashes??? */ for (tmp = method_name; *tmp != '\0'; tmp++) if (*tmp == '-') *tmp = '_'; method = PyObject_GetAttrString (object_wrapper, method_name); g_free (method_name); if (!method) { PyErr_Clear (); Py_DECREF (object_wrapper); PyGILState_Release (state); return; } Py_DECREF (object_wrapper); /* construct Python tuple for the parameter values; don't copy boxed values initially because we'll check after the call to see if a copy is needed. */ params = PyTuple_New (n_param_values - 1); for (i = 1; i < n_param_values; i++) { PyObject *item = pyg_value_as_pyobject (¶m_values[i], FALSE); /* error condition */ if (!item) { Py_DECREF (params); PyGILState_Release (state); return; } PyTuple_SetItem (params, i - 1, item); } ret = PyObject_CallObject (method, params); /* Copy boxed values if others ref them, this needs to be done regardless of exception status. */ py_len = PyTuple_Size (params); len = (guint)py_len; for (i = 0; i < len; i++) { PyObject *item = PyTuple_GetItem (params, i); if (item != NULL && PyObject_TypeCheck (item, &PyGBoxed_Type) && Py_REFCNT (item) != 1) { PyGBoxed *boxed_item = (PyGBoxed *)item; if (!boxed_item->free_on_dealloc) { gpointer boxed_ptr = pyg_boxed_get_ptr (boxed_item); pyg_boxed_set_ptr ( boxed_item, g_boxed_copy (boxed_item->gtype, boxed_ptr)); boxed_item->free_on_dealloc = TRUE; } } } if (ret == NULL) { PyErr_Print (); Py_DECREF (method); Py_DECREF (params); PyGILState_Release (state); return; } Py_DECREF (method); Py_DECREF (params); if (G_IS_VALUE (return_value)) pyg_value_from_pyobject (return_value, ret); Py_DECREF (ret); PyGILState_Release (state); } /** * pyg_signal_class_closure_get: * * Returns the GClosure used for the class closure of signals. When * called, it will invoke the method do_signalname (for the signal * "signalname"). * * Returns: the closure. */ GClosure * pyg_signal_class_closure_get (void) { static GClosure *closure; if (closure == NULL) { closure = g_closure_new_simple (sizeof (GClosure), NULL); g_closure_set_marshal (closure, pyg_signal_class_closure_marshal); g_closure_ref (closure); g_closure_sink (closure); } return closure; } /* ----- __doc__ descriptor for GObject and GInterface ----- */ static void object_doc_dealloc (PyObject *self) { PyObject_Free (self); } /* append information about signals of a particular gtype */ static void add_signal_docs (GType gtype, GString *string) { GTypeClass *class = NULL; guint *signal_ids, n_ids = 0, i; if (G_TYPE_IS_CLASSED (gtype)) class = g_type_class_ref (gtype); signal_ids = g_signal_list_ids (gtype, &n_ids); if (n_ids > 0) { g_string_append_printf (string, "Signals from %s:\n", g_type_name (gtype)); for (i = 0; i < n_ids; i++) { GSignalQuery query; guint j; g_signal_query (signal_ids[i], &query); g_string_append (string, " "); g_string_append (string, query.signal_name); g_string_append (string, " ("); for (j = 0; j < query.n_params; j++) { g_string_append (string, g_type_name (query.param_types[j])); if (j != query.n_params - 1) g_string_append (string, ", "); } g_string_append (string, ")"); if (query.return_type && query.return_type != G_TYPE_NONE) { g_string_append (string, " -> "); g_string_append (string, g_type_name (query.return_type)); } g_string_append (string, "\n"); } g_free (signal_ids); g_string_append (string, "\n"); } if (class) g_type_class_unref (class); } static void add_property_docs (GType gtype, GString *string) { GObjectClass *class; GParamSpec **props; guint n_props = 0, i; gboolean has_prop = FALSE; const gchar *blurb = NULL; class = g_type_class_ref (gtype); props = g_object_class_list_properties (class, &n_props); for (i = 0; i < n_props; i++) { if (props[i]->owner_type != gtype) continue; /* these are from a parent type */ /* print out the heading first */ if (!has_prop) { g_string_append_printf (string, "Properties from %s:\n", g_type_name (gtype)); has_prop = TRUE; } g_string_append_printf (string, " %s -> %s: %s\n", g_param_spec_get_name (props[i]), g_type_name (props[i]->value_type), g_param_spec_get_nick (props[i])); /* g_string_append_printf crashes on win32 if the third argument is NULL. */ blurb = g_param_spec_get_blurb (props[i]); if (blurb) g_string_append_printf (string, " %s\n", blurb); } g_free (props); if (has_prop) g_string_append (string, "\n"); g_type_class_unref (class); } static PyObject * object_doc_descr_get (PyObject *self, PyObject *obj, PyObject *type) { GType gtype = 0; GString *string; PyObject *pystring; if (obj && pygobject_check (obj, &PyGObject_Type)) { gtype = G_OBJECT_TYPE (pygobject_get (obj)); if (!gtype) PyErr_SetString (PyExc_RuntimeError, "could not get object type"); } else { gtype = pyg_type_from_object (type); } if (!gtype) return NULL; string = g_string_new_len (NULL, 512); if (g_type_is_a (gtype, G_TYPE_INTERFACE)) g_string_append_printf (string, "Interface %s\n\n", g_type_name (gtype)); else if (g_type_is_a (gtype, G_TYPE_OBJECT)) g_string_append_printf (string, "Object %s\n\n", g_type_name (gtype)); else g_string_append_printf (string, "%s\n\n", g_type_name (gtype)); if (((PyTypeObject *)type)->tp_doc) g_string_append_printf (string, "%s\n\n", ((PyTypeObject *)type)->tp_doc); if (g_type_is_a (gtype, G_TYPE_OBJECT)) { GType parent = G_TYPE_OBJECT; GArray *parents = g_array_new (FALSE, FALSE, sizeof (GType)); int iparent; while (parent) { g_array_append_val (parents, parent); parent = g_type_next_base (gtype, parent); } for (iparent = parents->len - 1; iparent >= 0; --iparent) { GType *interfaces; guint n_interfaces, i; parent = g_array_index (parents, GType, iparent); add_signal_docs (parent, string); add_property_docs (parent, string); /* add docs for implemented interfaces */ interfaces = g_type_interfaces (parent, &n_interfaces); for (i = 0; i < n_interfaces; i++) add_signal_docs (interfaces[i], string); g_free (interfaces); } g_array_free (parents, TRUE); } pystring = PyUnicode_FromStringAndSize (string->str, string->len); g_string_free (string, TRUE); return pystring; } PYGI_DEFINE_TYPE ("gobject.GObject.__doc__", PyGObjectDoc_Type, PyObject); /** * pyg_object_descr_doc_get: * * Returns an object intended to be the __doc__ attribute of GObject * wrappers. When read in the context of the object it will return * some documentation about the signals and properties of the object. * * Returns: the descriptor. */ PyObject * pyg_object_descr_doc_get (void) { static PyObject *doc_descr = NULL; if (!doc_descr) { Py_SET_TYPE (&PyGObjectDoc_Type, &PyType_Type); if (PyType_Ready (&PyGObjectDoc_Type)) return NULL; doc_descr = PyObject_New (PyObject, &PyGObjectDoc_Type); if (doc_descr == NULL) return NULL; } return doc_descr; } /** * pyg_pyobj_to_unichar_conv: * * Converts PyObject value to a unichar and write result to memory * pointed to by ptr. Follows the calling convention of a ParseArgs * converter (O& format specifier) so it may be used to convert function * arguments. * * Returns: 1 if the conversion succeeds and 0 otherwise. If the conversion * did not succeesd, a Python exception is raised */ int pyg_pyobj_to_unichar_conv (PyObject *py_obj, void *ptr) { if (!pygi_gunichar_from_py (py_obj, ptr)) return 0; return 1; } gboolean pyg_gtype_is_custom (GType gtype) { return g_type_get_qdata (gtype, pygobject_custom_key) != NULL; } static PyObject * strv_from_gvalue (const GValue *value) { gchar **argv; PyObject *py_argv; gsize i; argv = (gchar **)g_value_get_boxed (value); py_argv = PyList_New (0); for (i = 0; argv && argv[i]; i++) { int res; PyObject *item = pygi_utf8_to_py (argv[i]); if (item == NULL) { Py_DECREF (py_argv); return NULL; } res = PyList_Append (py_argv, item); Py_DECREF (item); if (res == -1) { Py_DECREF (py_argv); return NULL; } } return py_argv; } static int strv_to_gvalue (GValue *value, PyObject *obj) { Py_ssize_t argc, i; gchar **argv; if (!(PyTuple_Check (obj) || PyList_Check (obj))) return -1; argc = PySequence_Length (obj); argv = g_new (gchar *, argc + 1); for (i = 0; i < argc; ++i) { PyObject *item = PySequence_Fast_GET_ITEM (obj, i); if (!pygi_utf8_from_py (item, &(argv[i]))) goto error; } argv[i] = NULL; g_value_take_boxed (value, argv); return 0; error: for (i = i - 1; i >= 0; i--) { g_free (argv[i]); } g_free (argv); return -1; } /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_type_register_types (PyObject *d) { PyGTypeWrapper_Type.tp_dealloc = (destructor)pyg_type_wrapper_dealloc; PyGTypeWrapper_Type.tp_richcompare = pyg_type_wrapper_richcompare; PyGTypeWrapper_Type.tp_repr = (reprfunc)pyg_type_wrapper_repr; PyGTypeWrapper_Type.tp_hash = (hashfunc)pyg_type_wrapper_hash; PyGTypeWrapper_Type.tp_flags = Py_TPFLAGS_DEFAULT; PyGTypeWrapper_Type.tp_methods = _PyGTypeWrapper_methods; PyGTypeWrapper_Type.tp_getset = _PyGTypeWrapper_getsets; PyGTypeWrapper_Type.tp_init = (initproc)pyg_type_wrapper_init; PyGTypeWrapper_Type.tp_alloc = PyType_GenericAlloc; PyGTypeWrapper_Type.tp_new = PyType_GenericNew; if (PyType_Ready (&PyGTypeWrapper_Type)) return -1; PyDict_SetItemString (d, "GType", (PyObject *)&PyGTypeWrapper_Type); /* This type lazily registered in pyg_object_descr_doc_get */ PyGObjectDoc_Type.tp_dealloc = (destructor)object_doc_dealloc; PyGObjectDoc_Type.tp_flags = Py_TPFLAGS_DEFAULT; PyGObjectDoc_Type.tp_descr_get = (descrgetfunc)object_doc_descr_get; pyg_register_gtype_custom (G_TYPE_STRV, strv_from_gvalue, strv_to_gvalue); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-type.h0000664000000000000000000000457315074673150015056 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * pyginterface.c: wrapper for the gobject library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_TYPE_H__ #define __PYGI_TYPE_H__ #include #include #include #include "pygobject-internal.h" extern PyTypeObject PyGTypeWrapper_Type; typedef PyObject *(*fromvaluefunc) (const GValue *value); typedef int (*tovaluefunc) (GValue *value, PyObject *obj); typedef struct { fromvaluefunc fromvalue; tovaluefunc tovalue; } PyGTypeMarshal; PyGTypeMarshal *pyg_type_lookup (GType type); gboolean pyg_gtype_is_custom (GType gtype); void pyg_register_gtype_custom (GType gtype, fromvaluefunc from_func, tovaluefunc to_func); int pygi_type_register_types (PyObject *d); PyObject *pyg_object_descr_doc_get (void); PyObject *pyg_type_wrapper_new (GType type); GType pyg_type_from_object_strict (PyObject *obj, gboolean strict); GType pyg_type_from_object (PyObject *obj); int pyg_pyobj_to_unichar_conv (PyObject *py_obj, void *ptr); GClosure *pyg_closure_new (PyObject *callback, PyObject *extra_args, PyObject *swap_data); GClosure *pyg_signal_class_closure_get (void); void pyg_closure_set_exception_handler (GClosure *closure, PyClosureExceptionHandler handler); PyObject *pygi_type_import_by_g_type (GType g_type); PyObject *pygi_type_import_by_name (const char *namespace_, const char *name); PyObject *pygi_type_import_by_gi_info (GIBaseInfo *info); PyObject *pygi_type_get_from_g_type (GType g_type); #endif /* __PYGI_TYPE_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-util.c0000664000000000000000000000733215074673150015041 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-util.h" gboolean pygi_guint_from_pyssize (Py_ssize_t pyval, guint *result) { if (pyval < 0) { PyErr_SetString (PyExc_ValueError, "< 0"); return FALSE; } else if (G_MAXUINT < PY_SSIZE_T_MAX && pyval > (Py_ssize_t)G_MAXUINT) { PyErr_SetString (PyExc_ValueError, "too large"); return FALSE; } *result = (guint)pyval; return TRUE; } PyObject * pyg_integer_richcompare (PyObject *v, PyObject *w, int op) { PyObject *result; gboolean t; switch (op) { case Py_EQ: t = PyLong_AS_LONG (v) == PyLong_AS_LONG (w); break; case Py_NE: t = PyLong_AS_LONG (v) != PyLong_AS_LONG (w); break; case Py_LE: t = PyLong_AS_LONG (v) <= PyLong_AS_LONG (w); break; case Py_GE: t = PyLong_AS_LONG (v) >= PyLong_AS_LONG (w); break; case Py_LT: t = PyLong_AS_LONG (v) < PyLong_AS_LONG (w); break; case Py_GT: t = PyLong_AS_LONG (v) > PyLong_AS_LONG (w); break; default: g_assert_not_reached (); } result = t ? Py_True : Py_False; return Py_NewRef (result); } PyObject * pyg_ptr_richcompare (void *a, void *b, int op) { PyObject *res; switch (op) { case Py_EQ: res = (a == b) ? Py_True : Py_False; break; case Py_NE: res = (a != b) ? Py_True : Py_False; break; case Py_LT: res = (a < b) ? Py_True : Py_False; break; case Py_LE: res = (a <= b) ? Py_True : Py_False; break; case Py_GT: res = (a > b) ? Py_True : Py_False; break; case Py_GE: res = (a >= b) ? Py_True : Py_False; break; default: res = Py_NotImplemented; break; } return Py_NewRef (res); } /** * pyg_constant_strip_prefix: * @name: the constant name. * @strip_prefix: the prefix to strip. * * Advances the pointer @name by strlen(@strip_prefix) characters. If * the resulting name does not start with a letter or underscore, the * @name pointer will be rewound. This is to ensure that the * resulting name is a valid identifier. Hence the returned string is * a pointer into the string @name. * * Returns: the stripped constant name. */ const gchar * pyg_constant_strip_prefix (const gchar *name, const gchar *strip_prefix) { size_t prefix_len, i; prefix_len = strlen (strip_prefix); /* Check so name starts with strip_prefix, if it doesn't: * return the rest of the part which doesn't match */ for (i = 0; i < prefix_len; i++) { if (name[i] != strip_prefix[i] && name[i] != '_') { return &name[i]; } } /* strip off prefix from value name, while keeping it a valid * identifier */ for (i = prefix_len + 1; i > 0; i--) { if (g_ascii_isalpha (name[i - 1]) || name[i - 1] == '_') { return &name[i - 1]; } } return name; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-util.h0000664000000000000000000000550315074673150015044 0ustar00rootroot#ifndef __PYGI_UTIL_H__ #define __PYGI_UTIL_H__ #include #include G_BEGIN_DECLS PyObject *pyg_integer_richcompare (PyObject *v, PyObject *w, int op); PyObject *pyg_ptr_richcompare (void *a, void *b, int op); const gchar *pyg_constant_strip_prefix (const gchar *name, const gchar *strip_prefix); gboolean pygi_guint_from_pyssize (Py_ssize_t pyval, guint *result); #if PY_VERSION_HEX < 0x030900A4 #define Py_SET_TYPE(obj, type) ((Py_TYPE (obj) = (type)), (void)0) #endif #if PY_VERSION_HEX >= 0x03080000 #define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_BEGIN (op, dealloc) #define CPy_TRASHCAN_END(op) Py_TRASHCAN_END #else #define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_SAFE_BEGIN (op) #define CPy_TRASHCAN_END(op) Py_TRASHCAN_SAFE_END (op) #endif #define PYGI_DEFINE_TYPE(typename, symbol, csymbol) \ PyTypeObject symbol = { PyVarObject_HEAD_INIT (NULL, 0) typename, \ sizeof (csymbol) }; #define _PyGI_ERROR_PREFIX(format, ...) \ G_STMT_START \ { \ PyObject *py_error_prefix; \ py_error_prefix = PyUnicode_FromFormat (format, ##__VA_ARGS__); \ if (py_error_prefix != NULL) { \ PyObject *py_error_type, *py_error_value, *py_error_traceback; \ PyErr_Fetch (&py_error_type, &py_error_value, \ &py_error_traceback); \ if (PyUnicode_Check (py_error_value)) { \ PyObject *new; \ new = PyUnicode_Concat (py_error_prefix, py_error_value); \ Py_DECREF (py_error_value); \ if (new != NULL) { \ py_error_value = new; \ } \ } \ PyErr_Restore (py_error_type, py_error_value, \ py_error_traceback); \ Py_DECREF (py_error_prefix); \ } \ } \ G_STMT_END G_END_DECLS #endif /* __PYGI_UTIL_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-value.c0000664000000000000000000007436215074673150015207 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "pygi-value.h" #include "pygboxed.h" #include "pygenum.h" #include "pygflags.h" #include "pygi-basictype.h" #include "pygi-fundamental.h" #include "pygi-repository.h" #include "pygi-struct.h" #include "pygi-type.h" #include "pygobject-object.h" #include "pygpointer.h" /* glib 2.62 has started to print warnings for these which can't be disabled selectively, so just copy them here */ #define PYGI_TYPE_VALUE_ARRAY (g_value_array_get_type ()) #define PYGI_IS_PARAM_SPEC_VALUE_ARRAY(pspec) \ (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), PYGI_TYPE_VALUE_ARRAY)) #define PYGI_PARAM_SPEC_VALUE_ARRAY(pspec) \ (G_TYPE_CHECK_INSTANCE_CAST ((pspec), g_param_spec_types[18], \ GParamSpecValueArray)) GIArgument _pygi_argument_from_g_value (const GValue *value, GITypeInfo *type_info) { GIArgument arg = { 0, }; GITypeTag type_tag = gi_type_info_get_tag (type_info); /* For the long handling: long can be equivalent to int32 or int64, depending on the architecture, but gi doesn't tell us (and same for ulong) */ switch (type_tag) { case GI_TYPE_TAG_BOOLEAN: arg.v_boolean = g_value_get_boolean (value); break; case GI_TYPE_TAG_INT8: arg.v_int8 = g_value_get_schar (value); break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_INT32: if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG)) arg.v_int32 = (gint32)g_value_get_long (value); else arg.v_int32 = (gint32)g_value_get_int (value); break; case GI_TYPE_TAG_INT64: if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG)) arg.v_int64 = g_value_get_long (value); else arg.v_int64 = g_value_get_int64 (value); break; case GI_TYPE_TAG_UINT8: arg.v_uint8 = g_value_get_uchar (value); break; case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_UINT32: if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG)) arg.v_uint32 = (guint32)g_value_get_ulong (value); else arg.v_uint32 = (guint32)g_value_get_uint (value); break; case GI_TYPE_TAG_UINT64: if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG)) arg.v_uint64 = g_value_get_ulong (value); else arg.v_uint64 = g_value_get_uint64 (value); break; case GI_TYPE_TAG_UNICHAR: arg.v_uint32 = g_value_get_schar (value); break; case GI_TYPE_TAG_FLOAT: arg.v_float = g_value_get_float (value); break; case GI_TYPE_TAG_DOUBLE: arg.v_double = g_value_get_double (value); break; case GI_TYPE_TAG_GTYPE: arg.v_size = g_value_get_gtype (value); break; case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: /* Callers are responsible for ensuring the GValue stays alive * long enough for the string to be copied. */ arg.v_string = (char *)g_value_get_string (value); break; case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_ARRAY: case GI_TYPE_TAG_GHASH: if (G_VALUE_HOLDS_BOXED (value)) arg.v_pointer = g_value_get_boxed (value); else /* e. g. GSettings::change-event */ arg.v_pointer = g_value_get_pointer (value); break; case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *info; info = gi_type_info_get_interface (type_info); if (GI_IS_FLAGS_INFO (info)) { /* Check flags before enums: flags are a subtype of enum. */ arg.v_uint = g_value_get_flags (value); } else if (GI_IS_ENUM_INFO (info)) { arg.v_int = g_value_get_enum (value); } else if (GI_IS_INTERFACE_INFO (info) || GI_IS_OBJECT_INFO (info)) { if (G_VALUE_HOLDS_PARAM (value)) arg.v_pointer = g_value_get_param (value); else if (G_VALUE_HOLDS_OBJECT (value)) arg.v_pointer = g_value_get_object (value); else arg.v_pointer = pygi_fundamental_from_value (value); } else if (GI_IS_STRUCT_INFO (info) || GI_IS_UNION_INFO (info)) { if (G_VALUE_HOLDS (value, G_TYPE_BOXED)) { arg.v_pointer = g_value_get_boxed (value); } else if (G_VALUE_HOLDS (value, G_TYPE_VARIANT)) { arg.v_pointer = g_value_get_variant (value); } else if (G_VALUE_HOLDS (value, G_TYPE_POINTER)) { arg.v_pointer = g_value_get_pointer (value); } else { PyErr_Format ( PyExc_NotImplementedError, "Converting GValue's of type '%s' is not implemented.", g_type_name (G_VALUE_TYPE (value))); } } else { PyErr_Format ( PyExc_NotImplementedError, "Converting GValue's of type '%s' is not implemented.", g_type_name (G_TYPE_FROM_INSTANCE (info))); } gi_base_info_unref (info); break; } case GI_TYPE_TAG_ERROR: arg.v_pointer = g_value_get_boxed (value); break; case GI_TYPE_TAG_VOID: arg.v_pointer = g_value_get_pointer (value); break; default: break; } return arg; } /* Ignore g_value_array deprecations. Although they are deprecated, * we still need to support the marshaling of them in PyGObject. */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS static int pyg_value_array_from_pyobject (GValue *value, PyObject *obj, const GParamSpecValueArray *pspec) { Py_ssize_t seq_len; GValueArray *value_array; guint len, i; seq_len = PySequence_Length (obj); if (seq_len == -1) { PyErr_Clear (); return -1; } len = (guint)seq_len; if (pspec && pspec->fixed_n_elements > 0 && len != pspec->fixed_n_elements) return -1; value_array = g_value_array_new (len); for (i = 0; i < len; ++i) { PyObject *item = PySequence_GetItem (obj, i); GType type; if (!item) { PyErr_Clear (); g_value_array_free (value_array); return -1; } if (pspec && pspec->element_spec) type = G_PARAM_SPEC_VALUE_TYPE (pspec->element_spec); else if (Py_IsNone (item)) type = G_TYPE_POINTER; /* store None as NULL */ else { type = pyg_type_from_object ((PyObject *)Py_TYPE (item)); if (!type) { PyErr_Clear (); g_value_array_free (value_array); Py_DECREF (item); return -1; } } if (type == G_TYPE_VALUE) { const GValue *item_value = pyg_boxed_get (item, GValue); g_value_array_append (value_array, item_value); } else { GValue item_value = { 0, }; int status; g_value_init (&item_value, type); status = (pspec && pspec->element_spec) ? pyg_param_gvalue_from_pyobject (&item_value, item, pspec->element_spec) : pyg_value_from_pyobject (&item_value, item); Py_DECREF (item); if (status == -1) { g_value_array_free (value_array); g_value_unset (&item_value); return -1; } g_value_array_append (value_array, &item_value); g_value_unset (&item_value); } } g_value_take_boxed (value, value_array); return 0; } G_GNUC_END_IGNORE_DEPRECATIONS static int pyg_array_from_pyobject (GValue *value, PyObject *obj) { Py_ssize_t len, i; GArray *array; len = PySequence_Length (obj); if (len == -1) { PyErr_Clear (); return -1; } array = g_array_new (FALSE, TRUE, sizeof (GValue)); for (i = 0; i < len; ++i) { PyObject *item = PySequence_GetItem (obj, i); GType type; GValue item_value = { 0, }; int status; if (!item) { PyErr_Clear (); g_array_free (array, FALSE); return -1; } if (Py_IsNone (item)) type = G_TYPE_POINTER; /* store None as NULL */ else { type = pyg_type_from_object ((PyObject *)Py_TYPE (item)); if (!type) { PyErr_Clear (); g_array_free (array, FALSE); Py_DECREF (item); return -1; } } g_value_init (&item_value, type); status = pyg_value_from_pyobject (&item_value, item); Py_DECREF (item); if (status == -1) { g_array_free (array, FALSE); g_value_unset (&item_value); return -1; } g_array_append_val (array, item_value); } g_value_take_boxed (value, array); return 0; } /** * pyg_value_from_pyobject_with_error: * @value: the GValue object to store the converted value in. * @obj: the Python object to convert. * * This function converts a Python object and stores the result in a * GValue. The GValue must be initialised in advance with * g_value_init(). If the Python object can't be converted to the * type of the GValue, then an error is returned. * * Returns: 0 on success, -1 on error. */ int pyg_value_from_pyobject_with_error (GValue *value, PyObject *obj) { GType value_type = G_VALUE_TYPE (value); switch (G_TYPE_FUNDAMENTAL (value_type)) { case G_TYPE_INTERFACE: /* we only handle interface types that have a GObject prereq */ if (g_type_is_a (value_type, G_TYPE_OBJECT)) { if (Py_IsNone (obj)) g_value_set_object (value, NULL); else { if (!PyObject_TypeCheck (obj, &PyGObject_Type)) { PyErr_SetString (PyExc_TypeError, "GObject is required"); return -1; } if (!G_TYPE_CHECK_INSTANCE_TYPE (pygobject_get (obj), value_type)) { PyErr_SetString (PyExc_TypeError, "Invalid GObject type for assignment"); return -1; } g_value_set_object (value, pygobject_get (obj)); } } else { PyErr_SetString (PyExc_TypeError, "Unsupported conversion"); return -1; } break; case G_TYPE_CHAR: { gint8 temp; if (pygi_gschar_from_py (obj, &temp)) { g_value_set_schar (value, temp); return 0; } else return -1; } case G_TYPE_UCHAR: { guchar temp; if (pygi_guchar_from_py (obj, &temp)) { g_value_set_uchar (value, temp); return 0; } else return -1; } case G_TYPE_BOOLEAN: { gboolean temp; if (pygi_gboolean_from_py (obj, &temp)) { g_value_set_boolean (value, temp); return 0; } else return -1; } case G_TYPE_INT: { gint temp; if (pygi_gint_from_py (obj, &temp)) { g_value_set_int (value, temp); return 0; } else return -1; } case G_TYPE_UINT: { guint temp; if (pygi_guint_from_py (obj, &temp)) { g_value_set_uint (value, temp); return 0; } else return -1; } case G_TYPE_LONG: { glong temp; if (pygi_glong_from_py (obj, &temp)) { g_value_set_long (value, temp); return 0; } else return -1; } case G_TYPE_ULONG: { gulong temp; if (pygi_gulong_from_py (obj, &temp)) { g_value_set_ulong (value, temp); return 0; } else return -1; } case G_TYPE_INT64: { gint64 temp; if (pygi_gint64_from_py (obj, &temp)) { g_value_set_int64 (value, temp); return 0; } else return -1; } case G_TYPE_UINT64: { guint64 temp; if (pygi_guint64_from_py (obj, &temp)) { g_value_set_uint64 (value, temp); return 0; } else return -1; } case G_TYPE_ENUM: { gint val = 0; if (pyg_enum_get_value (G_VALUE_TYPE (value), obj, &val) < 0) { return -1; } g_value_set_enum (value, val); break; } case G_TYPE_FLAGS: { guint val = 0; if (pyg_flags_get_value (G_VALUE_TYPE (value), obj, &val) < 0) { return -1; } g_value_set_flags (value, val); return 0; } case G_TYPE_FLOAT: { gfloat temp; if (pygi_gfloat_from_py (obj, &temp)) { g_value_set_float (value, temp); return 0; } else return -1; } case G_TYPE_DOUBLE: { gdouble temp; if (pygi_gdouble_from_py (obj, &temp)) { g_value_set_double (value, temp); return 0; } else return -1; } case G_TYPE_STRING: { gchar *temp; if (pygi_utf8_from_py (obj, &temp)) { g_value_take_string (value, temp); return 0; } else { /* also allows setting anything implementing __str__ */ PyObject *str; PyErr_Clear (); str = PyObject_Str (obj); if (str == NULL) return -1; if (pygi_utf8_from_py (str, &temp)) { Py_DECREF (str); g_value_take_string (value, temp); return 0; } Py_DECREF (str); return -1; } } case G_TYPE_POINTER: if (Py_IsNone (obj)) g_value_set_pointer (value, NULL); else if (PyObject_TypeCheck (obj, &PyGPointer_Type) && G_VALUE_HOLDS (value, ((PyGPointer *)obj)->gtype)) g_value_set_pointer (value, pyg_pointer_get (obj, gpointer)); else if (PyCapsule_CheckExact (obj)) g_value_set_pointer (value, PyCapsule_GetPointer (obj, NULL)); else if (G_VALUE_HOLDS_GTYPE (value)) g_value_set_gtype (value, pyg_type_from_object (obj)); else { PyErr_SetString (PyExc_TypeError, "Expected pointer"); return -1; } break; case G_TYPE_BOXED: { PyGTypeMarshal *bm; gboolean holds_value_array; G_GNUC_BEGIN_IGNORE_DEPRECATIONS holds_value_array = G_VALUE_HOLDS (value, PYGI_TYPE_VALUE_ARRAY); G_GNUC_END_IGNORE_DEPRECATIONS if (Py_IsNone (obj)) g_value_set_boxed (value, NULL); else if (G_VALUE_HOLDS (value, PY_TYPE_OBJECT)) g_value_set_boxed (value, obj); else if (PyObject_TypeCheck (obj, &PyGBoxed_Type) && G_VALUE_HOLDS (value, ((PyGBoxed *)obj)->gtype)) g_value_set_boxed (value, pyg_boxed_get (obj, gpointer)); else if (G_VALUE_HOLDS (value, G_TYPE_VALUE)) { GType type; GValue *n_value; type = pyg_type_from_object ((PyObject *)Py_TYPE (obj)); if (G_UNLIKELY (!type)) { return -1; } n_value = g_new0 (GValue, 1); g_value_init (n_value, type); g_value_take_boxed (value, n_value); return pyg_value_from_pyobject_with_error (n_value, obj); } else if (PySequence_Check (obj) && holds_value_array) return pyg_value_array_from_pyobject (value, obj, NULL); else if (PySequence_Check (obj) && G_VALUE_HOLDS (value, G_TYPE_ARRAY)) return pyg_array_from_pyobject (value, obj); else if (PyUnicode_Check (obj) && G_VALUE_HOLDS (value, G_TYPE_GSTRING)) { GString *string; char *buffer; Py_ssize_t len; buffer = PyUnicode_AsUTF8AndSize (obj, &len); if (buffer == NULL) return -1; string = g_string_new_len (buffer, len); g_value_set_boxed (value, string); g_string_free (string, TRUE); break; } else if ((bm = pyg_type_lookup (G_VALUE_TYPE (value))) != NULL) return bm->tovalue (value, obj); else if (PyCapsule_CheckExact (obj)) g_value_set_boxed (value, PyCapsule_GetPointer (obj, NULL)); else { PyErr_SetString (PyExc_TypeError, "Expected Boxed"); return -1; } break; } case G_TYPE_OBJECT: if (Py_IsNone (obj)) { g_value_set_object (value, NULL); } else if (PyObject_TypeCheck (obj, &PyGObject_Type) && G_TYPE_CHECK_INSTANCE_TYPE (pygobject_get (obj), G_VALUE_TYPE (value))) { g_value_set_object (value, pygobject_get (obj)); } else { PyErr_SetString (PyExc_TypeError, "Expected GObject"); return -1; } break; case G_TYPE_VARIANT: { if (Py_IsNone (obj)) g_value_set_variant (value, NULL); else if (pyg_type_from_object_strict (obj, FALSE) == G_TYPE_VARIANT) g_value_set_variant (value, pyg_boxed_get (obj, GVariant)); else { PyErr_SetString (PyExc_TypeError, "Expected Variant"); return -1; } break; } default: { PyGTypeMarshal *bm; if ((bm = pyg_type_lookup (G_VALUE_TYPE (value))) != NULL) { return bm->tovalue (value, obj); } else { GIRepository *repository; GIBaseInfo *info; GIObjectInfoSetValueFunction set_value_func = NULL; if (!PyObject_TypeCheck (obj, &PyGIFundamental_Type)) { PyErr_SetString (PyExc_TypeError, "Fundamental type is required"); return -1; } if (!G_TYPE_CHECK_INSTANCE_TYPE (pygi_fundamental_get (obj), value_type)) { PyErr_SetString (PyExc_TypeError, "Invalid fundamental type for assignment"); return -1; } repository = pygi_repository_get_default (); info = gi_repository_find_by_gtype (repository, value_type); if (info && GI_IS_OBJECT_INFO (info)) { set_value_func = gi_object_info_get_set_value_function_pointer ( (GIObjectInfo *)info); if (set_value_func) { set_value_func (value, pygi_fundamental_get (obj)); } else { PyErr_SetString ( PyExc_TypeError, "No set-value function for fundamental type"); } } else { PyErr_SetString (PyExc_TypeError, "Unknown value type"); } if (info) gi_base_info_unref (info); } break; } } /* If an error occurred, unset the GValue but don't clear the Python error. */ if (PyErr_Occurred ()) { g_value_unset (value); return -1; } return 0; } /** * pyg_value_from_pyobject: * @value: the GValue object to store the converted value in. * @obj: the Python object to convert. * * Same basic function as pyg_value_from_pyobject_with_error but clears * any Python errors before returning. * * Returns: 0 on success, -1 on error. */ int pyg_value_from_pyobject (GValue *value, PyObject *obj) { int res = pyg_value_from_pyobject_with_error (value, obj); if (PyErr_Occurred ()) { PyErr_Clear (); return -1; } return res; } /** * pygi_value_to_py_basic_type: * @value: the GValue object. * @handled: (out): TRUE if the return value is defined * * This function creates/returns a Python wrapper object that * represents the GValue passed as an argument limited to supporting basic types * like ints, bools, and strings. * * Returns: a PyObject representing the value. */ PyObject * pygi_value_to_py_basic_type (const GValue *value, GType fundamental, gboolean *handled) { *handled = TRUE; switch (fundamental) { case G_TYPE_CHAR: return PyLong_FromLong (g_value_get_schar (value)); case G_TYPE_UCHAR: return PyLong_FromLong (g_value_get_uchar (value)); case G_TYPE_BOOLEAN: return pygi_gboolean_to_py (g_value_get_boolean (value)); case G_TYPE_INT: return pygi_gint_to_py (g_value_get_int (value)); case G_TYPE_UINT: return pygi_guint_to_py (g_value_get_uint (value)); case G_TYPE_LONG: return pygi_glong_to_py (g_value_get_long (value)); case G_TYPE_ULONG: return pygi_gulong_to_py (g_value_get_ulong (value)); case G_TYPE_INT64: return pygi_gint64_to_py (g_value_get_int64 (value)); case G_TYPE_UINT64: return pygi_guint64_to_py (g_value_get_uint64 (value)); case G_TYPE_ENUM: return pyg_enum_from_gtype (G_VALUE_TYPE (value), g_value_get_enum (value)); case G_TYPE_FLAGS: return pyg_flags_from_gtype (G_VALUE_TYPE (value), g_value_get_flags (value)); case G_TYPE_FLOAT: return pygi_gfloat_to_py (g_value_get_float (value)); case G_TYPE_DOUBLE: return pygi_gdouble_to_py (g_value_get_double (value)); case G_TYPE_STRING: return pygi_utf8_to_py (g_value_get_string (value)); default: *handled = FALSE; return NULL; } } /** * value_to_py_structured_type: * @value: the GValue object. * @copy_boxed: true if boxed values should be copied. * * This function creates/returns a Python wrapper object that * represents the GValue passed as an argument. * * Returns: a PyObject representing the value or NULL and sets an error; */ static PyObject * value_to_py_structured_type (const GValue *value, GType fundamental, gboolean copy_boxed) { const gchar *type_name; switch (fundamental) { case G_TYPE_INTERFACE: if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_OBJECT)) return pygobject_new (g_value_get_object (value)); else break; case G_TYPE_POINTER: if (G_VALUE_HOLDS_GTYPE (value)) return pyg_type_wrapper_new (g_value_get_gtype (value)); else return pyg_pointer_new (G_VALUE_TYPE (value), g_value_get_pointer (value)); case G_TYPE_BOXED: { PyGTypeMarshal *bm; gboolean holds_value_array; G_GNUC_BEGIN_IGNORE_DEPRECATIONS holds_value_array = G_VALUE_HOLDS (value, PYGI_TYPE_VALUE_ARRAY); G_GNUC_END_IGNORE_DEPRECATIONS if (G_VALUE_HOLDS (value, PY_TYPE_OBJECT)) { PyObject *ret = (PyObject *)g_value_dup_boxed (value); if (ret == NULL) { Py_RETURN_NONE; } return ret; } else if (G_VALUE_HOLDS (value, G_TYPE_VALUE)) { GValue *n_value = g_value_get_boxed (value); return pyg_value_as_pyobject (n_value, copy_boxed); } else if (holds_value_array) { GValueArray *array = (GValueArray *)g_value_get_boxed (value); Py_ssize_t n_values = array ? array->n_values : 0; PyObject *ret = PyList_New (n_values); int i; for (i = 0; i < n_values; ++i) PyList_SET_ITEM ( ret, i, pyg_value_as_pyobject (array->values + i, copy_boxed)); return ret; } else if (G_VALUE_HOLDS (value, G_TYPE_GSTRING)) { GString *string = (GString *)g_value_get_boxed (value); PyObject *ret = PyUnicode_FromStringAndSize (string->str, string->len); return ret; } bm = pyg_type_lookup (G_VALUE_TYPE (value)); if (bm) { return bm->fromvalue (value); } else { if (copy_boxed) return pygi_gboxed_new (G_VALUE_TYPE (value), g_value_get_boxed (value), TRUE, TRUE); else return pygi_gboxed_new (G_VALUE_TYPE (value), g_value_get_boxed (value), FALSE, FALSE); } } case G_TYPE_OBJECT: return pygobject_new (g_value_get_object (value)); case G_TYPE_VARIANT: { GVariant *v = g_value_get_variant (value); if (v == NULL) { Py_RETURN_NONE; } return pygi_struct_new_from_g_type (G_TYPE_VARIANT, g_variant_ref (v), FALSE); } case G_TYPE_INVALID: PyErr_SetString (PyExc_TypeError, "Invalid type"); return NULL; default: { PyGTypeMarshal *bm; GIRepository *repository; GIBaseInfo *info; GIObjectInfoGetValueFunction get_value_func = NULL; if ((bm = pyg_type_lookup (G_VALUE_TYPE (value)))) return bm->fromvalue (value); repository = pygi_repository_get_default (); info = gi_repository_find_by_gtype (repository, fundamental); if (info == NULL) break; if (GI_IS_OBJECT_INFO (info)) get_value_func = gi_object_info_get_get_value_function_pointer ( (GIObjectInfo *)info); gi_base_info_unref (info); if (get_value_func) return pygi_fundamental_new (get_value_func (value)); break; } } type_name = g_type_name (G_VALUE_TYPE (value)); if (type_name == NULL) { type_name = "(null)"; } PyErr_Format (PyExc_TypeError, "unknown type %s", type_name); return NULL; } /** * pyg_value_as_pyobject: * @value: the GValue object. * @copy_boxed: true if boxed values should be copied. * * This function creates/returns a Python wrapper object that * represents the GValue passed as an argument. * * Returns: a PyObject representing the value or %NULL and sets an exception. */ PyObject * pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed) { PyObject *pyobj; gboolean handled; GType fundamental = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)); /* HACK: special case char and uchar to return PyBytes intstead of integers * in the general case. Property access will skip this by calling * pygi_value_to_py_basic_type() directly. * See: https://bugzilla.gnome.org/show_bug.cgi?id=733893 */ if (fundamental == G_TYPE_CHAR) { gint8 val = g_value_get_schar (value); return PyUnicode_FromStringAndSize ((char *)&val, 1); } else if (fundamental == G_TYPE_UCHAR) { guint8 val = g_value_get_uchar (value); return PyBytes_FromStringAndSize ((char *)&val, 1); } pyobj = pygi_value_to_py_basic_type (value, fundamental, &handled); if (handled) return pyobj; pyobj = value_to_py_structured_type (value, fundamental, copy_boxed); return pyobj; } G_GNUC_BEGIN_IGNORE_DEPRECATIONS int pyg_param_gvalue_from_pyobject (GValue *value, PyObject *py_obj, const GParamSpec *pspec) { if (G_IS_PARAM_SPEC_UNICHAR (pspec)) { gunichar u; if (!pyg_pyobj_to_unichar_conv (py_obj, &u)) { PyErr_Clear (); return -1; } g_value_set_uint (value, u); return 0; } else if (PYGI_IS_PARAM_SPEC_VALUE_ARRAY (pspec)) return pyg_value_array_from_pyobject ( value, py_obj, PYGI_PARAM_SPEC_VALUE_ARRAY (pspec)); else { return pyg_value_from_pyobject (value, py_obj); } } G_GNUC_END_IGNORE_DEPRECATIONS PyObject * pyg_param_gvalue_as_pyobject (const GValue *gvalue, gboolean copy_boxed, const GParamSpec *pspec) { if (G_IS_PARAM_SPEC_UNICHAR (pspec)) { gunichar u; gchar *encoded; PyObject *retval; u = g_value_get_uint (gvalue); encoded = g_ucs4_to_utf8 (&u, 1, NULL, NULL, NULL); if (encoded == NULL) { PyErr_SetString (PyExc_ValueError, "Failed to decode"); return NULL; } retval = PyUnicode_FromString (encoded); g_free (encoded); return retval; } else { return pyg_value_as_pyobject (gvalue, copy_boxed); } } PyObject * pyg__gvalue_get (PyObject *module, PyObject *pygvalue) { if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) { PyErr_SetString (PyExc_TypeError, "Expected GValue argument."); return NULL; } return pyg_value_as_pyobject (pyg_boxed_get (pygvalue, GValue), /*copy_boxed=*/TRUE); } PyObject * pyg__gvalue_get_type (PyObject *module, PyObject *pygvalue) { GValue *value; GType type; if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) { PyErr_SetString (PyExc_TypeError, "Expected GValue argument."); return NULL; } value = pyg_boxed_get (pygvalue, GValue); type = G_VALUE_TYPE (value); return pyg_type_wrapper_new (type); } PyObject * pyg__gvalue_set (PyObject *module, PyObject *args) { PyObject *pygvalue; PyObject *pyobject; if (!PyArg_ParseTuple (args, "OO:_gi._gvalue_set", &pygvalue, &pyobject)) return NULL; if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) { PyErr_SetString (PyExc_TypeError, "Expected GValue argument."); return NULL; } if (pyg_value_from_pyobject_with_error (pyg_boxed_get (pygvalue, GValue), pyobject) == -1) return NULL; Py_RETURN_NONE; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygi-value.h0000664000000000000000000000401615074673150015201 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGI_VALUE_H__ #define __PYGI_VALUE_H__ #include #include #include G_BEGIN_DECLS GIArgument _pygi_argument_from_g_value (const GValue *value, GITypeInfo *type_info); int pyg_value_from_pyobject (GValue *value, PyObject *obj); int pyg_value_from_pyobject_with_error (GValue *value, PyObject *obj); PyObject *pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed); int pyg_param_gvalue_from_pyobject (GValue *value, PyObject *py_obj, const GParamSpec *pspec); PyObject *pyg_param_gvalue_as_pyobject (const GValue *gvalue, gboolean copy_boxed, const GParamSpec *pspec); PyObject *pyg_strv_from_gvalue (const GValue *value); int pyg_strv_to_gvalue (GValue *value, PyObject *obj); PyObject *pygi_value_to_py_basic_type (const GValue *value, GType fundamental, gboolean *handled); PyObject *pyg__gvalue_get (PyObject *module, PyObject *pygvalue); PyObject *pyg__gvalue_set (PyObject *module, PyObject *args); PyObject *pyg__gvalue_get_type (PyObject *module, PyObject *pygvalue); G_END_DECLS #endif /* __PYGI_VALUE_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pyginterface.c0000664000000000000000000001025315074673150015572 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * pyginterface.c: wrapper for the gobject library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include #include "pygi-type.h" #include "pygi-util.h" #include "pyginterface.h" GQuark pyginterface_type_key; GQuark pyginterface_info_key; PYGI_DEFINE_TYPE ("gobject.GInterface", PyGInterface_Type, PyObject) static int pyg_interface_init (PyObject *self, PyObject *args, PyObject *kwargs) { gchar buf[512]; if (!PyArg_ParseTuple (args, ":GInterface.__init__")) return -1; g_snprintf (buf, sizeof (buf), "%s can not be constructed", Py_TYPE (self)->tp_name); PyErr_SetString (PyExc_NotImplementedError, buf); return -1; } static void pyg_interface_free (PyObject *op) { PyObject_Free (op); } /** * pyg_register_interface: * @dict: a module dictionary. * @class_name: the class name for the wrapper class. * @gtype: the GType of the interface. * @type: the wrapper class for the interface. * * Registers a Python class as the wrapper for a GInterface. As a * convenience it will also place a reference to the wrapper class in * the provided module dictionary. */ void pyg_register_interface (PyObject *dict, const gchar *class_name, GType gtype, PyTypeObject *type) { PyObject *o; Py_SET_TYPE (type, &PyType_Type); g_assert (Py_TYPE (&PyGInterface_Type) != NULL); type->tp_base = &PyGInterface_Type; if (PyType_Ready (type) < 0) { g_warning ("could not ready `%s'", type->tp_name); return; } if (gtype) { o = pyg_type_wrapper_new (gtype); PyDict_SetItemString (type->tp_dict, "__gtype__", o); Py_DECREF (o); } g_type_set_qdata (gtype, pyginterface_type_key, type); PyDict_SetItemString (dict, (char *)class_name, (PyObject *)type); } void pyg_register_interface_info (GType gtype, const GInterfaceInfo *info) { GInterfaceInfo *prev_info = pyg_lookup_interface_info (gtype); if (prev_info) { g_free (prev_info); } g_type_set_qdata (gtype, pyginterface_info_key, g_memdup2 (info, sizeof (GInterfaceInfo))); } const GInterfaceInfo * pyg_lookup_interface_info (GType gtype) { return g_type_get_qdata (gtype, pyginterface_info_key); } /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_interface_register_types (PyObject *d) { PyObject *pygtype; pyginterface_type_key = g_quark_from_static_string ("PyGInterface::type"); pyginterface_info_key = g_quark_from_static_string ("PyGInterface::info"); PyGInterface_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; PyGInterface_Type.tp_init = (initproc)pyg_interface_init; PyGInterface_Type.tp_free = (freefunc)pyg_interface_free; PyGInterface_Type.tp_alloc = PyType_GenericAlloc; PyGInterface_Type.tp_new = PyType_GenericNew; if (PyType_Ready (&PyGInterface_Type)) return -1; pygtype = pyg_type_wrapper_new (G_TYPE_INTERFACE); PyDict_SetItemString (PyGInterface_Type.tp_dict, "__gtype__", pygtype); Py_DECREF (pygtype); PyDict_SetItemString (PyGInterface_Type.tp_dict, "__doc__", pyg_object_descr_doc_get ()); PyDict_SetItemString (PyGInterface_Type.tp_dict, "__gdoc__", pyg_object_descr_doc_get ()); PyDict_SetItemString (d, "GInterface", (PyObject *)&PyGInterface_Type); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pyginterface.h0000664000000000000000000000264615074673150015606 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * pyginterface.c: wrapper for the gobject library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGOBJECT_INTERFACE_H__ #define __PYGOBJECT_INTERFACE_H__ extern GQuark pyginterface_type_key; extern GQuark pyginterface_info_key; extern PyTypeObject PyGInterface_Type; void pyg_register_interface (PyObject *dict, const gchar *class_name, GType gtype, PyTypeObject *type); const GInterfaceInfo *pyg_lookup_interface_info (GType gtype); void pyg_register_interface_info (GType gtype, const GInterfaceInfo *info); int pygi_interface_register_types (PyObject *d); #endif /* __PYGOBJECT_INTERFACE_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygobject-internal.h0000664000000000000000000000022415074673150016714 0ustar00rootroot#ifndef _PYGOBJECT_INTERNAL_H_ #define _PYGOBJECT_INTERNAL_H_ #define _INSIDE_PYGOBJECT_ #include "pygobject.h" #endif /*_PYGOBJECT_INTERNAL_H_*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygobject-object.c0000664000000000000000000023314515074673150016353 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * * pygobject.c: wrapper for the GObject type. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "gimodule.h" #include "pygboxed.h" #include "pygi-basictype.h" #include "pygi-fundamental.h" #include "pygi-property.h" #include "pygi-signal-closure.h" #include "pygi-type.h" #include "pygi-util.h" #include "pygi-value.h" #include "pyginterface.h" #include "pygobject-object.h" extern PyObject *PyGIDeprecationWarning; static void pygobject_dealloc (PyGObject *self); static int pygobject_traverse (PyGObject *self, visitproc visit, void *arg); static PyObject *pyg_type_get_bases (GType gtype); static inline int pygobject_clear (PyGObject *self); static PyObject *pygobject_weak_ref_new (GObject *obj, PyObject *callback, PyObject *user_data); static void pygobject_inherit_slots (PyTypeObject *type, PyObject *bases, gboolean check_for_present); static void pygobject_find_slot_for (PyTypeObject *type, PyObject *bases, int slot_offset, gboolean check_for_present); GType PY_TYPE_OBJECT = 0; GQuark pygobject_custom_key; GQuark pygobject_class_key; GQuark pygobject_class_init_key; GQuark pygobject_wrapper_key; GQuark pygobject_has_updated_constructor_key; GQuark pygobject_instance_data_key; /* PyPy doesn't support tp_dictoffset, so we have to work around it */ #ifndef PYPY_VERSION #define PYGI_OBJECT_USE_CUSTOM_DICT #endif GClosure * gclosure_from_pyfunc (PyGObject *object, PyObject *func) { GSList *l; PyGObjectData *inst_data; inst_data = pyg_object_peek_inst_data (object->obj); if (inst_data) { for (l = inst_data->closures; l; l = l->next) { PyGClosure *pyclosure = l->data; int res = PyObject_RichCompareBool (pyclosure->callback, func, Py_EQ); if (res == -1) { PyErr_Clear (); /* Is there anything else to do? */ } else if (res) { return (GClosure *)pyclosure; } } } return NULL; } /* Copied from glib. gobject uses hyphens in property names, but in Python * we can only represent hyphens as underscores. Convert underscores to * hyphens for glib compatibility. */ static void canonicalize_key (gchar *key) { gchar *p; for (p = key; *p != 0; p++) { gchar c = *p; if (c != '-' && (c < '0' || c > '9') && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) *p = '-'; } } /* -------------- class <-> wrapper manipulation --------------- */ static void pygobject_data_free (PyGObjectData *data) { /* This function may be called after the python interpreter has already * been shut down. If this happens, we cannot do any python calls, so just * free the memory. */ PyGILState_STATE state = 0; PyThreadState *_save = NULL; gboolean state_saved; GSList *closures, *tmp; state_saved = Py_IsInitialized (); if (state_saved) { state = PyGILState_Ensure (); Py_DECREF (data->type); /* We cannot use Py_BEGIN_ALLOW_THREADS here because this is inside * a branch. */ Py_UNBLOCK_THREADS; /* Modifies _save */ } tmp = closures = data->closures; #ifndef NDEBUG data->closures = NULL; data->type = NULL; #endif while (tmp) { GClosure *closure = tmp->data; /* we get next item first, because the current link gets * invalidated by pygobject_unwatch_closure */ tmp = tmp->next; g_closure_invalidate (closure); } if (data->closures != NULL) g_warning ("invalidated all closures, but data->closures != NULL !"); g_free (data); if (state_saved && Py_IsInitialized ()) { Py_BLOCK_THREADS; /* Restores _save */ PyGILState_Release (state); } } static inline PyGObjectData * pygobject_data_new (void) { PyGObjectData *data; data = g_new0 (PyGObjectData, 1); return data; } static inline PyGObjectData * pygobject_get_inst_data (PyGObject *self) { PyGObjectData *inst_data; if (G_UNLIKELY (!self->obj)) return NULL; inst_data = g_object_get_qdata (self->obj, pygobject_instance_data_key); if (inst_data == NULL) { inst_data = pygobject_data_new (); inst_data->type = Py_TYPE (self); Py_INCREF ((PyObject *)inst_data->type); g_object_set_qdata_full (self->obj, pygobject_instance_data_key, inst_data, (GDestroyNotify)pygobject_data_free); } return inst_data; } PyTypeObject *PyGObject_MetaType = NULL; /** * pygobject_sink: * @obj: a GObject * * As Python handles reference counting for us, the "floating * reference" code in GTK is not all that useful. In fact, it can * cause leaks. This function should be called to remove the floating * references on objects on construction. **/ void pygobject_sink (GObject *obj) { /* The default behaviour for GInitiallyUnowned subclasses is to call ref_sink(). * - if the object is new and owned by someone else, its ref has been sunk and * we need to keep the one from that someone and add our own "fresh ref" * - if the object is not and owned by nobody, its ref is floating and we need * to transform it into a regular ref. */ if (G_IS_INITIALLY_UNOWNED (obj)) { g_object_ref_sink (obj); } } typedef struct { PyObject_HEAD GParamSpec **props; guint n_props; guint index; } PyGPropsIter; PYGI_DEFINE_TYPE ("gi._gi.GPropsIter", PyGPropsIter_Type, PyGPropsIter); static void pyg_props_iter_dealloc (PyGPropsIter *self) { g_free (self->props); PyObject_Free ((PyObject *)self); } static PyObject * pygobject_props_iter_next (PyGPropsIter *iter) { if (iter->index < iter->n_props) return pygi_fundamental_new (iter->props[iter->index++]); else { PyErr_SetNone (PyExc_StopIteration); return NULL; } } typedef struct { PyObject_HEAD /* a reference to the object containing the properties */ PyGObject *pygobject; GType gtype; } PyGProps; static void PyGProps_dealloc (PyGProps *self) { PyObject_GC_UnTrack ((PyObject *)self); Py_XSETREF (self->pygobject, NULL); PyObject_GC_Del ((PyObject *)self); } static PyObject * build_parameter_list (GObjectClass *class) { GParamSpec **props; guint n_props = 0, i; PyObject *prop_str; PyObject *props_list; props = g_object_class_list_properties (class, &n_props); props_list = PyList_New (n_props); for (i = 0; i < n_props; i++) { char *name; name = g_strdup (g_param_spec_get_name (props[i])); /* hyphens cannot belong in identifiers */ g_strdelimit (name, "-", '_'); prop_str = PyUnicode_FromString (name); PyList_SetItem (props_list, i, prop_str); g_free (name); } if (props) g_free (props); return props_list; } static PyObject * PyGProps_getattro (PyGProps *self, PyObject *attr) { char *attr_name, *property_name; GObjectClass *class; GParamSpec *pspec; attr_name = PyUnicode_AsUTF8 (attr); if (!attr_name) { PyErr_Clear (); return PyObject_GenericGetAttr ((PyObject *)self, attr); } class = g_type_class_ref (self->gtype); /* g_object_class_find_property recurses through the class hierarchy, * so the resulting pspec tells us the owner_type that owns the property * we're dealing with. */ property_name = g_strdup (attr_name); canonicalize_key (property_name); pspec = g_object_class_find_property (class, property_name); g_free (property_name); g_type_class_unref (class); if (!pspec) { return PyObject_GenericGetAttr ((PyObject *)self, attr); } if (!self->pygobject) { /* If we're doing it without an instance, return a GParamSpec */ return pygi_fundamental_new (pspec); } return pygi_get_property_value (self->pygobject, pspec); } static gboolean set_property_from_pspec (GObject *obj, GParamSpec *pspec, PyObject *pvalue) { GValue value = { 0, }; if (pspec->flags & G_PARAM_CONSTRUCT_ONLY) { PyErr_Format (PyExc_TypeError, "property '%s' can only be set in constructor", pspec->name); return FALSE; } if (!(pspec->flags & G_PARAM_WRITABLE)) { PyErr_Format (PyExc_TypeError, "property '%s' is not writable", pspec->name); return FALSE; } g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); if (pyg_param_gvalue_from_pyobject (&value, pvalue, pspec) < 0) { PyObject *pvalue_str = PyObject_Repr (pvalue); PyErr_Format ( PyExc_TypeError, "could not convert %s to type '%s' when setting property '%s.%s'", PyUnicode_AsUTF8 (pvalue_str), g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)), G_OBJECT_TYPE_NAME (obj), pspec->name); Py_DECREF (pvalue_str); return FALSE; } Py_BEGIN_ALLOW_THREADS; g_object_set_property (obj, pspec->name, &value); g_value_unset (&value); Py_END_ALLOW_THREADS; return TRUE; } PYGI_DEFINE_TYPE ("gi._gi.GProps", PyGProps_Type, PyGProps); static int PyGProps_setattro (PyGProps *self, PyObject *attr, PyObject *pvalue) { GParamSpec *pspec; char *attr_name, *property_name; GObject *obj; int ret = -1; if (pvalue == NULL) { PyErr_SetString (PyExc_TypeError, "properties cannot be " "deleted"); return -1; } attr_name = PyUnicode_AsUTF8 (attr); if (!attr_name) { PyErr_Clear (); return PyObject_GenericSetAttr ((PyObject *)self, attr, pvalue); } if (!self->pygobject) { PyErr_SetString (PyExc_TypeError, "cannot set GOject properties without an instance"); return -1; } obj = self->pygobject->obj; property_name = g_strdup (attr_name); canonicalize_key (property_name); /* g_object_class_find_property recurses through the class hierarchy, * so the resulting pspec tells us the owner_type that owns the property * we're dealing with. */ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (obj), property_name); g_free (property_name); if (!pspec) { return PyObject_GenericSetAttr ((PyObject *)self, attr, pvalue); } if (!pyg_gtype_is_custom (pspec->owner_type)) { /* This GType is not implemented in Python: see if we can set the * property via gi. */ ret = pygi_set_property_value (self->pygobject, pspec, pvalue); if (ret == 0) return 0; else if (ret == -1 && PyErr_Occurred ()) return -1; } /* This GType is implemented in Python, or we failed to set it via gi: * do a straightforward set. */ if (!set_property_from_pspec (obj, pspec, pvalue)) return -1; return 0; } static int pygobject_props_traverse (PyGProps *self, visitproc visit, void *arg) { if (self->pygobject && visit ((PyObject *)self->pygobject, arg) < 0) return -1; return 0; } static PyObject * pygobject_props_get_iter (PyGProps *self) { PyGPropsIter *iter; GObjectClass *class; iter = PyObject_New (PyGPropsIter, &PyGPropsIter_Type); class = g_type_class_ref (self->gtype); iter->props = g_object_class_list_properties (class, &iter->n_props); iter->index = 0; g_type_class_unref (class); return (PyObject *)iter; } static PyObject * pygobject_props_dir (PyGProps *self) { PyObject *ret; GObjectClass *class; class = g_type_class_ref (self->gtype); ret = build_parameter_list (class); g_type_class_unref (class); return ret; } static PyMethodDef pygobject_props_methods[] = { { "__dir__", (PyCFunction)pygobject_props_dir, METH_NOARGS }, { NULL, NULL, 0 }, }; static Py_ssize_t PyGProps_length (PyGProps *self) { GObjectClass *class; GParamSpec **props; guint n_props; class = g_type_class_ref (self->gtype); props = g_object_class_list_properties (class, &n_props); g_type_class_unref (class); g_free (props); return (Py_ssize_t)n_props; } static PySequenceMethods _PyGProps_as_sequence = { (lenfunc)PyGProps_length, 0, 0, 0, 0, 0, 0, }; PYGI_DEFINE_TYPE ("gi._gi.GPropsDescr", PyGPropsDescr_Type, PyObject); static PyObject * pyg_props_descr_descr_get (PyObject *self, PyObject *obj, PyObject *type) { PyGProps *gprops; gprops = PyObject_GC_New (PyGProps, &PyGProps_Type); if (obj == NULL || Py_IsNone (obj)) { gprops->pygobject = NULL; gprops->gtype = pyg_type_from_object (type); } else { if (!PyObject_IsInstance (obj, (PyObject *)&PyGObject_Type)) { PyErr_SetString (PyExc_TypeError, "cannot use GObject property" " descriptor on non-GObject instances"); return NULL; } gprops->pygobject = (PyGObject *)Py_NewRef (obj); gprops->gtype = pyg_type_from_object (obj); } return (PyObject *)gprops; } /** * pygobject_register_class: * @dict: the module dictionary. A reference to the type will be stored here. * @type_name: not used ? * @gtype: the GType of the GObject subclass. * @type: the Python type object for this wrapper. * @static_bases: a tuple of Python type objects that are the bases of * this type * * This function is used to register a Python type as the wrapper for * a particular GObject subclass. It will also insert a reference to * the wrapper class into the module dictionary passed as a reference, * which simplifies initialisation. */ void pygobject_register_class (PyObject *dict, const gchar *type_name, GType gtype, PyTypeObject *type, PyObject *static_bases) { PyObject *o; const char *class_name, *s; PyObject *runtime_bases; PyObject *bases_list, *bases, *mod_name; int i; class_name = type->tp_name; s = strrchr (class_name, '.'); if (s != NULL) class_name = s + 1; runtime_bases = pyg_type_get_bases (gtype); if (static_bases) { PyTypeObject *py_parent_type = (PyTypeObject *)PyTuple_GET_ITEM (static_bases, 0); bases_list = PySequence_List (static_bases); /* we start at index 1 because we want to skip the primary * base, otherwise we might get MRO conflict */ for (i = 1; i < PyTuple_GET_SIZE (runtime_bases); ++i) { PyObject *base = PyTuple_GET_ITEM (runtime_bases, i); int contains = PySequence_Contains (bases_list, base); if (contains < 0) PyErr_Print (); else if (!contains) { if (!PySequence_Contains (py_parent_type->tp_mro, base)) { #if 0 g_message("Adding missing base %s to type %s", ((PyTypeObject *)base)->tp_name, type->tp_name); #endif PyList_Append (bases_list, base); } } } bases = PySequence_Tuple (bases_list); Py_DECREF (bases_list); Py_DECREF (runtime_bases); } else bases = runtime_bases; Py_SET_TYPE (type, PyGObject_MetaType); type->tp_bases = bases; if (G_LIKELY (bases)) { type->tp_base = (PyTypeObject *)PyTuple_GetItem (bases, 0); Py_INCREF (type->tp_base); } pygobject_inherit_slots (type, bases, TRUE); if (PyType_Ready (type) < 0) { g_warning ("couldn't make the type `%s' ready", type->tp_name); return; } /* Set type.__module__ to the name of the module, * otherwise it'll default to 'gobject', see #376099 */ s = strrchr (type->tp_name, '.'); if (s != NULL) { mod_name = PyUnicode_FromStringAndSize (type->tp_name, (int)(s - type->tp_name)); PyDict_SetItemString (type->tp_dict, "__module__", mod_name); Py_DECREF (mod_name); } if (gtype) { o = pyg_type_wrapper_new (gtype); PyDict_SetItemString (type->tp_dict, "__gtype__", o); Py_DECREF (o); /* stash a pointer to the python class with the GType */ Py_INCREF (type); g_type_set_qdata (gtype, pygobject_class_key, type); } /* set up __doc__ descriptor on type */ PyDict_SetItemString (type->tp_dict, "__doc__", pyg_object_descr_doc_get ()); PyDict_SetItemString (dict, (char *)class_name, (PyObject *)type); } static void pyg_toggle_notify (gpointer data, GObject *object, gboolean is_last_ref) { PyGObject *self; PyGILState_STATE state; state = PyGILState_Ensure (); /* Avoid thread safety problems by using qdata for wrapper retrieval * instead of the user data argument. * See: https://bugzilla.gnome.org/show_bug.cgi?id=709223 */ self = (PyGObject *)g_object_get_qdata (object, pygobject_wrapper_key); if (self) { if (is_last_ref) Py_DECREF (self); else Py_INCREF (self); } PyGILState_Release (state); } static inline gboolean pygobject_toggle_ref_is_required (PyGObject *self) { #ifdef PYGI_OBJECT_USE_CUSTOM_DICT return self->inst_dict != NULL; #else PyObject *dict; gboolean result; dict = PyObject_GetAttrString ((PyObject *)self, "__dict__"); if (!dict) { PyErr_Clear (); return FALSE; } result = PyDict_Size (dict) != 0; Py_DECREF (dict); return result; #endif } static inline gboolean pygobject_toggle_ref_is_active (PyGObject *self) { return self->private_flags.flags & PYGOBJECT_USING_TOGGLE_REF; } /* Called when the inst_dict is first created; switches the reference counting strategy to start using toggle ref to keep the wrapper alive while the GObject lives. In contrast, while inst_dict was NULL the python wrapper is allowed to die at will and is recreated on demand. */ static inline void pygobject_toggle_ref_ensure (PyGObject *self) { if (pygobject_toggle_ref_is_active (self)) return; if (!pygobject_toggle_ref_is_required (self)) return; if (self->obj == NULL) return; g_assert (self->obj->ref_count >= 1); self->private_flags.flags |= PYGOBJECT_USING_TOGGLE_REF; /* Note that add_toggle_ref will never immediately call back into pyg_toggle_notify */ Py_INCREF ((PyObject *)self); g_object_add_toggle_ref (self->obj, pyg_toggle_notify, NULL); g_object_unref (self->obj); } /* Called when an custom gobject is initalized via g_object_new instead of its constructor. The next time the wrapper is access via pygobject_new_full it will sink the floating reference instead of adding a new reference and causing a leak */ void pygobject_ref_float (PyGObject *self) { /* should only be floated once */ g_assert (!(self->private_flags.flags & PYGOBJECT_IS_FLOATING_REF)); self->private_flags.flags |= PYGOBJECT_IS_FLOATING_REF; } /* Called by gobject_new_full, if the floating flag is set remove it, otherwise ref the pyobject */ void pygobject_ref_sink (PyGObject *self) { if (self->private_flags.flags & PYGOBJECT_IS_FLOATING_REF) self->private_flags.flags &= ~PYGOBJECT_IS_FLOATING_REF; else Py_INCREF ((PyObject *)self); } /** * pygobject_register_wrapper: * @self: the wrapper instance * * In the constructor of PyGTK wrappers, this function should be * called after setting the obj member. It will tie the wrapper * instance to the GObject so that the same wrapper instance will * always be used for this GObject instance. */ void pygobject_register_wrapper (PyObject *self) { PyGObject *gself; g_return_if_fail (self != NULL); g_return_if_fail (PyObject_TypeCheck (self, &PyGObject_Type)); gself = (PyGObject *)self; g_assert (gself->obj->ref_count >= 1); /* save wrapper pointer so we can access it later */ g_object_set_qdata_full (gself->obj, pygobject_wrapper_key, gself, NULL); pygobject_toggle_ref_ensure (gself); } static PyObject * pyg_type_get_bases (GType gtype) { GType *interfaces, parent_type, interface_type; guint n_interfaces; PyTypeObject *py_parent_type, *py_interface_type; PyObject *bases; guint i; if (G_UNLIKELY (gtype == G_TYPE_OBJECT)) return NULL; /* Lookup the parent type */ parent_type = g_type_parent (gtype); py_parent_type = pygobject_lookup_class (parent_type); interfaces = g_type_interfaces (gtype, &n_interfaces); bases = PyTuple_New (n_interfaces + 1); /* We will always put the parent at the first position in bases */ Py_INCREF (py_parent_type); /* PyTuple_SetItem steals a reference */ PyTuple_SetItem (bases, 0, (PyObject *)py_parent_type); /* And traverse interfaces */ if (n_interfaces) { for (i = 0; i < n_interfaces; i++) { interface_type = interfaces[i]; py_interface_type = pygobject_lookup_class (interface_type); Py_INCREF ( py_interface_type); /* PyTuple_SetItem steals a reference */ PyTuple_SetItem (bases, i + 1, (PyObject *)py_interface_type); } } g_free (interfaces); return bases; } /** * pygobject_new_with_interfaces * @gtype: the GType of the GObject subclass. * * Creates a new PyTypeObject from the given GType with interfaces attached in * bases. * * Returns: a PyTypeObject for the new type or NULL if it couldn't be created */ static PyTypeObject * pygobject_new_with_interfaces (GType gtype) { PyGILState_STATE state; PyObject *o; PyTypeObject *type; PyObject *dict; PyTypeObject *py_parent_type; PyObject *bases; state = PyGILState_Ensure (); bases = pyg_type_get_bases (gtype); py_parent_type = (PyTypeObject *)PyTuple_GetItem (bases, 0); dict = PyDict_New (); o = pyg_type_wrapper_new (gtype); PyDict_SetItemString (dict, "__gtype__", o); Py_DECREF (o); /* set up __doc__ descriptor on type */ PyDict_SetItemString (dict, "__doc__", pyg_object_descr_doc_get ()); /* Something special to point out that it's not accessible through * gi.repository */ o = PyUnicode_FromString ("__gi__"); PyDict_SetItemString (dict, "__module__", o); Py_DECREF (o); type = (PyTypeObject *)PyObject_CallFunction ( (PyObject *)Py_TYPE (py_parent_type), "sNN", g_type_name (gtype), bases, dict); if (type == NULL) { PyErr_Print (); PyGILState_Release (state); return NULL; } /* Workaround python tp_(get|set)attr slot inheritance bug. * Fixes bug #144135. */ if (!type->tp_getattr && py_parent_type->tp_getattr) { type->tp_getattro = NULL; type->tp_getattr = py_parent_type->tp_getattr; } if (!type->tp_setattr && py_parent_type->tp_setattr) { type->tp_setattro = NULL; type->tp_setattr = py_parent_type->tp_setattr; } /* override more python stupid hacks behind our back */ type->tp_dealloc = py_parent_type->tp_dealloc; type->tp_alloc = py_parent_type->tp_alloc; type->tp_free = py_parent_type->tp_free; type->tp_traverse = py_parent_type->tp_traverse; type->tp_clear = py_parent_type->tp_clear; pygobject_inherit_slots (type, bases, FALSE); if (PyType_Ready (type) < 0) { g_warning ("couldn't make the type `%s' ready", type->tp_name); PyGILState_Release (state); return NULL; } /* stash a pointer to the python class with the GType */ Py_INCREF (type); g_type_set_qdata (gtype, pygobject_class_key, type); PyGILState_Release (state); return type; } /* Pick appropriate value for given slot (at slot_offset inside * PyTypeObject structure). It must be a pointer, e.g. a pointer to a * function. We use the following heuristic: * * - Scan all types listed as bases of the type. * - If for exactly one base type slot value is non-NULL and * different from that of 'object' and 'GObject', set current type * slot into that value. * - Otherwise (if there is more than one such base type or none at * all) don't touch it and live with Python default. * * The intention here is to propagate slot from custom wrappers to * wrappers created at runtime when appropriate. We prefer to be on * the safe side, so if there is potential collision (more than one * custom slot value), we discard custom overrides altogether. * * When registering type with pygobject_register_class(), i.e. a type * that has been manually created (likely with Codegen help), * `check_for_present' should be set to TRUE. In this case, the * function will never overwrite any non-NULL slots already present in * the type. If `check_for_present' is FALSE, such non-NULL slots are * though to be set by Python interpreter and so will be overwritten * if heuristic above says so. */ static void pygobject_inherit_slots (PyTypeObject *type, PyObject *bases, gboolean check_for_present) { static int slot_offsets[] = { offsetof (PyTypeObject, tp_richcompare), offsetof (PyTypeObject, tp_richcompare), offsetof (PyTypeObject, tp_hash), offsetof (PyTypeObject, tp_iter), offsetof (PyTypeObject, tp_repr), offsetof (PyTypeObject, tp_str), }; gsize i; /* Happens when registering gobject.GObject itself, at least. */ if (!bases) return; for (i = 0; i < G_N_ELEMENTS (slot_offsets); ++i) pygobject_find_slot_for (type, bases, slot_offsets[i], check_for_present); } static void pygobject_find_slot_for (PyTypeObject *type, PyObject *bases, int slot_offset, gboolean check_for_present) { #define TYPE_SLOT(type) (*(void **)(void *)(((char *)(type)) + slot_offset)) void *found_slot = NULL; Py_ssize_t num_bases = PyTuple_Size (bases); Py_ssize_t i; if (check_for_present && TYPE_SLOT (type) != NULL) { /* We are requested to check if there is any custom slot value * in this type already and there actually is. Don't * overwrite it. */ return; } for (i = 0; i < num_bases; ++i) { PyTypeObject *base_type = (PyTypeObject *)PyTuple_GetItem (bases, i); void *slot = TYPE_SLOT (base_type); if (slot == NULL) continue; if (slot == TYPE_SLOT (&PyGObject_Type) || slot == TYPE_SLOT (&PyBaseObject_Type)) continue; if (found_slot != NULL && found_slot != slot) { /* We have a conflict: more than one base use different * custom slots. To be on the safe side, we bail out. */ return; } found_slot = slot; } /* Only perform the final assignment if at least one base has a * custom value. Otherwise just leave this type's slot untouched. */ if (found_slot != NULL) TYPE_SLOT (type) = found_slot; #undef TYPE_SLOT } /** * pygobject_lookup_class: * @gtype: the GType of the GObject subclass. * * This function looks up the wrapper class used to represent * instances of a GObject represented by @gtype. If no wrapper class * or interface has been registered for the given GType, then a new * type will be created. * * Does not set an exception when NULL is returned. * * Returns: The wrapper class for the GObject or NULL if the * GType has no registered type and a new type couldn't be created */ PyTypeObject * pygobject_lookup_class (GType gtype) { PyTypeObject *py_type; if (gtype == G_TYPE_INTERFACE) return &PyGInterface_Type; py_type = g_type_get_qdata (gtype, pygobject_class_key); if (py_type == NULL) { py_type = g_type_get_qdata (gtype, pyginterface_type_key); if (py_type == NULL) { py_type = (PyTypeObject *)pygi_type_import_by_g_type (gtype); PyErr_Clear (); } if (py_type == NULL) { py_type = pygobject_new_with_interfaces (gtype); PyErr_Clear (); g_type_set_qdata (gtype, pyginterface_type_key, py_type); } } return py_type; } /** * pygobject_new_full: * @obj: a GObject instance. * @steal: whether to steal a ref from the GObject or add (sink) a new one. * @g_class: the GObjectClass * * This function gets a reference to a wrapper for the given GObject * instance. If a wrapper has already been created, a new reference * to that wrapper will be returned. Otherwise, a wrapper instance * will be created. * * Returns: a reference to the wrapper for the GObject. */ PyObject * pygobject_new_full (GObject *obj, gboolean steal, gpointer g_class) { PyGObject *self; if (obj == NULL) { Py_RETURN_NONE; } /* If the GObject already has a PyObject wrapper stashed in its qdata, re-use it. */ self = (PyGObject *)g_object_get_qdata (obj, pygobject_wrapper_key); if (self != NULL) { /* Note the use of "pygobject_ref_sink" here only deals with PyObject * wrapper ref counts and has nothing to do with GObject. */ pygobject_ref_sink (self); /* If steal is true, we also want to decref the incoming GObjects which * already have a Python wrapper because the wrapper is already holding a * strong reference. */ if (steal) g_object_unref (obj); } else { /* create wrapper */ PyGObjectData *inst_data = pyg_object_peek_inst_data (obj); PyTypeObject *tp; if (inst_data) tp = inst_data->type; else { if (g_class) tp = pygobject_lookup_class (G_OBJECT_CLASS_TYPE (g_class)); else tp = pygobject_lookup_class (G_OBJECT_TYPE (obj)); } g_assert (tp != NULL); /* need to bump type refcount if created with pygobject_new_with_interfaces(). fixes bug #141042 */ if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) Py_INCREF (tp); self = PyObject_GC_New (PyGObject, tp); if (self == NULL) return NULL; self->inst_dict = NULL; self->weakreflist = NULL; self->private_flags.flags = 0; self->obj = obj; /* If we are not stealing a ref or the object is floating, * add a regular ref or sink the object. */ if (g_object_is_floating (obj)) self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING; if (!steal || self->private_flags.flags & PYGOBJECT_GOBJECT_WAS_FLOATING) g_object_ref_sink (obj); pygobject_register_wrapper ((PyObject *)self); PyObject_GC_Track ((PyObject *)self); } return (PyObject *)self; } PyObject * pygobject_new (GObject *obj) { return pygobject_new_full (obj, /*steal=*/FALSE, NULL); } static void pygobject_unwatch_closure (gpointer data, GClosure *closure) { PyGObjectData *inst_data = data; /* Despite no Python API is called the list inst_data->closures * must be protected by GIL as it is used by GC in * pygobject_traverse */ PyGILState_STATE state = PyGILState_Ensure (); inst_data->closures = g_slist_remove (inst_data->closures, closure); PyGILState_Release (state); } /** * pygobject_watch_closure: * @self: a GObject wrapper instance * @closure: a GClosure to watch * * Adds a closure to the list of watched closures for the wrapper. * The closure must be one returned by pyg_closure_new(). When the * cycle GC traverses the wrapper instance, it will enumerate the * references to Python objects stored in watched closures. If the * cycle GC tells the wrapper to clear itself, the watched closures * will be invalidated. */ void pygobject_watch_closure (PyObject *self, GClosure *closure) { PyGObject *gself; PyGObjectData *data; g_return_if_fail (self != NULL); g_return_if_fail (PyObject_TypeCheck (self, &PyGObject_Type)); g_return_if_fail (closure != NULL); gself = (PyGObject *)self; data = pygobject_get_inst_data (gself); g_return_if_fail (data != NULL); g_return_if_fail (g_slist_find (data->closures, closure) == NULL); data->closures = g_slist_prepend (data->closures, closure); g_closure_add_invalidate_notifier (closure, data, pygobject_unwatch_closure); } /* -------------- PyGObject behaviour ----------------- */ PYGI_DEFINE_TYPE ("gi._gi.GObject", PyGObject_Type, PyGObject); static void pygobject_dealloc (PyGObject *self) { /* Untrack must be done first. This is because followup calls such as * ClearWeakRefs could call into Python and cause new allocations to * happen, which could in turn could trigger the garbage collector, * which would then get confused as it is tracking this half-deallocated * object. */ PyObject_GC_UnTrack ((PyObject *)self); if (self->weakreflist != NULL) PyObject_ClearWeakRefs ((PyObject *)self); /* this forces inst_data->type to be updated, which could prove * important if a new wrapper has to be created and it is of a * unregistered type */ pygobject_get_inst_data (self); pygobject_clear (self); /* the following causes problems with subclassed types */ /* Py_TYPE(self)->tp_free((PyObject *)self); */ PyObject_GC_Del (self); } static PyObject * pygobject_richcompare (PyObject *self, PyObject *other, int op) { int isinst; isinst = PyObject_IsInstance (self, (PyObject *)&PyGObject_Type); if (isinst == -1) return NULL; if (!isinst) { Py_RETURN_NOTIMPLEMENTED; } isinst = PyObject_IsInstance (other, (PyObject *)&PyGObject_Type); if (isinst == -1) return NULL; if (!isinst) { Py_RETURN_NOTIMPLEMENTED; } return pyg_ptr_richcompare (((PyGObject *)self)->obj, ((PyGObject *)other)->obj, op); } static Py_hash_t pygobject_hash (PyGObject *self) { return (Py_hash_t)(gintptr)(self->obj); } static PyObject * pygobject_repr (PyGObject *self) { PyObject *module, *repr; gchar *module_str, *namespace; module = PyObject_GetAttrString ((PyObject *)self, "__module__"); if (module == NULL) return NULL; if (!PyUnicode_Check (module)) { Py_DECREF (module); return NULL; } module_str = PyUnicode_AsUTF8 (module); namespace = g_strrstr (module_str, "."); if (namespace == NULL) { namespace = module_str; } else { namespace += 1; } repr = PyUnicode_FromFormat ( "<%s.%s object at %p (%s at %p)>", namespace, Py_TYPE (self)->tp_name, self, self->obj ? G_OBJECT_TYPE_NAME (self->obj) : "uninitialized", self->obj); Py_DECREF (module); return repr; } static int pygobject_traverse (PyGObject *self, visitproc visit, void *arg) { int ret = 0; GSList *tmp; PyGObjectData *data = pygobject_get_inst_data (self); if (self->inst_dict) ret = visit (self->inst_dict, arg); if (ret != 0) return ret; /* Only let the GC track the closures when tp_clear() would free them. * https://bugzilla.gnome.org/show_bug.cgi?id=731501 */ if (data && self->obj->ref_count == 1) { for (tmp = data->closures; tmp != NULL; tmp = tmp->next) { PyGClosure *closure = tmp->data; if (closure->callback) ret = visit (closure->callback, arg); if (ret != 0) return ret; if (closure->extra_args) ret = visit (closure->extra_args, arg); if (ret != 0) return ret; if (closure->swap_data) ret = visit (closure->swap_data, arg); if (ret != 0) return ret; } } return ret; } static inline int pygobject_clear (PyGObject *self) { if (self->obj) { g_object_set_qdata_full (self->obj, pygobject_wrapper_key, NULL, NULL); if (pygobject_toggle_ref_is_active (self)) { g_object_remove_toggle_ref (self->obj, pyg_toggle_notify, NULL); self->private_flags.flags &= ~PYGOBJECT_USING_TOGGLE_REF; } else { Py_BEGIN_ALLOW_THREADS; g_object_unref (self->obj); Py_END_ALLOW_THREADS; } self->obj = NULL; } Py_CLEAR (self->inst_dict); return 0; } static void pygobject_free (PyObject *op) { PyObject_GC_Del (op); } static gboolean pygobject_prepare_construct_properties (GObjectClass *class, PyObject *kwargs, guint *n_properties, const char **names[], const GValue **values) { *n_properties = 0; *names = NULL; *values = NULL; if (kwargs) { Py_ssize_t pos = 0; PyObject *key; PyObject *value; Py_ssize_t len; len = PyDict_Size (kwargs); *names = g_new (const char *, len); *values = g_new0 (GValue, len); while (PyDict_Next (kwargs, &pos, &key, &value)) { GParamSpec *pspec; GValue *gvalue = &(*values)[*n_properties]; const gchar *key_str = PyUnicode_AsUTF8 (key); pspec = g_object_class_find_property (class, key_str); if (!pspec) { PyErr_Format (PyExc_TypeError, "gobject `%s' doesn't support property `%s'", G_OBJECT_CLASS_NAME (class), key_str); return FALSE; } g_value_init (gvalue, G_PARAM_SPEC_VALUE_TYPE (pspec)); if (pyg_param_gvalue_from_pyobject (gvalue, value, pspec) < 0) { PyErr_Format ( PyExc_TypeError, "could not convert value for property `%s' from %s to %s", key_str, Py_TYPE (value)->tp_name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec))); return FALSE; } (*names)[*n_properties] = g_strdup (key_str); ++(*n_properties); } } return TRUE; } /* ---------------- PyGObject methods ----------------- */ static int pygobject_init (PyGObject *self, PyObject *args, PyObject *kwargs) { GType object_type; guint n_properties = 0, i; const GValue *values = NULL; const char **names = NULL; GObjectClass *class; /* Only do GObject creation and property setting if the GObject hasn't * already been created. The case where self->obj already exists can occur * when C constructors are called directly (Gtk.Button.new_with_label) * and we are simply wrapping the result with a PyGObject. * In these cases we want to ignore any keyword arguments passed along * to __init__ and simply return. * * See: https://bugzilla.gnome.org/show_bug.cgi?id=705810 */ if (self->obj != NULL) return 0; if (!PyArg_ParseTuple (args, ":GObject.__init__", NULL)) return -1; object_type = pyg_type_from_object ((PyObject *)self); if (!object_type) return -1; if (G_TYPE_IS_ABSTRACT (object_type)) { PyErr_Format (PyExc_TypeError, "cannot create instance of abstract " "(non-instantiable) type `%s'", g_type_name (object_type)); return -1; } if ((class = g_type_class_ref (object_type)) == NULL) { PyErr_SetString (PyExc_TypeError, "could not get a reference to type class"); return -1; } if (!pygobject_prepare_construct_properties (class, kwargs, &n_properties, &names, &values)) goto cleanup; if (pygobject_constructv (self, n_properties, names, values)) PyErr_SetString (PyExc_RuntimeError, "could not create object"); cleanup: for (i = 0; i < n_properties; i++) { g_free (names[i]); g_value_unset (&values[i]); } g_free (names); g_free (values); g_type_class_unref (class); return (self->obj) ? 0 : -1; } #define CHECK_GOBJECT(self) \ if (!G_IS_OBJECT (self->obj)) { \ PyErr_Format (PyExc_TypeError, \ "object at %p of type %s is not initialized", self, \ Py_TYPE (self)->tp_name); \ return NULL; \ } static PyObject * pygobject_get_property (PyGObject *self, PyObject *args) { gchar *param_name; if (!PyArg_ParseTuple (args, "s:GObject.get_property", ¶m_name)) { return NULL; } CHECK_GOBJECT (self); return pygi_get_property_value_by_name (self, param_name); } static PyObject * pygobject_get_properties (PyGObject *self, PyObject *args) { Py_ssize_t len, i; PyObject *tuple; if ((len = PyTuple_Size (args)) < 1) { PyErr_SetString (PyExc_TypeError, "requires at least one argument"); return NULL; } tuple = PyTuple_New (len); for (i = 0; i < len; i++) { PyObject *py_property = PyTuple_GetItem (args, i); gchar *property_name; PyObject *item; if (!PyUnicode_Check (py_property)) { PyErr_SetString (PyExc_TypeError, "Expected string argument for property."); goto fail; } property_name = PyUnicode_AsUTF8 (py_property); item = pygi_get_property_value_by_name (self, property_name); PyTuple_SetItem (tuple, i, item); } return tuple; fail: Py_DECREF (tuple); return NULL; } static PyObject * pygobject_set_property (PyGObject *self, PyObject *args) { gchar *param_name; GParamSpec *pspec; PyObject *pvalue; int ret = -1; if (!PyArg_ParseTuple (args, "sO:GObject.set_property", ¶m_name, &pvalue)) return NULL; CHECK_GOBJECT (self); pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (self->obj), param_name); if (!pspec) { PyErr_Format (PyExc_TypeError, "object of type `%s' does not have property `%s'", g_type_name (G_OBJECT_TYPE (self->obj)), param_name); return NULL; } ret = pygi_set_property_value (self, pspec, pvalue); if (ret == 0) goto done; else if (PyErr_Occurred ()) return NULL; if (!set_property_from_pspec (self->obj, pspec, pvalue)) return NULL; done: Py_RETURN_NONE; } static PyObject * pygobject_set_properties (PyGObject *self, PyObject *args, PyObject *kwargs) { GObjectClass *class; Py_ssize_t pos; PyObject *value; PyObject *key; PyObject *result = NULL; CHECK_GOBJECT (self); class = G_OBJECT_GET_CLASS (self->obj); g_object_freeze_notify (G_OBJECT (self->obj)); pos = 0; while (kwargs && PyDict_Next (kwargs, &pos, &key, &value)) { gchar *key_str = PyUnicode_AsUTF8 (key); GParamSpec *pspec; int ret = -1; pspec = g_object_class_find_property (class, key_str); if (!pspec) { gchar buf[512]; g_snprintf (buf, sizeof (buf), "object `%s' doesn't support property `%s'", g_type_name (G_OBJECT_TYPE (self->obj)), key_str); PyErr_SetString (PyExc_TypeError, buf); goto exit; } ret = pygi_set_property_value (self, pspec, value); if (ret != 0) { /* Non-zero return code means that either an error occured ...*/ if (PyErr_Occurred ()) goto exit; /* ... or the property couldn't be found , so let's try the default * call. */ if (!set_property_from_pspec (G_OBJECT (self->obj), pspec, value)) goto exit; } } result = Py_None; exit: g_object_thaw_notify (G_OBJECT (self->obj)); return Py_XNewRef (result); } /* custom closure for gobject bindings */ static void pygbinding_closure_invalidate (gpointer data, GClosure *closure) { PyGClosure *pc = (PyGClosure *)closure; PyGILState_STATE state; state = PyGILState_Ensure (); Py_XDECREF (pc->callback); Py_XDECREF (pc->extra_args); PyGILState_Release (state); pc->callback = NULL; pc->extra_args = NULL; } static void pygbinding_marshal (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data) { PyGILState_STATE state; PyGClosure *pc = (PyGClosure *)closure; PyObject *params, *ret; GValue *out_value; state = PyGILState_Ensure (); /* construct Python tuple for the parameter values */ params = PyTuple_New (2); PyTuple_SetItem (params, 0, pyg_value_as_pyobject (¶m_values[0], FALSE)); PyTuple_SetItem (params, 1, pyg_value_as_pyobject (¶m_values[1], FALSE)); /* params passed to function may have extra arguments */ if (pc->extra_args) { PyObject *tuple = params; params = PySequence_Concat (tuple, pc->extra_args); Py_DECREF (tuple); } ret = PyObject_CallObject (pc->callback, params); if (!ret) { PyErr_Print (); goto out; } else if (Py_IsNone (ret)) { g_value_set_boolean (return_value, FALSE); goto out; } out_value = g_value_get_boxed (¶m_values[2]); if (pyg_value_from_pyobject (out_value, ret) != 0) { PyErr_SetString (PyExc_ValueError, "can't convert value"); PyErr_Print (); g_value_set_boolean (return_value, FALSE); } else { g_value_set_boolean (return_value, TRUE); } Py_DECREF (ret); out: Py_DECREF (params); PyGILState_Release (state); } static GClosure * pygbinding_closure_new (PyObject *callback, PyObject *extra_args) { GClosure *closure; g_return_val_if_fail (callback != NULL, NULL); closure = g_closure_new_simple (sizeof (PyGClosure), NULL); g_closure_add_invalidate_notifier (closure, NULL, pygbinding_closure_invalidate); g_closure_set_marshal (closure, pygbinding_marshal); Py_INCREF (callback); ((PyGClosure *)closure)->callback = callback; if (extra_args && !Py_IsNone (extra_args)) { Py_INCREF (extra_args); if (!PyTuple_Check (extra_args)) { PyObject *tmp = PyTuple_New (1); PyTuple_SetItem (tmp, 0, extra_args); extra_args = tmp; } ((PyGClosure *)closure)->extra_args = extra_args; } return closure; } static PyObject * pygobject_bind_property (PyGObject *self, PyObject *args, PyObject *kwargs) { gchar *source_name, *target_name; gchar *source_canon, *target_canon; PyObject *target, *source_repr, *target_repr; PyObject *transform_to, *transform_from, *user_data = NULL; GBinding *binding; GBindingFlags flags = G_BINDING_DEFAULT; GClosure *to_closure = NULL, *from_closure = NULL; transform_from = NULL; transform_to = NULL; static char *kwlist[] = { "source_property", "target", "target_property", "flags", "transform_to", "transform_from", "user_data", NULL }; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "sOs|iOOO:GObject.bind_property", kwlist, &source_name, &target, &target_name, &flags, &transform_to, &transform_from, &user_data)) return NULL; CHECK_GOBJECT (self); if (!PyObject_TypeCheck (target, &PyGObject_Type)) { PyErr_SetString (PyExc_TypeError, "Second argument must be a GObject"); return NULL; } if (transform_to && !Py_IsNone (transform_to)) { if (!PyCallable_Check (transform_to)) { PyErr_SetString (PyExc_TypeError, "transform_to must be callable or None"); return NULL; } to_closure = pygbinding_closure_new (transform_to, user_data); } if (transform_from && !Py_IsNone (transform_from)) { if (!PyCallable_Check (transform_from)) { PyErr_SetString (PyExc_TypeError, "transform_from must be callable or None"); return NULL; } from_closure = pygbinding_closure_new (transform_from, user_data); } /* Canonicalize underscores to hyphens. Note the results must be freed. */ source_canon = g_strdelimit (g_strdup (source_name), "_", '-'); target_canon = g_strdelimit (g_strdup (target_name), "_", '-'); binding = g_object_bind_property_with_closures ( G_OBJECT (self->obj), source_canon, pygobject_get (target), target_canon, flags, to_closure, from_closure); g_free (source_canon); g_free (target_canon); source_canon = target_canon = NULL; if (binding == NULL) { source_repr = PyObject_Repr ((PyObject *)self); target_repr = PyObject_Repr (target); PyErr_Format (PyExc_TypeError, "Cannot create binding from %s.%s to %s.%s", PyUnicode_AsUTF8 (source_repr), source_name, PyUnicode_AsUTF8 (target_repr), target_name); Py_DECREF (source_repr); Py_DECREF (target_repr); return NULL; } return pygobject_new (G_OBJECT (binding)); } static PyObject * connect_helper (PyGObject *self, gchar *name, PyObject *callback, PyObject *extra_args, PyObject *object, gboolean after) { guint sigid; GQuark detail = 0; GClosure *closure = NULL; gulong handlerid; GSignalQuery query_info; if (!g_signal_parse_name (name, G_OBJECT_TYPE (self->obj), &sigid, &detail, TRUE)) { PyObject *repr = PyObject_Repr ((PyObject *)self); PyErr_Format (PyExc_TypeError, "%s: unknown signal name: %s", PyUnicode_AsUTF8 (repr), name); Py_DECREF (repr); return NULL; } if (object && !PyObject_TypeCheck (object, &PyGObject_Type)) { if (PyErr_WarnEx (PyGIDeprecationWarning, "Using non GObject arguments for connect_object() " "is deprecated, use: " "connect_data(signal, callback, data, " "connect_flags=GObject.ConnectFlags.SWAPPED)", 1)) { return NULL; } } g_signal_query (sigid, &query_info); if (!pyg_gtype_is_custom (query_info.itype)) { /* The signal is implemented by a non-Python class, probably * something in the gi repository. */ closure = pygi_signal_closure_new (self, query_info.itype, query_info.signal_name, callback, extra_args, object); } if (!closure) { /* The signal is either implemented at the Python level, or it comes * from a foreign class that we don't have introspection data for. */ closure = pyg_closure_new (callback, extra_args, object); } pygobject_watch_closure ((PyObject *)self, closure); handlerid = g_signal_connect_closure_by_id (self->obj, sigid, detail, closure, after); return pygi_gulong_to_py (handlerid); } static PyObject * pygobject_connect (PyGObject *self, PyObject *args) { PyObject *first, *callback, *extra_args, *ret; gchar *name; Py_ssize_t len; len = PyTuple_Size (args); if (len < 2) { PyErr_SetString (PyExc_TypeError, "GObject.connect requires at least 2 arguments"); return NULL; } first = PySequence_GetSlice (args, 0, 2); if (!PyArg_ParseTuple (first, "sO:GObject.connect", &name, &callback)) { Py_DECREF (first); return NULL; } Py_DECREF (first); if (!PyCallable_Check (callback)) { PyErr_SetString (PyExc_TypeError, "second argument must be callable"); return NULL; } CHECK_GOBJECT (self); extra_args = PySequence_GetSlice (args, 2, len); if (extra_args == NULL) return NULL; ret = connect_helper (self, name, callback, extra_args, NULL, FALSE); Py_DECREF (extra_args); return ret; } static PyObject * pygobject_connect_after (PyGObject *self, PyObject *args) { PyObject *first, *callback, *extra_args, *ret; gchar *name; Py_ssize_t len; len = PyTuple_Size (args); if (len < 2) { PyErr_SetString ( PyExc_TypeError, "GObject.connect_after requires at least 2 arguments"); return NULL; } first = PySequence_GetSlice (args, 0, 2); if (!PyArg_ParseTuple (first, "sO:GObject.connect_after", &name, &callback)) { Py_DECREF (first); return NULL; } Py_DECREF (first); if (!PyCallable_Check (callback)) { PyErr_SetString (PyExc_TypeError, "second argument must be callable"); return NULL; } CHECK_GOBJECT (self); extra_args = PySequence_GetSlice (args, 2, len); if (extra_args == NULL) return NULL; ret = connect_helper (self, name, callback, extra_args, NULL, TRUE); Py_DECREF (extra_args); return ret; } static PyObject * pygobject_connect_object (PyGObject *self, PyObject *args) { PyObject *first, *callback, *extra_args, *object, *ret; gchar *name; Py_ssize_t len; len = PyTuple_Size (args); if (len < 3) { PyErr_SetString ( PyExc_TypeError, "GObject.connect_object requires at least 3 arguments"); return NULL; } first = PySequence_GetSlice (args, 0, 3); if (!PyArg_ParseTuple (first, "sOO:GObject.connect_object", &name, &callback, &object)) { Py_DECREF (first); return NULL; } Py_DECREF (first); if (!PyCallable_Check (callback)) { PyErr_SetString (PyExc_TypeError, "second argument must be callable"); return NULL; } CHECK_GOBJECT (self); extra_args = PySequence_GetSlice (args, 3, len); if (extra_args == NULL) return NULL; ret = connect_helper (self, name, callback, extra_args, object, FALSE); Py_DECREF (extra_args); return ret; } static PyObject * pygobject_connect_object_after (PyGObject *self, PyObject *args) { PyObject *first, *callback, *extra_args, *object, *ret; gchar *name; Py_ssize_t len; len = PyTuple_Size (args); if (len < 3) { PyErr_SetString ( PyExc_TypeError, "GObject.connect_object_after requires at least 3 arguments"); return NULL; } first = PySequence_GetSlice (args, 0, 3); if (!PyArg_ParseTuple (first, "sOO:GObject.connect_object_after", &name, &callback, &object)) { Py_DECREF (first); return NULL; } Py_DECREF (first); if (!PyCallable_Check (callback)) { PyErr_SetString (PyExc_TypeError, "second argument must be callable"); return NULL; } CHECK_GOBJECT (self); extra_args = PySequence_GetSlice (args, 3, len); if (extra_args == NULL) return NULL; ret = connect_helper (self, name, callback, extra_args, object, TRUE); Py_DECREF (extra_args); return ret; } static PyObject * pygobject_emit (PyGObject *self, PyObject *args) { guint signal_id, i, j; Py_ssize_t len; GQuark detail; PyObject *first, *py_ret, *repr = NULL; gchar *name; GSignalQuery query; GValue *params, ret = { 0, }; len = PyTuple_Size (args); if (len < 1) { PyErr_SetString (PyExc_TypeError, "GObject.emit needs at least one arg"); return NULL; } first = PySequence_GetSlice (args, 0, 1); if (!PyArg_ParseTuple (first, "s:GObject.emit", &name)) { Py_DECREF (first); return NULL; } Py_DECREF (first); CHECK_GOBJECT (self); if (!g_signal_parse_name (name, G_OBJECT_TYPE (self->obj), &signal_id, &detail, TRUE)) { repr = PyObject_Repr ((PyObject *)self); PyErr_Format (PyExc_TypeError, "%s: unknown signal name: %s", PyUnicode_AsUTF8 (repr), name); Py_DECREF (repr); return NULL; } g_signal_query (signal_id, &query); if ((gsize)len != query.n_params + 1) { gchar buf[128]; g_snprintf (buf, sizeof (buf), "%d parameters needed for signal %s; %ld given", query.n_params, name, (long int)(len - 1)); PyErr_SetString (PyExc_TypeError, buf); return NULL; } params = g_new0 (GValue, query.n_params + 1); g_value_init (¶ms[0], G_OBJECT_TYPE (self->obj)); g_value_set_object (¶ms[0], G_OBJECT (self->obj)); for (i = 0; i < query.n_params; i++) g_value_init (¶ms[i + 1], query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE); for (i = 0; i < query.n_params; i++) { PyObject *item = PyTuple_GetItem (args, i + 1); if (pyg_value_from_pyobject (¶ms[i + 1], item) < 0) { gchar buf[128]; g_snprintf ( buf, sizeof (buf), "could not convert type %s to %s required for parameter %d", Py_TYPE (item)->tp_name, G_VALUE_TYPE_NAME (¶ms[i + 1]), i); PyErr_SetString (PyExc_TypeError, buf); for (j = 0; j <= i; j++) g_value_unset (¶ms[j]); g_free (params); return NULL; } } if (query.return_type != G_TYPE_NONE) g_value_init (&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); Py_BEGIN_ALLOW_THREADS; g_signal_emitv (params, signal_id, detail, &ret); Py_END_ALLOW_THREADS; for (i = 0; i < query.n_params + 1; i++) g_value_unset (¶ms[i]); g_free (params); if ((query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE) != G_TYPE_NONE) { gboolean was_floating = FALSE; if (G_VALUE_HOLDS_OBJECT (&ret)) { GObject *obj = g_value_get_object (&ret); if (obj != NULL && G_IS_OBJECT (obj)) { was_floating = g_object_is_floating (obj); } } py_ret = pyg_value_as_pyobject (&ret, TRUE); if (!was_floating) g_value_unset (&ret); } else { py_ret = Py_NewRef (Py_None); } return py_ret; } static PyObject * pygobject_chain_from_overridden (PyGObject *self, PyObject *args) { GSignalInvocationHint *ihint; guint signal_id, i; Py_ssize_t len; PyObject *py_ret; const gchar *name; GSignalQuery query; GValue *params, ret = { 0, }; CHECK_GOBJECT (self); ihint = g_signal_get_invocation_hint (self->obj); if (!ihint) { PyErr_SetString (PyExc_TypeError, "could not find signal invocation " "information for this object."); return NULL; } signal_id = ihint->signal_id; name = g_signal_name (signal_id); len = PyTuple_Size (args); if (signal_id == 0) { PyErr_SetString (PyExc_TypeError, "unknown signal name"); return NULL; } g_signal_query (signal_id, &query); if (len < 0 || (gsize)len != query.n_params) { gchar buf[128]; g_snprintf (buf, sizeof (buf), "%d parameters needed for signal %s; %ld given", query.n_params, name, (long int)len); PyErr_SetString (PyExc_TypeError, buf); return NULL; } params = g_new0 (GValue, query.n_params + 1); g_value_init (¶ms[0], G_OBJECT_TYPE (self->obj)); g_value_set_object (¶ms[0], G_OBJECT (self->obj)); for (i = 0; i < query.n_params; i++) g_value_init (¶ms[i + 1], query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE); for (i = 0; i < query.n_params; i++) { PyObject *item = PyTuple_GetItem (args, i); if (pyg_boxed_check ( item, query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) { g_value_set_static_boxed (¶ms[i + 1], pyg_boxed_get (item, void)); } else if (pyg_value_from_pyobject (¶ms[i + 1], item) < 0) { gchar buf[128]; g_snprintf ( buf, sizeof (buf), "could not convert type %s to %s required for parameter %d", Py_TYPE (item)->tp_name, g_type_name (G_VALUE_TYPE (¶ms[i + 1])), i); PyErr_SetString (PyExc_TypeError, buf); for (i = 0; i < query.n_params + 1; i++) g_value_unset (¶ms[i]); g_free (params); return NULL; } } if (query.return_type != G_TYPE_NONE) g_value_init (&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); g_signal_chain_from_overridden (params, &ret); for (i = 0; i < query.n_params + 1; i++) g_value_unset (¶ms[i]); g_free (params); if (query.return_type != G_TYPE_NONE) { py_ret = pyg_value_as_pyobject (&ret, TRUE); g_value_unset (&ret); } else { py_ret = Py_NewRef (Py_None); } return py_ret; } static PyObject * pygobject_weak_ref (PyGObject *self, PyObject *args) { Py_ssize_t len; PyObject *callback = NULL, *user_data = NULL; PyObject *retval; CHECK_GOBJECT (self); if ((len = PySequence_Length (args)) >= 1) { callback = PySequence_ITEM (args, 0); user_data = PySequence_GetSlice (args, 1, len); } retval = pygobject_weak_ref_new (self->obj, callback, user_data); Py_XDECREF (callback); Py_XDECREF (user_data); return retval; } static PyObject * pygobject_do_dispose (PyObject *self) { Py_RETURN_NONE; } static PyObject * pygobject_copy (PyGObject *self) { PyErr_SetString (PyExc_TypeError, "GObject descendants' instances are non-copyable"); return NULL; } static PyObject * pygobject_deepcopy (PyGObject *self, PyObject *args) { PyErr_SetString (PyExc_TypeError, "GObject descendants' instances are non-copyable"); return NULL; } static PyObject * pygobject_disconnect_by_func (PyGObject *self, PyObject *args) { PyObject *pyfunc = NULL, *repr = NULL; GClosure *closure = NULL; guint retval; CHECK_GOBJECT (self); if (!PyArg_ParseTuple (args, "O:GObject.disconnect_by_func", &pyfunc)) return NULL; if (!PyCallable_Check (pyfunc)) { PyErr_SetString (PyExc_TypeError, "first argument must be callable"); return NULL; } closure = gclosure_from_pyfunc (self, pyfunc); if (!closure) { repr = PyObject_Repr ((PyObject *)pyfunc); PyErr_Format (PyExc_TypeError, "nothing connected to %s", PyUnicode_AsUTF8 (repr)); Py_DECREF (repr); return NULL; } retval = g_signal_handlers_disconnect_matched ( self->obj, G_SIGNAL_MATCH_CLOSURE, 0, 0, closure, NULL, NULL); return pygi_guint_to_py (retval); } static PyObject * pygobject_handler_block_by_func (PyGObject *self, PyObject *args) { PyObject *pyfunc = NULL, *repr = NULL; GClosure *closure = NULL; guint retval; CHECK_GOBJECT (self); if (!PyArg_ParseTuple (args, "O:GObject.handler_block_by_func", &pyfunc)) return NULL; if (!PyCallable_Check (pyfunc)) { PyErr_SetString (PyExc_TypeError, "first argument must be callable"); return NULL; } closure = gclosure_from_pyfunc (self, pyfunc); if (!closure) { repr = PyObject_Repr ((PyObject *)pyfunc); PyErr_Format (PyExc_TypeError, "nothing connected to %s", PyUnicode_AsUTF8 (repr)); Py_DECREF (repr); return NULL; } retval = g_signal_handlers_block_matched ( self->obj, G_SIGNAL_MATCH_CLOSURE, 0, 0, closure, NULL, NULL); return pygi_guint_to_py (retval); } static PyObject * pygobject_handler_unblock_by_func (PyGObject *self, PyObject *args) { PyObject *pyfunc = NULL, *repr = NULL; GClosure *closure = NULL; guint retval; CHECK_GOBJECT (self); if (!PyArg_ParseTuple (args, "O:GObject.handler_unblock_by_func", &pyfunc)) return NULL; if (!PyCallable_Check (pyfunc)) { PyErr_SetString (PyExc_TypeError, "first argument must be callable"); return NULL; } closure = gclosure_from_pyfunc (self, pyfunc); if (!closure) { repr = PyObject_Repr ((PyObject *)pyfunc); PyErr_Format (PyExc_TypeError, "nothing connected to %s", PyUnicode_AsUTF8 (repr)); Py_DECREF (repr); return NULL; } retval = g_signal_handlers_unblock_matched ( self->obj, G_SIGNAL_MATCH_CLOSURE, 0, 0, closure, NULL, NULL); return pygi_guint_to_py (retval); } static PyMethodDef pygobject_methods[] = { { "get_property", (PyCFunction)pygobject_get_property, METH_VARARGS }, { "get_properties", (PyCFunction)pygobject_get_properties, METH_VARARGS }, { "set_property", (PyCFunction)pygobject_set_property, METH_VARARGS }, { "set_properties", (PyCFunction)pygobject_set_properties, METH_VARARGS | METH_KEYWORDS }, { "bind_property", (PyCFunction)pygobject_bind_property, METH_VARARGS | METH_KEYWORDS }, { "connect", (PyCFunction)pygobject_connect, METH_VARARGS }, { "connect_after", (PyCFunction)pygobject_connect_after, METH_VARARGS }, { "connect_object", (PyCFunction)pygobject_connect_object, METH_VARARGS }, { "connect_object_after", (PyCFunction)pygobject_connect_object_after, METH_VARARGS }, { "disconnect_by_func", (PyCFunction)pygobject_disconnect_by_func, METH_VARARGS }, { "handler_block_by_func", (PyCFunction)pygobject_handler_block_by_func, METH_VARARGS }, { "handler_unblock_by_func", (PyCFunction)pygobject_handler_unblock_by_func, METH_VARARGS }, { "emit", (PyCFunction)pygobject_emit, METH_VARARGS }, { "chain", (PyCFunction)pygobject_chain_from_overridden, METH_VARARGS }, { "weak_ref", (PyCFunction)pygobject_weak_ref, METH_VARARGS }, { "do_dispose", (PyCFunction)pygobject_do_dispose, METH_NOARGS }, { "__copy__", (PyCFunction)pygobject_copy, METH_NOARGS }, { "__deepcopy__", (PyCFunction)pygobject_deepcopy, METH_VARARGS }, { NULL, NULL, 0 }, }; #ifdef PYGI_OBJECT_USE_CUSTOM_DICT static PyObject * pygobject_get_dict (PyGObject *self, void *closure) { if (self->inst_dict == NULL) { self->inst_dict = PyDict_New (); pygobject_toggle_ref_ensure (self); } return Py_NewRef (self->inst_dict); } #endif static PyObject * pygobject_get_refcount (PyGObject *self, void *closure) { if (self->obj == NULL) { PyErr_Format (PyExc_TypeError, "GObject instance is not yet created"); return NULL; } return pygi_guint_to_py (self->obj->ref_count); } static PyObject * pygobject_get_pointer (PyGObject *self, void *closure) { return PyCapsule_New (self->obj, NULL, NULL); } static int pygobject_setattro (PyObject *self, PyObject *name, PyObject *value) { int res; res = PyGObject_Type.tp_base->tp_setattro (self, name, value); pygobject_toggle_ref_ensure ((PyGObject *)self); return res; } static PyGetSetDef pygobject_getsets[] = { #ifdef PYGI_OBJECT_USE_CUSTOM_DICT { "__dict__", (getter)pygobject_get_dict, (setter)0 }, #endif { "__grefcount__", (getter)pygobject_get_refcount, (setter)0, }, { "__gpointer__", (getter)pygobject_get_pointer, (setter)0, }, { NULL, 0, 0 }, }; /* ------------------------------------ */ /* ****** GObject weak reference ****** */ /* ------------------------------------ */ typedef struct { PyObject_HEAD GObject *obj; PyObject *callback; PyObject *user_data; gboolean have_floating_ref; } PyGObjectWeakRef; PYGI_DEFINE_TYPE ("gi._gi.GObjectWeakRef", PyGObjectWeakRef_Type, PyGObjectWeakRef); static int pygobject_weak_ref_traverse (PyGObjectWeakRef *self, visitproc visit, void *arg) { if (self->callback && visit (self->callback, arg) < 0) return -1; if (self->user_data && visit (self->user_data, arg) < 0) return -1; return 0; } static void pygobject_weak_ref_notify (PyGObjectWeakRef *self, GObject *dummy) { self->obj = NULL; if (self->callback) { PyObject *retval; PyGILState_STATE state = PyGILState_Ensure (); retval = PyObject_Call (self->callback, self->user_data, NULL); if (retval) { if (!Py_IsNone (retval)) PyErr_Format (PyExc_TypeError, "GObject weak notify callback returned a value" " of type %s, should return None", Py_TYPE (retval)->tp_name); Py_DECREF (retval); PyErr_Print (); } else PyErr_Print (); Py_CLEAR (self->callback); Py_CLEAR (self->user_data); if (self->have_floating_ref) { self->have_floating_ref = FALSE; Py_DECREF ((PyObject *)self); } PyGILState_Release (state); } } static inline int pygobject_weak_ref_clear (PyGObjectWeakRef *self) { Py_CLEAR (self->callback); Py_CLEAR (self->user_data); if (self->obj) { g_object_weak_unref (self->obj, (GWeakNotify)pygobject_weak_ref_notify, self); self->obj = NULL; } return 0; } static void pygobject_weak_ref_dealloc (PyGObjectWeakRef *self) { PyObject_GC_UnTrack ((PyObject *)self); pygobject_weak_ref_clear (self); PyObject_GC_Del (self); } static PyObject * pygobject_weak_ref_new (GObject *obj, PyObject *callback, PyObject *user_data) { PyGObjectWeakRef *self; self = PyObject_GC_New (PyGObjectWeakRef, &PyGObjectWeakRef_Type); self->callback = callback; self->user_data = user_data; Py_XINCREF (self->callback); Py_XINCREF (self->user_data); self->obj = obj; g_object_weak_ref (self->obj, (GWeakNotify)pygobject_weak_ref_notify, self); if (callback != NULL) { /* when we have a callback, we should INCREF the weakref * object to make it stay alive even if it goes out of scope */ self->have_floating_ref = TRUE; Py_INCREF ((PyObject *)self); } return (PyObject *)self; } static PyObject * pygobject_weak_ref_unref (PyGObjectWeakRef *self, PyObject *args) { if (!self->obj) { PyErr_SetString (PyExc_ValueError, "weak ref already unreffed"); return NULL; } g_object_weak_unref (self->obj, (GWeakNotify)pygobject_weak_ref_notify, self); self->obj = NULL; if (self->have_floating_ref) { self->have_floating_ref = FALSE; Py_DECREF (self); } Py_RETURN_NONE; } static PyMethodDef pygobject_weak_ref_methods[] = { { "unref", (PyCFunction)pygobject_weak_ref_unref, METH_NOARGS }, { NULL, NULL, 0 }, }; static PyObject * pygobject_weak_ref_call (PyGObjectWeakRef *self, PyObject *args, PyObject *kw) { static char *argnames[] = { NULL }; if (!PyArg_ParseTupleAndKeywords (args, kw, ":__call__", argnames)) return NULL; if (self->obj) return pygobject_new (self->obj); else { Py_RETURN_NONE; } } static gpointer pyobject_copy (gpointer boxed) { PyObject *object = boxed; PyGILState_STATE state; state = PyGILState_Ensure (); Py_INCREF (object); PyGILState_Release (state); return object; } static void pyobject_free (gpointer boxed) { PyObject *object = boxed; PyGILState_STATE state; state = PyGILState_Ensure (); Py_DECREF (object); PyGILState_Release (state); } /** * Returns 0 on success, or -1 and sets an exception. */ int pyi_object_register_types (PyObject *d) { PyObject *o, *descr; pygobject_custom_key = g_quark_from_static_string ("PyGObject::custom"); pygobject_class_key = g_quark_from_static_string ("PyGObject::class"); pygobject_class_init_key = g_quark_from_static_string ("PyGObject::class-init"); pygobject_wrapper_key = g_quark_from_static_string ("PyGObject::wrapper"); pygobject_has_updated_constructor_key = g_quark_from_static_string ("PyGObject::has-updated-constructor"); pygobject_instance_data_key = g_quark_from_static_string ("PyGObject::instance-data"); /* GObject */ if (!PY_TYPE_OBJECT) PY_TYPE_OBJECT = g_boxed_type_register_static ( "PyObject", pyobject_copy, pyobject_free); PyGObject_Type.tp_dealloc = (destructor)pygobject_dealloc; PyGObject_Type.tp_richcompare = pygobject_richcompare; PyGObject_Type.tp_repr = (reprfunc)pygobject_repr; PyGObject_Type.tp_hash = (hashfunc)pygobject_hash; PyGObject_Type.tp_setattro = (setattrofunc)pygobject_setattro; PyGObject_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC); PyGObject_Type.tp_traverse = (traverseproc)pygobject_traverse; PyGObject_Type.tp_clear = (inquiry)pygobject_clear; PyGObject_Type.tp_weaklistoffset = offsetof (PyGObject, weakreflist); PyGObject_Type.tp_methods = pygobject_methods; PyGObject_Type.tp_getset = pygobject_getsets; #ifdef PYGI_OBJECT_USE_CUSTOM_DICT PyGObject_Type.tp_dictoffset = offsetof (PyGObject, inst_dict); #endif PyGObject_Type.tp_init = (initproc)pygobject_init; PyGObject_Type.tp_free = (freefunc)pygobject_free; PyGObject_Type.tp_alloc = PyType_GenericAlloc; PyGObject_Type.tp_new = PyType_GenericNew; pygobject_register_class (d, "GObject", G_TYPE_OBJECT, &PyGObject_Type, NULL); PyDict_SetItemString (PyGObject_Type.tp_dict, "__gdoc__", pyg_object_descr_doc_get ()); /* GProps */ PyGProps_Type.tp_dealloc = (destructor)PyGProps_dealloc; PyGProps_Type.tp_as_sequence = (PySequenceMethods *)&_PyGProps_as_sequence; PyGProps_Type.tp_getattro = (getattrofunc)PyGProps_getattro; PyGProps_Type.tp_setattro = (setattrofunc)PyGProps_setattro; PyGProps_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC; PyGProps_Type.tp_doc = "The properties of the GObject accessible as " "Python attributes."; PyGProps_Type.tp_traverse = (traverseproc)pygobject_props_traverse; PyGProps_Type.tp_iter = (getiterfunc)pygobject_props_get_iter; PyGProps_Type.tp_methods = pygobject_props_methods; if (PyType_Ready (&PyGProps_Type) < 0) return -1; /* GPropsDescr */ PyGPropsDescr_Type.tp_flags = Py_TPFLAGS_DEFAULT; PyGPropsDescr_Type.tp_descr_get = pyg_props_descr_descr_get; if (PyType_Ready (&PyGPropsDescr_Type) < 0) return -1; descr = PyObject_New (PyObject, &PyGPropsDescr_Type); PyDict_SetItemString (PyGObject_Type.tp_dict, "props", descr); PyDict_SetItemString (PyGObject_Type.tp_dict, "__module__", o = PyUnicode_FromString ("gi._gi")); Py_DECREF (o); /* GPropsIter */ PyGPropsIter_Type.tp_dealloc = (destructor)pyg_props_iter_dealloc; PyGPropsIter_Type.tp_flags = Py_TPFLAGS_DEFAULT; PyGPropsIter_Type.tp_doc = "GObject properties iterator"; PyGPropsIter_Type.tp_iter = PyObject_SelfIter; PyGPropsIter_Type.tp_iternext = (iternextfunc)pygobject_props_iter_next; if (PyType_Ready (&PyGPropsIter_Type) < 0) return -1; PyGObjectWeakRef_Type.tp_dealloc = (destructor)pygobject_weak_ref_dealloc; PyGObjectWeakRef_Type.tp_call = (ternaryfunc)pygobject_weak_ref_call; PyGObjectWeakRef_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC; PyGObjectWeakRef_Type.tp_doc = "A GObject weak reference"; PyGObjectWeakRef_Type.tp_traverse = (traverseproc)pygobject_weak_ref_traverse; PyGObjectWeakRef_Type.tp_clear = (inquiry)pygobject_weak_ref_clear; PyGObjectWeakRef_Type.tp_methods = pygobject_weak_ref_methods; if (PyType_Ready (&PyGObjectWeakRef_Type) < 0) return -1; PyDict_SetItemString (d, "GObjectWeakRef", (PyObject *)&PyGObjectWeakRef_Type); return 0; } PyObject * pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs) { PyObject *pytype; GType type; GObject *obj = NULL; GObjectClass *class; guint n_properties = 0, i; const GValue *values = NULL; const char **names = NULL; if (!PyArg_ParseTuple (args, "O:gobject.new", &pytype)) { return NULL; } if ((type = pyg_type_from_object (pytype)) == 0) return NULL; if (G_TYPE_IS_ABSTRACT (type)) { PyErr_Format (PyExc_TypeError, "cannot create instance of abstract " "(non-instantiable) type `%s'", g_type_name (type)); return NULL; } if ((class = g_type_class_ref (type)) == NULL) { PyErr_SetString (PyExc_TypeError, "could not get a reference to type class"); return NULL; } if (!pygobject_prepare_construct_properties (class, kwargs, &n_properties, &names, &values)) goto cleanup; obj = pygobject_object_new_with_properties (type, n_properties, names, values); if (!obj) PyErr_SetString (PyExc_RuntimeError, "could not create object"); cleanup: for (i = 0; i < n_properties; i++) { g_free (names[i]); g_value_unset (&values[i]); } g_free (names); g_free (values); g_type_class_unref (class); if (obj) { pygobject_sink (obj); self = (PyGObject *)pygobject_new ((GObject *)obj); g_object_unref (obj); } else self = NULL; return (PyObject *)self; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygobject-object.h0000664000000000000000000000343115074673150016351 0ustar00rootroot#ifndef _PYGOBJECT_OBJECT_H_ #define _PYGOBJECT_OBJECT_H_ #include #include #include "pygobject-internal.h" /* Data that belongs to the GObject instance, not the Python wrapper */ struct _PyGObjectData { PyTypeObject *type; /* wrapper type for this instance */ GSList *closures; }; extern GType PY_TYPE_OBJECT; extern GQuark pygobject_instance_data_key; extern GQuark pygobject_custom_key; extern GQuark pygobject_wrapper_key; extern GQuark pygobject_class_key; extern GQuark pygobject_class_init_key; extern PyTypeObject PyGObjectWeakRef_Type; extern PyTypeObject PyGPropsIter_Type; extern PyTypeObject PyGPropsDescr_Type; extern PyTypeObject PyGProps_Type; extern PyTypeObject PyGObject_Type; extern PyTypeObject *PyGObject_MetaType; static inline PyGObjectData * pyg_object_peek_inst_data (GObject *obj) { return ((PyGObjectData *)g_object_get_qdata (obj, pygobject_instance_data_key)); } void pygobject_register_class (PyObject *dict, const gchar *type_name, GType gtype, PyTypeObject *type, PyObject *bases); void pygobject_register_wrapper (PyObject *self); PyObject *pygobject_new (GObject *obj); PyObject *pygobject_new_full (GObject *obj, gboolean steal, gpointer g_class); void pygobject_sink (GObject *obj); PyTypeObject *pygobject_lookup_class (GType gtype); void pygobject_watch_closure (PyObject *self, GClosure *closure); int pyi_object_register_types (PyObject *d); void pygobject_ref_float (PyGObject *self); void pygobject_ref_sink (PyGObject *self); PyObject *pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs); GClosure *gclosure_from_pyfunc (PyGObject *object, PyObject *func); #endif /*_PYGOBJECT_OBJECT_H_*/ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygobject.h0000664000000000000000000006572215074673150015120 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- */ #ifndef _PYGOBJECT_H_ #define _PYGOBJECT_H_ #include #include #include G_BEGIN_DECLS /* PyGClosure is a _private_ structure */ typedef void (*PyClosureExceptionHandler) (GValue *ret, guint n_param_values, const GValue *params); typedef struct _PyGClosure PyGClosure; typedef struct _PyGObjectData PyGObjectData; struct _PyGClosure { GClosure closure; PyObject *callback; PyObject *extra_args; /* tuple of extra args to pass to callback */ PyObject *swap_data; /* other object for gtk_signal_connect__object */ PyClosureExceptionHandler exception_handler; }; typedef enum { PYGOBJECT_USING_TOGGLE_REF = 1 << 0, PYGOBJECT_IS_FLOATING_REF = 1 << 1, PYGOBJECT_GOBJECT_WAS_FLOATING = 1 << 2 } PyGObjectFlags; /* closures is just an alias for what is found in the * PyGObjectData */ typedef struct { PyObject_HEAD GObject *obj; PyObject *inst_dict; /* the instance dictionary -- must be last */ PyObject *weakreflist; /* list of weak references */ /*< private >*/ /* using union to preserve ABI compatibility (structure size * must not change) */ union { GSList *closures; /* stale field; no longer updated DO-NOT-USE! */ PyGObjectFlags flags; } private_flags; } PyGObject; #define pygobject_get(v) (((PyGObject *)(v))->obj) #define pygobject_check(v, base) (PyObject_TypeCheck (v, base)) typedef struct { PyObject_HEAD gpointer boxed; GType gtype; gboolean free_on_dealloc; } PyGBoxed; #define pyg_boxed_get(v, t) ((t *)((PyGBoxed *)(v))->boxed) #define pyg_boxed_get_ptr(v) (((PyGBoxed *)(v))->boxed) #define pyg_boxed_set_ptr(v, p) (((PyGBoxed *)(v))->boxed = (gpointer)p) #define pyg_boxed_check(v, typecode) \ (PyObject_TypeCheck (v, &PyGBoxed_Type) \ && ((PyGBoxed *)(v))->gtype == (typecode)) typedef struct { PyObject_HEAD gpointer pointer; GType gtype; } PyGPointer; #define pyg_pointer_get(v, t) ((t *)((PyGPointer *)(v))->pointer) #define pyg_pointer_get_ptr(v) (((PyGPointer *)(v))->pointer) #define pyg_pointer_set_ptr(v, p) (((PyGPointer *)(v))->pointer = (gpointer)p) #define pyg_pointer_check(v, typecode) \ (PyObject_TypeCheck (v, &PyGPointer_Type) \ && ((PyGPointer *)(v))->gtype == (typecode)) typedef void (*PyGFatalExceptionFunc) (void); typedef void (*PyGThreadBlockFunc) (void); typedef int (*PyGClassInitFunc) (gpointer gclass, PyTypeObject *pyclass); typedef PyTypeObject *(*PyGTypeRegistrationFunction) (const gchar *name, gpointer data); struct _PyGObject_Functions { /* * All field names in here are considered private, * use the macros below instead, which provides stability */ void (*register_class) (PyObject *dict, const gchar *class_name, GType gtype, PyTypeObject *type, PyObject *bases); void (*register_wrapper) (PyObject *self); PyTypeObject *(*lookup_class) (GType type); PyObject *(*newgobj) (GObject *obj); GClosure *(*closure_new) (PyObject *callback, PyObject *extra_args, PyObject *swap_data); void (*object_watch_closure) (PyObject *self, GClosure *closure); GDestroyNotify destroy_notify; GType (*type_from_object) (PyObject *obj); PyObject *(*type_wrapper_new) (GType type); gint (*enum_get_value) (GType enum_type, PyObject *obj, gint *val); gint (*flags_get_value) (GType flag_type, PyObject *obj, guint *val); void (*register_gtype_custom) ( GType gtype, PyObject *(*from_func) (const GValue *value), int (*to_func) (GValue *value, PyObject *obj)); int (*value_from_pyobject) (GValue *value, PyObject *obj); PyObject *(*value_as_pyobject) (const GValue *value, gboolean copy_boxed); void (*register_interface) (PyObject *dict, const gchar *class_name, GType gtype, PyTypeObject *type); PyTypeObject *boxed_type; void (*register_boxed) (PyObject *dict, const gchar *class_name, GType boxed_type, PyTypeObject *type); PyObject *(*boxed_new) (GType boxed_type, gpointer boxed, gboolean copy_boxed, gboolean own_ref); PyTypeObject *pointer_type; void (*register_pointer) (PyObject *dict, const gchar *class_name, GType pointer_type, PyTypeObject *type); PyObject *(*pointer_new) (GType boxed_type, gpointer pointer); void (*enum_add_constants) (PyObject *module, GType enum_type, const gchar *strip_prefix); void (*flags_add_constants) (PyObject *module, GType flags_type, const gchar *strip_prefix); const gchar *(*constant_strip_prefix) (const gchar *name, const gchar *strip_prefix); gboolean (*error_check) (GError **error); /* hooks to register handlers for getting GDK threads to cooperate * with python threading */ void (*set_thread_block_funcs) (PyGThreadBlockFunc block_threads_func, PyGThreadBlockFunc unblock_threads_func); PyGThreadBlockFunc block_threads; PyGThreadBlockFunc unblock_threads; PyTypeObject *paramspec_type; PyObject *(*paramspec_new) (GParamSpec *spec); GParamSpec *(*paramspec_get) (PyObject *tuple); int (*pyobj_to_unichar_conv) (PyObject *pyobj, void *ptr); G_GNUC_BEGIN_IGNORE_DEPRECATIONS gboolean (*parse_constructor_args) (GType obj_type, char **arg_names, char **prop_names, GParameter *params, guint *nparams, PyObject **py_args); G_GNUC_END_IGNORE_DEPRECATIONS PyObject *(*param_gvalue_as_pyobject) (const GValue *gvalue, gboolean copy_boxed, const GParamSpec *pspec); int (*gvalue_from_param_pyobject) (GValue *value, PyObject *py_obj, const GParamSpec *pspec); PyTypeObject *enum_type; PyObject *(*enum_add) (PyObject *module, const char *type_name_, const char *strip_prefix, GType gtype); PyObject *(*enum_from_gtype) (GType gtype, int value); PyTypeObject *flags_type; PyObject *(*flags_add) (PyObject *module, const char *type_name_, const char *strip_prefix, GType gtype); PyObject *(*flags_from_gtype) (GType gtype, guint value); gboolean threads_enabled; int (*enable_threads) (void); int (*gil_state_ensure) (void); void (*gil_state_release) (int flag); void (*register_class_init) (GType gtype, PyGClassInitFunc class_init); void (*register_interface_info) (GType gtype, const GInterfaceInfo *info); void (*closure_set_exception_handler) (GClosure *closure, PyClosureExceptionHandler handler); void (*add_warning_redirection) (const char *domain, PyObject *warning); void (*disable_warning_redirections) (void); /* type_register_custom API now removed, but leave a pointer here to not * break ABI. */ void *_type_register_custom; gboolean (*gerror_exception_check) (GError **error); PyObject *(*option_group_new) (GOptionGroup *group); GType (*type_from_object_strict) (PyObject *obj, gboolean strict); PyObject *(*newgobj_full) (GObject *obj, gboolean steal, gpointer g_class); PyTypeObject *object_type; int (*value_from_pyobject_with_error) (GValue *value, PyObject *obj); }; /* Deprecated, only available for API compatibility. */ #define pyg_threads_enabled TRUE #define pyg_gil_state_ensure PyGILState_Ensure #define pyg_gil_state_release PyGILState_Release #define pyg_begin_allow_threads Py_BEGIN_ALLOW_THREADS #define pyg_end_allow_threads Py_END_ALLOW_THREADS #define pyg_enable_threads() #define pyg_set_thread_block_funcs(a, b) #define pyg_block_threads() #define pyg_unblock_threads() #ifndef _INSIDE_PYGOBJECT_ #if defined(NO_IMPORT) || defined(NO_IMPORT_PYGOBJECT) extern struct _PyGObject_Functions *_PyGObject_API; #else struct _PyGObject_Functions *_PyGObject_API; #endif #define pygobject_register_class (_PyGObject_API->register_class) #define pygobject_register_wrapper (_PyGObject_API->register_wrapper) #define pygobject_lookup_class (_PyGObject_API->lookup_class) #define pygobject_new (_PyGObject_API->newgobj) #define pygobject_new_full (_PyGObject_API->newgobj_full) #define PyGObject_Type (*_PyGObject_API->object_type) #define pyg_closure_new (_PyGObject_API->closure_new) #define pygobject_watch_closure (_PyGObject_API->object_watch_closure) #define pyg_closure_set_exception_handler \ (_PyGObject_API->closure_set_exception_handler) #define pyg_destroy_notify (_PyGObject_API->destroy_notify) #define pyg_type_from_object_strict (_PyGObject_API->type_from_object_strict) #define pyg_type_from_object (_PyGObject_API->type_from_object) #define pyg_type_wrapper_new (_PyGObject_API->type_wrapper_new) #define pyg_enum_get_value (_PyGObject_API->enum_get_value) #define pyg_flags_get_value (_PyGObject_API->flags_get_value) #define pyg_register_gtype_custom (_PyGObject_API->register_gtype_custom) #define pyg_value_from_pyobject (_PyGObject_API->value_from_pyobject) #define pyg_value_from_pyobject_with_error \ (_PyGObject_API->value_from_pyobject_with_error) #define pyg_value_as_pyobject (_PyGObject_API->value_as_pyobject) #define pyg_register_interface (_PyGObject_API->register_interface) #define PyGBoxed_Type (*_PyGObject_API->boxed_type) #define pyg_register_boxed (_PyGObject_API->register_boxed) #define pyg_boxed_new (_PyGObject_API->boxed_new) #define PyGPointer_Type (*_PyGObject_API->pointer_type) #define pyg_register_pointer (_PyGObject_API->register_pointer) #define pyg_pointer_new (_PyGObject_API->pointer_new) #define pyg_enum_add_constants (_PyGObject_API->enum_add_constants) #define pyg_flags_add_constants (_PyGObject_API->flags_add_constants) #define pyg_constant_strip_prefix (_PyGObject_API->constant_strip_prefix) #define pyg_error_check (_PyGObject_API->error_check) #define PyGParamSpec_Type (*_PyGObject_API->paramspec_type) #define pyg_param_spec_new (_PyGObject_API->paramspec_new) #define pyg_param_spec_from_object (_PyGObject_API->paramspec_get) #define pyg_pyobj_to_unichar_conv (_PyGObject_API->pyobj_to_unichar_conv) #define pyg_parse_constructor_args (_PyGObject_API->parse_constructor_args) #define pyg_param_gvalue_as_pyobject (_PyGObject_API->value_as_pyobject) #define pyg_param_gvalue_from_pyobject \ (_PyGObject_API->gvalue_from_param_pyobject) #define PyGEnum_Type (*_PyGObject_API->enum_type) #define pyg_enum_add (_PyGObject_API->enum_add) #define pyg_enum_from_gtype (_PyGObject_API->enum_from_gtype) #define PyGFlags_Type (*_PyGObject_API->flags_type) #define pyg_flags_add (_PyGObject_API->flags_add) #define pyg_flags_from_gtype (_PyGObject_API->flags_from_gtype) #define pyg_register_class_init (_PyGObject_API->register_class_init) #define pyg_register_interface_info (_PyGObject_API->register_interface_info) #define pyg_add_warning_redirection (_PyGObject_API->add_warning_redirection) #define pyg_disable_warning_redirections \ (_PyGObject_API->disable_warning_redirections) #define pyg_gerror_exception_check (_PyGObject_API->gerror_exception_check) #define pyg_option_group_new (_PyGObject_API->option_group_new) /** * pygobject_init: * @req_major: minimum version major number, or -1 * @req_minor: minimum version minor number, or -1 * @req_micro: minimum version micro number, or -1 * * Imports and initializes the 'gobject' python module. Can * optionally check for a required minimum version if @req_major, * @req_minor, and @req_micro are all different from -1. * * Returns: a new reference to the gobject module on success, NULL in * case of failure (and raises ImportError). **/ static inline PyObject * pygobject_init (int req_major, int req_minor, int req_micro) { PyObject *gobject, *cobject; gobject = PyImport_ImportModule ("gi._gobject"); if (!gobject) { if (PyErr_Occurred ()) { PyObject *type, *value, *traceback; PyObject *py_orig_exc; PyErr_Fetch (&type, &value, &traceback); py_orig_exc = PyObject_Repr (value); Py_XDECREF (type); Py_XDECREF (value); Py_XDECREF (traceback); #if PY_VERSION_HEX < 0x03000000 PyErr_Format (PyExc_ImportError, "could not import gobject (error was: %s)", PyString_AsString (py_orig_exc)); #else { /* Can not use PyErr_Format because it doesn't have * a format string for dealing with PyUnicode objects * like PyUnicode_FromFormat has */ PyObject *errmsg = PyUnicode_FromFormat ( "could not import gobject (error was: %U)", py_orig_exc); if (errmsg) { PyErr_SetObject (PyExc_ImportError, errmsg); Py_DECREF (errmsg); } /* if errmsg is NULL then we might have OOM * PyErr should already be set and trying to * return our own error would be futile */ } #endif Py_DECREF (py_orig_exc); } else { PyErr_SetString (PyExc_ImportError, "could not import gobject (no error given)"); } return NULL; } cobject = PyObject_GetAttrString (gobject, "_PyGObject_API"); if (cobject && PyCapsule_CheckExact (cobject)) { _PyGObject_API = (struct _PyGObject_Functions *)PyCapsule_GetPointer ( cobject, "gobject._PyGObject_API"); Py_DECREF (cobject); } else { PyErr_SetString ( PyExc_ImportError, "could not import gobject (could not find _PyGObject_API object)"); Py_XDECREF (cobject); Py_DECREF (gobject); return NULL; } if (req_major != -1) { int found_major, found_minor, found_micro; PyObject *version; version = PyObject_GetAttrString (gobject, "pygobject_version"); if (!version) { PyErr_SetString (PyExc_ImportError, "could not import gobject (version too old)"); Py_DECREF (gobject); return NULL; } if (!PyArg_ParseTuple (version, "iii", &found_major, &found_minor, &found_micro)) { PyErr_SetString ( PyExc_ImportError, "could not import gobject (version has invalid format)"); Py_DECREF (version); Py_DECREF (gobject); return NULL; } Py_DECREF (version); if (req_major != found_major || req_minor > found_minor || (req_minor == found_minor && req_micro > found_micro)) { PyErr_Format (PyExc_ImportError, "could not import gobject (version mismatch, " "%d.%d.%d is required, " "found %d.%d.%d)", req_major, req_minor, req_micro, found_major, found_minor, found_micro); Py_DECREF (gobject); return NULL; } } return gobject; } /** * PYLIST_FROMGLIBLIST: * @type: the type of the GLib list e.g. #GList or #GSList * @prefix: the prefix of functions that manipulate a list of the type * given by type. * * A macro that creates a type specific code block which converts a GLib * list (#GSList or #GList) to a Python list. The first two args of the macro * are used to specify the type and list function prefix so that the type * specific macros can be generated. * * The rest of the args are for the standard args for the type specific * macro(s) created from this macro. */ #define PYLIST_FROMGLIBLIST(type, prefix, py_list, list, item_convert_func, \ list_free, list_item_free) \ G_STMT_START \ { \ gint i, len; \ PyObject *item; \ void (*glib_list_free) (type *) = list_free; \ GFunc glib_list_item_free = (GFunc)list_item_free; \ \ len = prefix##_length (list); \ py_list = PyList_New (len); \ for (i = 0; i < len; i++) { \ gpointer list_item = prefix##_nth_data (list, i); \ \ item = item_convert_func; \ PyList_SetItem (py_list, i, item); \ } \ if (glib_list_item_free != NULL) \ prefix##_foreach (list, glib_list_item_free, NULL); \ if (glib_list_free != NULL) glib_list_free (list); \ } \ G_STMT_END /** * PYLIST_FROMGLIST: * @py_list: the name of the Python list * * @list: the #GList to be converted to a Python list * * @item_convert_func: the function that converts a list item to a Python * object. The function must refer to the list item using "@list_item" and * must return a #PyObject* object. An example conversion function is: * [[ * PyString_FromString(list_item) * ]] * A more elaborate function is: * [[ * pyg_boxed_new(GTK_TYPE_RECENT_INFO, list_item, TRUE, TRUE) * ]] * @list_free: the name of a function that takes a single arg (the list) and * frees its memory. Can be NULL if the list should not be freed. An example * is: * [[ * g_list_free * ]] * @list_item_free: the name of a #GFunc function that frees the memory used * by the items in the list or %NULL if the list items do not have to be * freed. A simple example is: * [[ * g_free * ]] * * A macro that adds code that converts a #GList to a Python list. * */ #define PYLIST_FROMGLIST(py_list, list, item_convert_func, list_free, \ list_item_free) \ PYLIST_FROMGLIBLIST (GList, g_list, py_list, list, item_convert_func, \ list_free, list_item_free) /** * PYLIST_FROMGSLIST: * @py_list: the name of the Python list * * @list: the #GSList to be converted to a Python list * * @item_convert_func: the function that converts a list item to a Python * object. The function must refer to the list item using "@list_item" and * must return a #PyObject* object. An example conversion function is: * [[ * PyString_FromString(list_item) * ]] * A more elaborate function is: * [[ * pyg_boxed_new(GTK_TYPE_RECENT_INFO, list_item, TRUE, TRUE) * ]] * @list_free: the name of a function that takes a single arg (the list) and * frees its memory. Can be %NULL if the list should not be freed. An example * is: * [[ * g_list_free * ]] * @list_item_free: the name of a #GFunc function that frees the memory used * by the items in the list or %NULL if the list items do not have to be * freed. A simple example is: * [[ * g_free * ]] * * A macro that adds code that converts a #GSList to a Python list. * */ #define PYLIST_FROMGSLIST(py_list, list, item_convert_func, list_free, \ list_item_free) \ PYLIST_FROMGLIBLIST (GSList, g_slist, py_list, list, item_convert_func, \ list_free, list_item_free) /** * PYLIST_ASGLIBLIST * @type: the type of the GLib list e.g. GList or GSList * @prefix: the prefix of functions that manipulate a list of the type * given by type e.g. g_list or g_slist * * A macro that creates a type specific code block to be used to convert a * Python list to a GLib list (GList or GSList). The first two args of the * macro are used to specify the type and list function prefix so that the * type specific macros can be generated. * * The rest of the args are for the standard args for the type specific * macro(s) created from this macro. */ #define PYLIST_ASGLIBLIST(type, prefix, py_list, list, check_func, \ convert_func, child_free_func, errormsg, \ errorreturn) \ G_STMT_START \ { \ Py_ssize_t i, n_list; \ GFunc glib_child_free_func = (GFunc)child_free_func; \ \ if (!(py_list = PySequence_Fast (py_list, ""))) { \ errormsg; \ return errorreturn; \ } \ n_list = PySequence_Fast_GET_SIZE (py_list); \ for (i = 0; i < n_list; i++) { \ PyObject *py_item = PySequence_Fast_GET_ITEM (py_list, i); \ \ if (!check_func) { \ if (glib_child_free_func) \ prefix##_foreach (list, glib_child_free_func, NULL); \ prefix##_free (list); \ Py_DECREF (py_list); \ errormsg; \ return errorreturn; \ } \ list = prefix##_prepend (list, convert_func); \ }; \ Py_DECREF (py_list); \ list = prefix##_reverse (list); \ } \ G_STMT_END /** * PYLIST_ASGLIST * @py_list: the Python list to be converted * @list: the #GList list to be converted * @check_func: the expression that takes a #PyObject* arg (must be named * @py_item) and returns an int value indicating if the Python object matches * the required list item type (0 - %False or 1 - %True). An example is: * [[ * (PyString_Check(py_item)||PyUnicode_Check(py_item)) * ]] * @convert_func: the function that takes a #PyObject* arg (must be named * py_item) and returns a pointer to the converted list object. An example * is: * [[ * pygobject_get(py_item) * ]] * @child_free_func: the name of a #GFunc function that frees a GLib list * item or %NULL if the list item does not have to be freed. This function is * used to help free the items in a partially created list if there is an * error. An example is: * [[ * g_free * ]] * @errormsg: a function that sets up a Python error message. An example is: * [[ * PyErr_SetString(PyExc_TypeError, "strings must be a sequence of" "strings * or unicode objects") * ]] * @errorreturn: the value to return if an error occurs, e.g.: * [[ * %NULL * ]] * * A macro that creates code that converts a Python list to a #GList. The * returned list must be freed using the appropriate list free function when * it's no longer needed. If an error occurs the child_free_func is used to * release the memory used by the list items and then the list memory is * freed. */ #define PYLIST_ASGLIST(py_list, list, check_func, convert_func, \ child_free_func, errormsg, errorreturn) \ PYLIST_ASGLIBLIST (GList, g_list, py_list, list, check_func, \ convert_func, child_free_func, errormsg, errorreturn) /** * PYLIST_ASGSLIST * @py_list: the Python list to be converted * @list: the #GSList list to be converted * @check_func: the expression that takes a #PyObject* arg (must be named * @py_item) and returns an int value indicating if the Python object matches * the required list item type (0 - %False or 1 - %True). An example is: * [[ * (PyString_Check(py_item)||PyUnicode_Check(py_item)) * ]] * @convert_func: the function that takes a #PyObject* arg (must be named * py_item) and returns a pointer to the converted list object. An example * is: * [[ * pygobject_get(py_item) * ]] * @child_free_func: the name of a #GFunc function that frees a GLib list * item or %NULL if the list item does not have to be freed. This function is * used to help free the items in a partially created list if there is an * error. An example is: * [[ * g_free * ]] * @errormsg: a function that sets up a Python error message. An example is: * [[ * PyErr_SetString(PyExc_TypeError, "strings must be a sequence of" "strings * or unicode objects") * ]] * @errorreturn: the value to return if an error occurs, e.g.: * [[ * %NULL * ]] * * A macro that creates code that converts a Python list to a #GSList. The * returned list must be freed using the appropriate list free function when * it's no longer needed. If an error occurs the child_free_func is used to * release the memory used by the list items and then the list memory is * freed. */ #define PYLIST_ASGSLIST(py_list, list, check_func, convert_func, \ child_free_func, errormsg, errorreturn) \ PYLIST_ASGLIBLIST (GSList, g_slist, py_list, list, check_func, \ convert_func, child_free_func, errormsg, errorreturn) #endif /* !_INSIDE_PYGOBJECT_ */ G_END_DECLS #endif /* !_PYGOBJECT_H_ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygoptioncontext.c0000664000000000000000000002610615074673150016553 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 2006 Johannes Hoelzl * * pygoptioncontext.c: GOptionContext wrapper * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-basictype.h" #include "pygi-error.h" #include "pygi-util.h" #include "pygoptioncontext.h" PYGI_DEFINE_TYPE ("gi._gi.OptionContext", PyGOptionContext_Type, PyGOptionContext) /** * pyg_option_group_transfer_group: * @group: a GOptionGroup wrapper * * This is used to transfer the GOptionGroup to a GOptionContext. After this * is called, the calle must handle the release of the GOptionGroup. * * When #NULL is returned, the GOptionGroup was already transfered. * * Returns: Either #NULL or the wrapped GOptionGroup. */ static GOptionGroup * pyglib_option_group_transfer_group (PyObject *obj) { PyGOptionGroup *self = (PyGOptionGroup *)obj; if (self->is_in_context) return NULL; self->is_in_context = TRUE; /* Here we increase the reference count of the PyGOptionGroup, because now * the GOptionContext holds an reference to us (it is the userdata passed * to g_option_group_new(). * * The GOptionGroup is freed with the GOptionContext. * * We set it here because if we would do this in the init method we would * hold two references and the PyGOptionGroup would never be freed. */ Py_INCREF (self); return self->group; } /** * pyg_option_context_new: * @context: a GOptionContext * * Returns: A new GOptionContext wrapper. */ PyObject * pyg_option_context_new (GOptionContext *context) { PyGOptionContext *self; self = (PyGOptionContext *)PyObject_New (PyGOptionContext, &PyGOptionContext_Type); if (self == NULL) return NULL; self->context = context; self->main_group = NULL; return (PyObject *)self; } static int pyg_option_context_init (PyGOptionContext *self, PyObject *args, PyObject *kwargs) { char *parameter_string; if (!PyArg_ParseTuple (args, "s:gi._gi.GOptionContext.__init__", ¶meter_string)) return -1; self->context = g_option_context_new (parameter_string); return 0; } static void pyg_option_context_dealloc (PyGOptionContext *self) { Py_CLEAR (self->main_group); if (self->context != NULL) { GOptionContext *tmp = self->context; self->context = NULL; g_option_context_free (tmp); } PyObject_Free (self); } static PyObject * pyg_option_context_parse (PyGOptionContext *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "argv", NULL }; PyObject *arg; PyObject *new_argv, *argv; Py_ssize_t argv_length, pos; gint argv_length_int; char **argv_content, **original; GError *error = NULL; gboolean result; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O:GOptionContext.parse", kwlist, &argv)) return NULL; if (!PyList_Check (argv)) { PyErr_SetString (PyExc_TypeError, "GOptionContext.parse expects a list of strings."); return NULL; } argv_length = PyList_Size (argv); if (argv_length == -1) { PyErr_SetString (PyExc_TypeError, "GOptionContext.parse expects a list of strings."); return NULL; } argv_content = g_new (char *, argv_length + 1); argv_content[argv_length] = NULL; for (pos = 0; pos < argv_length; pos++) { arg = PyList_GetItem (argv, pos); argv_content[pos] = g_strdup (PyUnicode_AsUTF8 (arg)); if (argv_content[pos] == NULL) { g_strfreev (argv_content); return NULL; } } original = g_strdupv (argv_content); g_assert (argv_length <= G_MAXINT); argv_length_int = (gint)argv_length; Py_BEGIN_ALLOW_THREADS; result = g_option_context_parse (self->context, &argv_length_int, &argv_content, &error); Py_END_ALLOW_THREADS; argv_length = argv_length_int; if (!result) { g_strfreev (argv_content); g_strfreev (original); pygi_error_check (&error); return NULL; } new_argv = PyList_New (g_strv_length (argv_content)); for (pos = 0; pos < argv_length; pos++) { arg = PyUnicode_FromString (argv_content[pos]); PyList_SetItem (new_argv, pos, arg); } g_strfreev (original); g_strfreev (argv_content); return new_argv; } static PyObject * pyg_option_context_set_help_enabled (PyGOptionContext *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "help_enable", NULL }; PyObject *help_enabled; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O:GOptionContext.set_help_enabled", kwlist, &help_enabled)) return NULL; g_option_context_set_help_enabled (self->context, PyObject_IsTrue (help_enabled)); Py_RETURN_NONE; } static PyObject * pyg_option_context_get_help_enabled (PyGOptionContext *self) { return pygi_gboolean_to_py ( g_option_context_get_help_enabled (self->context)); } static PyObject * pyg_option_context_set_ignore_unknown_options (PyGOptionContext *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "ignore_unknown_options", NULL }; PyObject *ignore_unknown_options; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "O:GOptionContext.set_ignore_unknown_options", kwlist, &ignore_unknown_options)) return NULL; g_option_context_set_ignore_unknown_options ( self->context, PyObject_IsTrue (ignore_unknown_options)); Py_RETURN_NONE; } static PyObject * pyg_option_context_get_ignore_unknown_options (PyGOptionContext *self) { return pygi_gboolean_to_py ( g_option_context_get_ignore_unknown_options (self->context)); } static PyObject * pyg_option_context_set_main_group (PyGOptionContext *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "group", NULL }; GOptionGroup *g_group; PyObject *group; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "O:GOptionContext.set_main_group", kwlist, &group)) return NULL; if (PyObject_IsInstance (group, (PyObject *)&PyGOptionGroup_Type) != 1) { PyErr_SetString ( PyExc_TypeError, "GOptionContext.set_main_group expects a GOptionGroup."); return NULL; } g_group = pyglib_option_group_transfer_group (group); if (g_group == NULL) { PyErr_SetString (PyExc_RuntimeError, "Group is already in a OptionContext."); return NULL; } g_option_context_set_main_group (self->context, g_group); self->main_group = (PyGOptionGroup *)Py_NewRef (group); Py_RETURN_NONE; } static PyObject * pyg_option_context_get_main_group (PyGOptionContext *self) { if (self->main_group == NULL) { Py_RETURN_NONE; } return Py_NewRef (self->main_group); } static PyObject * pyg_option_context_add_group (PyGOptionContext *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "group", NULL }; GOptionGroup *g_group; PyObject *group; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "O:GOptionContext.add_group", kwlist, &group)) return NULL; if (PyObject_IsInstance (group, (PyObject *)&PyGOptionGroup_Type) != 1) { PyErr_SetString (PyExc_TypeError, "GOptionContext.add_group expects a GOptionGroup."); return NULL; } g_group = pyglib_option_group_transfer_group (group); if (g_group == NULL) { PyErr_SetString (PyExc_RuntimeError, "Group is already in a OptionContext."); return NULL; } Py_INCREF (group); g_option_context_add_group (self->context, g_group); Py_RETURN_NONE; } static PyObject * pyg_option_context_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE (self) == Py_TYPE (other) && Py_TYPE (self) == &PyGOptionContext_Type) return pyg_ptr_richcompare (((PyGOptionContext *)self)->context, ((PyGOptionContext *)other)->context, op); else { Py_RETURN_NOTIMPLEMENTED; } } static PyObject * pyg_option_get_context (PyGOptionContext *self) { return PyCapsule_New (self->context, "goption.context", NULL); } static PyMethodDef pyg_option_context_methods[] = { { "parse", (PyCFunction)pyg_option_context_parse, METH_VARARGS | METH_KEYWORDS }, { "set_help_enabled", (PyCFunction)pyg_option_context_set_help_enabled, METH_VARARGS | METH_KEYWORDS }, { "get_help_enabled", (PyCFunction)pyg_option_context_get_help_enabled, METH_NOARGS }, { "set_ignore_unknown_options", (PyCFunction)pyg_option_context_set_ignore_unknown_options, METH_VARARGS | METH_KEYWORDS }, { "get_ignore_unknown_options", (PyCFunction)pyg_option_context_get_ignore_unknown_options, METH_NOARGS }, { "set_main_group", (PyCFunction)pyg_option_context_set_main_group, METH_VARARGS | METH_KEYWORDS }, { "get_main_group", (PyCFunction)pyg_option_context_get_main_group, METH_NOARGS }, { "add_group", (PyCFunction)pyg_option_context_add_group, METH_VARARGS | METH_KEYWORDS }, { "_get_context", (PyCFunction)pyg_option_get_context, METH_NOARGS }, { NULL, NULL, 0 }, }; /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_option_context_register_types (PyObject *d) { PyGOptionContext_Type.tp_dealloc = (destructor)pyg_option_context_dealloc; PyGOptionContext_Type.tp_richcompare = pyg_option_context_richcompare; PyGOptionContext_Type.tp_flags = Py_TPFLAGS_DEFAULT; PyGOptionContext_Type.tp_methods = pyg_option_context_methods; PyGOptionContext_Type.tp_init = (initproc)pyg_option_context_init; PyGOptionContext_Type.tp_alloc = PyType_GenericAlloc; PyGOptionContext_Type.tp_new = PyType_GenericNew; if (PyType_Ready (&PyGOptionContext_Type)) return -1; PyDict_SetItemString (d, "OptionContext", (PyObject *)&PyGOptionContext_Type); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygoptioncontext.h0000664000000000000000000000234615074673150016560 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pyglib - Python bindings for GLib toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYG_OPTIONCONTEXT_H__ #define __PYG_OPTIONCONTEXT_H__ #include "pygoptiongroup.h" extern PyTypeObject PyGOptionContext_Type; typedef struct { PyObject_HEAD PyGOptionGroup *main_group; GOptionContext *context; } PyGOptionContext; PyObject *pyg_option_context_new (GOptionContext *context); int pygi_option_context_register_types (PyObject *d); #endif /* __PYG_OPTIONCONTEXT_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygoptiongroup.c0000664000000000000000000002133515074673150016222 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygobject - Python bindings for the GLib, GObject and GIO * Copyright (C) 2006 Johannes Hoelzl * * pygoptiongroup.c: GOptionContext and GOptionGroup wrapper * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-error.h" #include "pygi-util.h" #include "pygoptiongroup.h" PYGI_DEFINE_TYPE ("gi._gi.OptionGroup", PyGOptionGroup_Type, PyGOptionGroup) /** * pyg_option_group_new: * @group: a GOptionGroup * * The returned GOptionGroup can't be used to set any hooks, translation domains * or add entries. It's only intend is, to use for GOptionContext.add_group(). * * Returns: the GOptionGroup wrapper. */ PyObject * pyg_option_group_new (GOptionGroup *group) { PyGOptionGroup *self; self = (PyGOptionGroup *)PyObject_New (PyGOptionGroup, &PyGOptionGroup_Type); if (self == NULL) return NULL; self->group = group; self->other_owner = TRUE; self->is_in_context = FALSE; return (PyObject *)self; } static gboolean check_if_owned (PyGOptionGroup *self) { if (self->other_owner) { PyErr_SetString ( PyExc_ValueError, "The GOptionGroup was not created by " "gi._gi.OptionGroup(), so operation is not possible."); return TRUE; } return FALSE; } static void destroy_g_group (PyGOptionGroup *self) { PyGILState_STATE state; state = PyGILState_Ensure (); self->group = NULL; Py_CLEAR (self->callback); g_slist_foreach (self->strings, (GFunc)g_free, NULL); g_slist_free (self->strings); self->strings = NULL; if (self->is_in_context) { Py_DECREF (self); } PyGILState_Release (state); } static int pyg_option_group_init (PyGOptionGroup *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "name", "description", "help_description", "callback", NULL }; char *name, *description, *help_description; PyObject *callback; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "zzzO:GOptionGroup.__init__", kwlist, &name, &description, &help_description, &callback)) return -1; self->group = g_option_group_new (name, description, help_description, self, (GDestroyNotify)destroy_g_group); self->other_owner = FALSE; self->is_in_context = FALSE; self->callback = Py_NewRef (callback); return 0; } static void pyg_option_group_dealloc (PyGOptionGroup *self) { if (!self->other_owner && !self->is_in_context) { GOptionGroup *tmp = self->group; self->group = NULL; if (tmp) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_option_group_free (tmp); G_GNUC_END_IGNORE_DEPRECATIONS } } PyObject_Free (self); } static gboolean arg_func (const gchar *option_name, const gchar *value, PyGOptionGroup *self, GError **error) { PyObject *ret; PyGILState_STATE state; gboolean no_error; state = PyGILState_Ensure (); if (value == NULL) ret = PyObject_CallFunction (self->callback, "sOO", option_name, Py_None, self); else ret = PyObject_CallFunction (self->callback, "ssO", option_name, value, self); if (ret != NULL) { Py_DECREF (ret); no_error = TRUE; } else no_error = pygi_gerror_exception_check (error) != -1; PyGILState_Release (state); return no_error; } static PyObject * pyg_option_group_add_entries (PyGOptionGroup *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "entries", NULL }; gssize entry_count, pos; PyObject *entry_tuple, *list; GOptionEntry *entries; if (check_if_owned (self)) return NULL; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "O:GOptionGroup.add_entries", kwlist, &list)) return NULL; if (!PyList_Check (list)) { PyErr_SetString ( PyExc_TypeError, "GOptionGroup.add_entries expected a list of entries"); return NULL; } entry_count = PyList_Size (list); if (entry_count == -1) { PyErr_SetString ( PyExc_TypeError, "GOptionGroup.add_entries expected a list of entries"); return NULL; } entries = g_new0 (GOptionEntry, entry_count + 1); for (pos = 0; pos < entry_count; pos++) { gchar *long_name, *description, *arg_description; entry_tuple = PyList_GetItem (list, pos); if (!PyTuple_Check (entry_tuple)) { PyErr_SetString (PyExc_TypeError, "GOptionGroup.add_entries " "expected a list of entries"); g_free (entries); return NULL; } if (!PyArg_ParseTuple ( entry_tuple, "scisz", &long_name, &(entries[pos].short_name), &(entries[pos].flags), &description, &arg_description)) { PyErr_SetString (PyExc_TypeError, "GOptionGroup.add_entries " "expected a list of entries"); g_free (entries); return NULL; } long_name = g_strdup (long_name); self->strings = g_slist_prepend (self->strings, long_name); entries[pos].long_name = long_name; description = g_strdup (description); self->strings = g_slist_prepend (self->strings, description); entries[pos].description = description; arg_description = g_strdup (arg_description); self->strings = g_slist_prepend (self->strings, arg_description); entries[pos].arg_description = arg_description; entries[pos].arg = G_OPTION_ARG_CALLBACK; entries[pos].arg_data = arg_func; } g_option_group_add_entries (self->group, entries); g_free (entries); Py_RETURN_NONE; } static PyObject * pyg_option_group_set_translation_domain (PyGOptionGroup *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "domain", NULL }; char *domain; if (check_if_owned (self)) return NULL; if (self->group == NULL) { PyErr_SetString (PyExc_RuntimeError, "The corresponding GOptionGroup was already freed, " "probably through the release of GOptionContext"); return NULL; } if (!PyArg_ParseTupleAndKeywords (args, kwargs, "z:GOptionGroup.set_translate_domain", kwlist, &domain)) return NULL; g_option_group_set_translation_domain (self->group, domain); Py_RETURN_NONE; } static PyObject * pyg_option_group_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE (self) == Py_TYPE (other) && Py_TYPE (self) == &PyGOptionGroup_Type) { return pyg_ptr_richcompare (((PyGOptionGroup *)self)->group, ((PyGOptionGroup *)other)->group, op); } else { Py_RETURN_NOTIMPLEMENTED; } } static PyMethodDef pyg_option_group_methods[] = { { "add_entries", (PyCFunction)pyg_option_group_add_entries, METH_VARARGS | METH_KEYWORDS }, { "set_translation_domain", (PyCFunction)pyg_option_group_set_translation_domain, METH_VARARGS | METH_KEYWORDS }, { NULL, NULL, 0 }, }; /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_option_group_register_types (PyObject *d) { PyGOptionGroup_Type.tp_dealloc = (destructor)pyg_option_group_dealloc; PyGOptionGroup_Type.tp_richcompare = pyg_option_group_richcompare; PyGOptionGroup_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; PyGOptionGroup_Type.tp_methods = pyg_option_group_methods; PyGOptionGroup_Type.tp_init = (initproc)pyg_option_group_init; PyGOptionGroup_Type.tp_alloc = PyType_GenericAlloc; PyGOptionGroup_Type.tp_new = PyType_GenericNew; if (PyType_Ready (&PyGOptionGroup_Type)) return -1; PyDict_SetItemString (d, "OptionGroup", (PyObject *)&PyGOptionGroup_Type); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygoptiongroup.h0000664000000000000000000000260115074673150016222 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pyglib - Python bindings for GLib toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYG_OPTIONGROUP_H__ #define __PYG_OPTIONGROUP_H__ #include #include extern PyTypeObject PyGOptionGroup_Type; typedef struct { PyObject_HEAD GOptionGroup *group; gboolean other_owner, is_in_context; PyObject *callback; GSList *strings; /* all strings added with the entries, are freed on GOptionGroup.destroy() */ } PyGOptionGroup; PyObject *pyg_option_group_new (GOptionGroup *group); int pygi_option_group_register_types (PyObject *d); #endif /* __PYG_OPTIONGROUP_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygpointer.c0000664000000000000000000001363115074673150015315 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * * pygpointer.c: wrapper for GPointer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include #include "pygi-type.h" #include "pygi-util.h" #include "pygpointer.h" GQuark pygpointer_class_key; PYGI_DEFINE_TYPE ("gobject.GPointer", PyGPointer_Type, PyGPointer); static void pyg_pointer_dealloc (PyGPointer *self) { Py_TYPE (self)->tp_free ((PyObject *)self); } static PyObject * pyg_pointer_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE (self) == Py_TYPE (other)) return pyg_ptr_richcompare (pyg_pointer_get_ptr (self), pyg_pointer_get_ptr (other), op); else { Py_RETURN_NOTIMPLEMENTED; } } static Py_hash_t pyg_pointer_hash (PyGPointer *self) { return (Py_hash_t)(gintptr)(pyg_pointer_get_ptr (self)); } static PyObject * pyg_pointer_repr (PyGPointer *self) { gchar buf[128]; g_snprintf (buf, sizeof (buf), "<%s at 0x%" G_GUINTPTR_FORMAT ">", g_type_name (self->gtype), (guintptr)pyg_pointer_get_ptr (self)); return PyUnicode_FromString (buf); } static int pyg_pointer_init (PyGPointer *self, PyObject *args, PyObject *kwargs) { gchar buf[512]; if (!PyArg_ParseTuple (args, ":GPointer.__init__")) return -1; pyg_pointer_set_ptr (self, NULL); self->gtype = 0; g_snprintf (buf, sizeof (buf), "%s can not be constructed", Py_TYPE (self)->tp_name); PyErr_SetString (PyExc_NotImplementedError, buf); return -1; } static void pyg_pointer_free (PyObject *op) { PyObject_Free (op); } /** * pyg_register_pointer: * @dict: the module dictionary to store the wrapper class. * @class_name: the Python name for the wrapper class. * @pointer_type: the GType of the pointer type being wrapped. * @type: the wrapper class. * * Registers a wrapper for a pointer type. The wrapper class will be * a subclass of gobject.GPointer, and a reference to the wrapper * class will be stored in the provided module dictionary. */ void pyg_register_pointer (PyObject *dict, const gchar *class_name, GType pointer_type, PyTypeObject *type) { PyObject *o; g_return_if_fail (dict != NULL); g_return_if_fail (class_name != NULL); g_return_if_fail (pointer_type != 0); if (!type->tp_dealloc) type->tp_dealloc = (destructor)pyg_pointer_dealloc; Py_SET_TYPE (type, &PyType_Type); g_assert (Py_TYPE (&PyGPointer_Type) != NULL); type->tp_base = &PyGPointer_Type; if (PyType_Ready (type) < 0) { g_warning ("could not get type `%s' ready", type->tp_name); return; } PyDict_SetItemString (type->tp_dict, "__gtype__", o = pyg_type_wrapper_new (pointer_type)); Py_DECREF (o); g_type_set_qdata (pointer_type, pygpointer_class_key, type); PyDict_SetItemString (dict, (char *)class_name, (PyObject *)type); } /** * pyg_pointer_new: * @pointer_type: the GType of the pointer value. * @pointer: the pointer value. * * Creates a wrapper for a pointer value. Since G_TYPE_POINTER types * don't register any information about how to copy/free them, there * is no guarantee that the pointer will remain valid, and there is * nothing registered to release the pointer when the pointer goes out * of scope. This is why we don't recommend people use these types. * * Returns: the boxed wrapper. */ PyObject * pyg_pointer_new (GType pointer_type, gpointer pointer) { PyGILState_STATE state; PyGPointer *self; PyTypeObject *tp; g_return_val_if_fail (pointer_type != 0, NULL); state = PyGILState_Ensure (); if (!pointer) { Py_INCREF (Py_None); PyGILState_Release (state); return Py_None; } tp = g_type_get_qdata (pointer_type, pygpointer_class_key); if (!tp) tp = (PyTypeObject *)pygi_type_import_by_g_type (pointer_type); if (!tp) tp = (PyTypeObject *)&PyGPointer_Type; /* fallback */ self = PyObject_New (PyGPointer, tp); PyGILState_Release (state); if (self == NULL) return NULL; pyg_pointer_set_ptr (self, pointer); self->gtype = pointer_type; return (PyObject *)self; } /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_pointer_register_types (PyObject *d) { PyObject *pygtype; pygpointer_class_key = g_quark_from_static_string ("PyGPointer::class"); PyGPointer_Type.tp_dealloc = (destructor)pyg_pointer_dealloc; PyGPointer_Type.tp_richcompare = pyg_pointer_richcompare; PyGPointer_Type.tp_repr = (reprfunc)pyg_pointer_repr; PyGPointer_Type.tp_hash = (hashfunc)pyg_pointer_hash; PyGPointer_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; PyGPointer_Type.tp_init = (initproc)pyg_pointer_init; PyGPointer_Type.tp_free = (freefunc)pyg_pointer_free; PyGPointer_Type.tp_alloc = PyType_GenericAlloc; PyGPointer_Type.tp_new = PyType_GenericNew; if (PyType_Ready (&PyGPointer_Type)) return -1; pygtype = pyg_type_wrapper_new (G_TYPE_POINTER); PyDict_SetItemString (PyGPointer_Type.tp_dict, "__gtype__", pygtype); Py_DECREF (pygtype); PyDict_SetItemString (d, "GPointer", (PyObject *)&PyGPointer_Type); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygpointer.h0000664000000000000000000000243315074673150015320 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYGOBJECT_POINTER_H__ #define __PYGOBJECT_POINTER_H__ #include extern GQuark pygpointer_class_key; extern PyTypeObject PyGPointer_Type; void pyg_register_pointer (PyObject *dict, const gchar *class_name, GType pointer_type, PyTypeObject *type); PyObject *pyg_pointer_new (GType pointer_type, gpointer pointer); int pygi_pointer_register_types (PyObject *d); #endif /* __PYGOBJECT_POINTER_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygspawn.c0000664000000000000000000002057715074673150014774 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pyglib - Python bindings for GLib toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * * pygspawn.c: wrapper for the glib library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include "pygi-basictype.h" #include "pygi-error.h" #include "pygi-util.h" #include "pygspawn.h" struct _PyGChildSetupData { PyObject *func; PyObject *data; }; typedef struct { PyLongObject obj; /* * This exists for two reasons: * 1. We must only close once (ideally we would not have "close" in python) * 2. In PyPy we cannot use PyLong_AsLong during free */ GPid unclosed; } PyGPid; PYGI_DEFINE_TYPE ("gi._gi.Pid", PyGPid_Type, PyGPid) static PyObject * pyg_pid_close (PyObject *self, PyObject *args, PyObject *kwargs) { PyGPid *gpid = (PyGPid *)self; if (gpid->unclosed) g_spawn_close_pid (gpid->unclosed); #ifdef G_OS_WIN32 gpid->unclosed = NULL; #else gpid->unclosed = 0; #endif Py_RETURN_NONE; } static PyMethodDef pyg_pid_methods[] = { { "close", (PyCFunction)pyg_pid_close, METH_NOARGS }, { NULL, NULL, 0 }, }; static void pyg_pid_free (PyObject *self) { PyGPid *gpid = (PyGPid *)self; if (gpid->unclosed) g_spawn_close_pid (gpid->unclosed); PyLong_Type.tp_free ((void *)self); } static int pyg_pid_tp_init (PyObject *self, PyObject *args, PyObject *kwargs) { PyErr_SetString (PyExc_TypeError, "gi._gi.Pid cannot be manually instantiated"); return -1; } PyObject * pyg_pid_new (GPid pid) { PyObject *long_val; #ifdef G_OS_WIN32 long_val = PyLong_FromVoidPtr (pid); #else long_val = pygi_gint_to_py (pid); #endif return PyObject_CallMethod ((PyObject *)&PyGPid_Type, "__new__", "ON", &PyGPid_Type, long_val); } static void _pyg_spawn_async_callback (gpointer user_data) { struct _PyGChildSetupData *data; PyObject *retval; PyGILState_STATE gil; data = (struct _PyGChildSetupData *)user_data; gil = PyGILState_Ensure (); if (data->data) retval = PyObject_CallFunction (data->func, "O", data->data); else retval = PyObject_CallFunction (data->func, NULL); if (retval) Py_DECREF (retval); else PyErr_Print (); Py_DECREF (data->func); Py_XDECREF (data->data); g_slice_free (struct _PyGChildSetupData, data); PyGILState_Release (gil); } PyObject * pyglib_spawn_async (PyObject *object, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "argv", "envp", "working_directory", "flags", "child_setup", "user_data", "standard_input", "standard_output", "standard_error", NULL }; PyObject *pyargv, *pyenvp = NULL; char **argv, **envp = NULL; PyObject *func = Py_None, *user_data = NULL; char *working_directory = NULL; int flags = 0, _stdin = -1, _stdout = -1, _stderr = -1; PyObject *pystdin = NULL, *pystdout = NULL, *pystderr = NULL; gint *standard_input, *standard_output, *standard_error; struct _PyGChildSetupData *callback_data = NULL; GError *error = NULL; GPid child_pid = 0; Py_ssize_t len, i; if (!PyArg_ParseTupleAndKeywords ( args, kwargs, "O|OsiOOOOO:gi._gi.spawn_async", kwlist, &pyargv, &pyenvp, &working_directory, &flags, &func, &user_data, &pystdin, &pystdout, &pystderr)) return NULL; if (pystdin && PyObject_IsTrue (pystdin)) standard_input = &_stdin; else standard_input = NULL; if (pystdout && PyObject_IsTrue (pystdout)) standard_output = &_stdout; else standard_output = NULL; if (pystderr && PyObject_IsTrue (pystderr)) standard_error = &_stderr; else standard_error = NULL; /* parse argv */ if (!PySequence_Check (pyargv)) { PyErr_SetString (PyExc_TypeError, "gi._gi.spawn_async: " "first argument must be a sequence of strings"); return NULL; } len = PySequence_Length (pyargv); argv = g_new0 (char *, len + 1); for (i = 0; i < len; ++i) { PyObject *tmp = PySequence_ITEM (pyargv, i); if (tmp == NULL || !PyUnicode_Check (tmp)) { PyErr_SetString (PyExc_TypeError, "gi._gi.spawn_async: " "first argument must be a sequence of strings"); g_free (argv); Py_XDECREF (tmp); return NULL; } argv[i] = PyUnicode_AsUTF8 (tmp); Py_DECREF (tmp); } /* parse envp */ if (pyenvp) { if (!PySequence_Check (pyenvp)) { PyErr_SetString (PyExc_TypeError, "gi._gi.spawn_async: " "second argument must be a sequence of strings"); g_free (argv); return NULL; } len = PySequence_Length (pyenvp); envp = g_new0 (char *, len + 1); for (i = 0; i < len; ++i) { PyObject *tmp = PySequence_ITEM (pyenvp, i); if (tmp == NULL || !PyUnicode_Check (tmp)) { PyErr_SetString ( PyExc_TypeError, "gi._gi.spawn_async: " "second argument must be a sequence of strings"); g_free (envp); Py_XDECREF (tmp); g_free (argv); return NULL; } envp[i] = PyUnicode_AsUTF8 (tmp); Py_DECREF (tmp); } } if (!Py_IsNone (func)) { if (!PyCallable_Check (func)) { PyErr_SetString (PyExc_TypeError, "child_setup parameter must be callable or None"); g_free (argv); if (envp) g_free (envp); return NULL; } callback_data = g_slice_new (struct _PyGChildSetupData); callback_data->func = func; callback_data->data = user_data; Py_INCREF (callback_data->func); if (callback_data->data) Py_INCREF (callback_data->data); } if (!g_spawn_async_with_pipes ( working_directory, argv, envp, flags, !Py_IsNone (func) ? _pyg_spawn_async_callback : NULL, callback_data, &child_pid, standard_input, standard_output, standard_error, &error)) { g_free (argv); if (envp) g_free (envp); if (callback_data) { Py_DECREF (callback_data->func); Py_XDECREF (callback_data->data); g_slice_free (struct _PyGChildSetupData, callback_data); } pygi_error_check (&error); return NULL; } g_free (argv); if (envp) g_free (envp); if (standard_input) pystdin = pygi_gint_to_py (*standard_input); else { pystdin = Py_NewRef (Py_None); } if (standard_output) pystdout = pygi_gint_to_py (*standard_output); else { pystdout = Py_NewRef (Py_None); } if (standard_error) pystderr = pygi_gint_to_py (*standard_error); else { pystderr = Py_NewRef (Py_None); } return Py_BuildValue ("NNNN", pyg_pid_new (child_pid), pystdin, pystdout, pystderr); } /** * Returns 0 on success, or -1 and sets an exception. */ int pygi_spawn_register_types (PyObject *d) { PyGPid_Type.tp_base = &PyLong_Type; PyGPid_Type.tp_flags = Py_TPFLAGS_DEFAULT; PyGPid_Type.tp_methods = pyg_pid_methods; PyGPid_Type.tp_init = pyg_pid_tp_init; PyGPid_Type.tp_free = (freefunc)pyg_pid_free; PyGPid_Type.tp_new = PyLong_Type.tp_new; PyGPid_Type.tp_alloc = PyType_GenericAlloc; if (PyType_Ready (&PyGPid_Type)) return -1; PyDict_SetItemString (d, "Pid", (PyObject *)&PyGPid_Type); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygspawn.h0000664000000000000000000000212715074673150014770 0ustar00rootroot/* -*- Mode: C; c-basic-offset: 4 -*- * pyglib - Python bindings for GLib toolkit. * Copyright (C) 1998-2003 James Henstridge * 2004-2008 Johan Dahlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #ifndef __PYG_PID_H__ #define __PYG_PID_H__ PyObject *pyg_pid_new (GPid pid); int pygi_spawn_register_types (PyObject *d); PyObject *pyglib_spawn_async (PyObject *self, PyObject *args, PyObject *kwargs); #endif /* __PYG_PID_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/pygtkcompat.py0000664000000000000000000000036015074673150015660 0ustar00rootrootimport warnings from gi import PyGIDeprecationWarning warnings.warn( 'gi.pygtkcompat is being deprecated in favor of using "pygtkcompat" directly.', PyGIDeprecationWarning, ) from pygtkcompat import enable __all__ = ["enable"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/repository/__init__.py0000664000000000000000000000162415074673150017300 0ustar00rootroot# Copyright (C) 2009 Johan Dahlin # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import sys from ..importer import DynamicImporter sys.meta_path.append(DynamicImporter("gi.repository")) del DynamicImporter del sys ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/repository/meson.build0000664000000000000000000000016515074673150017330 0ustar00rootrootpython_sources = ['__init__.py'] python.install_sources(python_sources, subdir : join_paths('gi', 'repository') ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/gi/types.py0000664000000000000000000003215615074673150014472 0ustar00rootroot# Copyright (C) 2005-2009 Johan Dahlin # # types.py: base types for introspected items. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import re from ._constants import TYPE_INVALID from .docstring import generate_doc_string from ._gi import ( InterfaceInfo, ObjectInfo, StructInfo, VFuncInfo, register_interface_info, hook_up_vfunc_implementation, GInterface, ) from . import _gi StructInfo, GInterface from . import _propertyhelper as propertyhelper from . import _signalhelper as signalhelper def snake_case(name): s1 = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", name) return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1).lower() class MetaClassHelper: def _setup_methods(cls): for method_info in cls.__info__.get_methods(): name = method_info.__name__ if method_info.is_constructor(): method_info = classmethod(method_info) elif not method_info.is_method(): method_info = staticmethod(method_info) setattr(cls, name, method_info) def _setup_class_methods(cls): info = cls.__info__ class_struct = info.get_class_struct() if class_struct is None: return for method_info in class_struct.get_methods(): name = method_info.__name__ # Don't mask regular methods or base class methods with TypeClass methods. if not hasattr(cls, name): setattr(cls, name, classmethod(method_info)) def _setup_fields(cls): for field_info in cls.__info__.get_fields(): name = field_info.get_name().replace("-", "_") setattr(cls, name, property(field_info.get_value, field_info.set_value)) def _setup_constants(cls): for constant_info in cls.__info__.get_constants(): name = constant_info.get_name() value = constant_info.get_value() setattr(cls, name, value) def _setup_vfuncs(cls): for vfunc_name, py_vfunc in cls.__dict__.items(): if not vfunc_name.startswith("do_") or not callable(py_vfunc): continue skip_ambiguity_check = False # If a method name starts with "do_" assume it is a vfunc, and search # in the base classes for a method with the same name to override. # Recursion is necessary as overriden methods in most immediate parent # classes may shadow vfuncs from classes higher in the hierarchy. vfunc_info = None for base in cls.__mro__: method = getattr(base, vfunc_name, None) method = getattr(method, "__func__", method) if method is not None and isinstance(method, VFuncInfo): vfunc_info = method break if not hasattr(base, "__info__") or not hasattr( base.__info__, "get_vfuncs" ): continue base_name = snake_case(base.__info__.get_type_name()) for v in base.__info__.get_vfuncs(): if vfunc_name == f"do_{base_name}_{v.get_name()}": vfunc_info = v skip_ambiguity_check = True break if vfunc_info: break # If we did not find a matching method name in the bases, we might # be overriding an interface virtual method. Since interfaces do not # provide implementations, there will be no method attribute installed # on the object. Instead we have to search through # InterfaceInfo.get_vfuncs(). Note that the infos returned by # get_vfuncs() use the C vfunc name (ie. there is no "do_" prefix). if vfunc_info is None: vfunc_info = find_vfunc_info_in_interface( cls.__bases__, vfunc_name[len("do_") :] ) if vfunc_info is not None: # Check to see if there are vfuncs with the same name in the bases. # We have no way of specifying which one we are supposed to override. if not skip_ambiguity_check: ambiguous_base = find_vfunc_conflict_in_bases( vfunc_info, cls.__bases__ ) if ambiguous_base is not None: base_info = vfunc_info.get_container() raise TypeError( f"Method {vfunc_name}() on class {cls.__info__.get_namespace()}.{cls.__info__.get_name()} is ambiguous " f"with methods in base classes {base_info.get_namespace()}.{base_info.get_name()} and {ambiguous_base.__info__.get_namespace()}.{ambiguous_base.__info__.get_name()}" ) hook_up_vfunc_implementation(vfunc_info, cls.__gtype__, py_vfunc) def _setup_native_vfuncs(cls): # Only InterfaceInfo and ObjectInfo have the get_vfuncs() method. # We skip InterfaceInfo because interfaces have no implementations for vfuncs. # Also check if __info__ in __dict__, not hasattr('__info__', ...) # because we do not want to accidentally retrieve __info__ from a base class. class_info = cls.__dict__.get("__info__") if class_info is None or not isinstance(class_info, ObjectInfo): return # Special case skipping of vfuncs for GObject.Object because they will break # the static bindings which will try to use them. if cls.__module__ == "gi.repository.GObject" and cls.__name__ == "Object": return for vfunc_info in class_info.get_vfuncs(): name = f"do_{vfunc_info.__name__}" setattr(cls, name, vfunc_info) def find_vfunc_info_in_interface(bases, vfunc_name): for base in bases: # All wrapped interfaces inherit from GInterface. # This can be seen in IntrospectionModule.__getattr__() in module.py. # We do not need to search regular classes here, only wrapped interfaces. # We also skip GInterface, because it is not wrapped and has no __info__ attr. # Skip bases without __info__ (static _gi.GObject) if ( base is GInterface or not issubclass(base, GInterface) or not hasattr(base, "__info__") ): continue # Only look at this classes vfuncs if it is an interface. if isinstance(base.__info__, InterfaceInfo): for vfunc in base.__info__.get_vfuncs(): if vfunc.get_name() == vfunc_name: return vfunc # Recurse into the parent classes vfunc = find_vfunc_info_in_interface(base.__bases__, vfunc_name) if vfunc is not None: return vfunc return None def find_vfunc_conflict_in_bases(vfunc, bases): for klass in bases: if not hasattr(klass, "__info__") or not hasattr(klass.__info__, "get_vfuncs"): continue vfuncs = klass.__info__.get_vfuncs() vfunc_name = vfunc.get_name() for v in vfuncs: if v.get_name() == vfunc_name and v != vfunc: return klass aklass = find_vfunc_conflict_in_bases(vfunc, klass.__bases__) if aklass is not None: return aklass return None class _GObjectMetaBase(type): """Metaclass for automatically registering GObject classes.""" def __init__(cls, name, bases, dict_): type.__init__(cls, name, bases, dict_) propertyhelper.install_properties(cls) signalhelper.install_signals(cls) cls._type_register(cls.__dict__) def _type_register(cls, namespace): # don't register the class if already registered if "__gtype__" in namespace: return # Do not register a new GType for the overrides, as this would sort of # defeat the purpose of overrides... if cls.__module__.startswith("gi.overrides."): return _gi.type_register(cls, namespace.get("__gtype_name__")) _gi._install_metaclass(_GObjectMetaBase) class GObjectMeta(_GObjectMetaBase, MetaClassHelper): """Meta class used for GI GObject based types.""" def __init__(cls, name, bases, dict_): super().__init__(name, bases, dict_) is_gi_defined = False if cls.__module__ == "gi.repository." + cls.__info__.get_namespace(): is_gi_defined = True is_python_defined = False if not is_gi_defined and cls.__module__ != GObjectMeta.__module__: is_python_defined = True if is_python_defined: cls._setup_vfuncs() elif is_gi_defined: if isinstance(cls.__info__, ObjectInfo): cls._setup_class_methods() cls._setup_methods() cls._setup_constants() cls._setup_native_vfuncs() if isinstance(cls.__info__, ObjectInfo): cls._setup_fields() elif isinstance(cls.__info__, InterfaceInfo): register_interface_info(cls.__info__.get_g_type()) def mro(cls): return mro(cls) @property def __doc__(cls): """Meta class property which shows up on any class using this meta-class.""" if cls == GObjectMeta: return "" doc = cls.__dict__.get("__doc__", None) if doc is not None: return doc # For repository classes, dynamically generate a doc string if it wasn't overridden. if cls.__module__.startswith(("gi.repository.", "gi.overrides")): return generate_doc_string(cls.__info__) return None def mro(C): """Compute the class precedence list (mro) according to C3, with GObject interface considerations. We override Python's MRO calculation to account for the fact that GObject classes are not affected by the diamond problem: http://en.wikipedia.org/wiki/Diamond_problem Based on http://www.python.org/download/releases/2.3/mro/ """ # TODO: If this turns out being too slow, consider using generators bases = [] bases_of_subclasses = [[C]] if C.__bases__: for base in C.__bases__: # Python causes MRO's to be calculated starting with the lowest # base class and working towards the descendant, storing the result # in __mro__ at each point. Therefore at this point we know that # we already have our base class MRO's available to us, there is # no need for us to (re)calculate them. bases_of_subclasses += [list(base.__mro__)] bases_of_subclasses += [list(C.__bases__)] while bases_of_subclasses: for subclass_bases in bases_of_subclasses: candidate = subclass_bases[0] not_head = [s for s in bases_of_subclasses if candidate in s[1:]] if not_head and GInterface not in candidate.__bases__: candidate = None # conflict, reject candidate else: break if candidate is None: raise TypeError("Cannot create a consistent method resolution order (MRO)") bases.append(candidate) for subclass_bases in bases_of_subclasses[:]: # remove candidate if subclass_bases and subclass_bases[0] == candidate: del subclass_bases[0] if not subclass_bases: bases_of_subclasses.remove(subclass_bases) return bases def nothing(*args, **kwargs): pass class StructMeta(type, MetaClassHelper): """Meta class used for GI Struct based types.""" def __init__(cls, name, bases, dict_): super().__init__(name, bases, dict_) # Avoid touching anything else than the base class. g_type = cls.__info__.get_g_type() if g_type != TYPE_INVALID and g_type.pytype is not None: return cls._setup_fields() cls._setup_methods() for method_info in cls.__info__.get_methods(): if ( method_info.is_constructor() and method_info.__name__ == "new" and (not method_info.get_arguments() or cls.__info__.get_size() == 0) ): cls.__new__ = staticmethod(method_info) # Boxed will raise an exception # if arguments are given to __init__ cls.__init__ = nothing break @property def __doc__(cls): if cls == StructMeta: return "" return generate_doc_string(cls.__info__) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/meson.build0000664000000000000000000001615615074673150014521 0ustar00rootrootproject( 'pygobject', 'c', version : '3.54.5', meson_version : '>= 0.64.0', default_options : ['warning_level=1', 'buildtype=debugoptimized'] ) pygobject_version = meson.project_version() version_arr = pygobject_version.split('.') pygobject_version_major = version_arr[0].to_int() pygobject_version_minor = version_arr[1].to_int() pygobject_version_micro = version_arr[2].to_int() platform_version = '@0@.0'.format(pygobject_version_major) pymod = import('python') python = pymod.find_installation(get_option('python'), pure: false) if python.language_version().version_compare('< 3.9') error('Requires Python >= 3.9') endif python_dep = python.dependency() glib_version_req = '>= 2.80.0' gi_version_req = '>= 1.64.0' pycairo_version_req = '>= 1.16.0' libffi_version_req = '>= 3.0' gi_dep = dependency('girepository-2.0', version : glib_version_req, fallback: ['glib', 'libgirepository_dep']) glib_dep = dependency('glib-2.0', version : glib_version_req, fallback: ['glib', 'libglib_dep'], default_options: ['-Dintrospection=enabled']) gobject_dep = dependency('gobject-2.0', version : glib_version_req, fallback: ['glib', 'libgobject_dep']) gio_dep = dependency('gio-2.0', version : glib_version_req, fallback: ['glib', 'libgio_dep']) ffi_dep = dependency('libffi', version : libffi_version_req, fallback : ['libffi', 'ffi_dep']) with_pycairo = get_option('pycairo') cc = meson.get_compiler('c') pythoncapi_compat = subproject('pythoncapi-compat') pythoncapi_compat_dep = declare_dependency( include_directories: pythoncapi_compat.get_variable('incdir') ) meson.add_dist_script( python, join_paths(meson.current_source_dir(), 'subprojects', 'packagefiles', 'pythoncapi-compat-dist.py')) if not with_pycairo.disabled() cairo_dep = dependency('cairo', required: with_pycairo.enabled() and cc.get_id() != 'msvc') cairo_gobject_dep = dependency('cairo-gobject', required: with_pycairo.enabled() and cc.get_id() != 'msvc') if cc.get_id() == 'msvc' and (not cairo_gobject_dep.found() or not cairo_dep.found()) if cc.has_header('cairo.h') and cc.has_header ('cairo-gobject.h') cairo_dep = cc.find_library ('cairo', required: with_pycairo) cairo_gobject_dep = cc.find_library ('cairo-gobject', required: with_pycairo) endif endif # Find pycairo with target Python (TODO: extract version as well, see setup.py) r = run_command( python, '-c', ''' import pathlib, sys from importlib.util import find_spec spec = find_spec("cairo") if spec is None: sys.stderr.write("cairo module spec not found") sys.exit(1) src_path = pathlib.Path(r"@0@") inc_path = pathlib.Path(spec.origin).parent / "include" try: sys.stdout.write(str(inc_path.relative_to(src_path))) except ValueError: sys.stdout.write(str(inc_path)) '''.format(meson.current_source_dir()), check: false, ) if r.returncode() == 0 message('Found pycairo with target Python: ' + r.stdout()) pycairo_inc_dir = include_directories(r.stdout()) pycairo_dep = declare_dependency( include_directories: pycairo_inc_dir, ) else message('pycairo not found via target Python, falling back to pkg-config (@0@)'.format(r.stderr())) # Find pycairo with pkg-config pycairo_dep = dependency( 'py3cairo', version: pycairo_version_req, fallback: ['pycairo', 'pycairo_dep'], default_options: ['python=' + get_option('python')], required: with_pycairo, ) endif else cairo_dep = dependency('', required: false) pycairo_dep = dependency('', required: false) endif main_c_args = [] if cc.get_id() == 'msvc' main_c_args += [ '-FImsvc_recommended_pragmas.h' ] else main_c_args += [ '-Wall', '-Warray-bounds', '-Wcast-align', '-Wduplicated-branches', '-Wextra', '-Wformat=2', '-Wformat-nonliteral', '-Wformat-security', '-Wimplicit-function-declaration', '-Winit-self', '-Wjump-misses-init', '-Wlogical-op', '-Wmissing-declarations', '-Wmissing-format-attribute', '-Wmissing-include-dirs', '-Wmissing-noreturn', '-Wmissing-prototypes', '-Wnull-dereference', '-Wold-style-definition', '-Wpacked', '-Wpointer-arith', '-Wrestrict', '-Wreturn-type', '-Wshadow', '-Wsign-compare', '-Wstrict-aliasing', '-Wstrict-prototypes', '-Wswitch-default', '-Wundef', '-Wunused-but-set-variable', '-Wwrite-strings', ] main_c_args += [ '-Wno-incompatible-pointer-types-discards-qualifiers', '-Wno-missing-field-initializers', '-Wno-unused-parameter', '-Wno-discarded-qualifiers', '-Wno-sign-conversion', '-Wno-cast-function-type', '-Wno-int-conversion', ] main_c_args += [ '-fno-strict-aliasing', '-fvisibility=hidden', ] main_c_args = cc.get_supported_arguments(main_c_args) endif pyext_c_args = ['-DPY_SSIZE_T_CLEAN'] cdata = configuration_data() cdata.set('PYGOBJECT_MAJOR_VERSION', pygobject_version_major) cdata.set('PYGOBJECT_MINOR_VERSION', pygobject_version_minor) cdata.set('PYGOBJECT_MICRO_VERSION', pygobject_version_micro) if gio_dep.version().version_compare('< 2.67.4') cdata.set('g_memdup2(ptr,sz)', '(G_LIKELY(((guint64)(sz)) < G_MAXUINT)) ? g_memdup(ptr,sz) : (g_abort(),NULL)') endif configure_file(output : 'config.h', configuration : cdata) pkgconf = configuration_data() pkgconf.set('prefix', join_paths(get_option('prefix'))) pkgconf.set('exec_prefix', '${prefix}') pkgconf.set('includedir', join_paths('${prefix}', get_option('includedir'))) pkgconf.set('datarootdir', join_paths('${prefix}', get_option('datadir'))) pkgconf.set('datadir', '${datarootdir}') pkgconf.set('VERSION', pygobject_version) for_wheel = get_option('wheel') if not for_wheel pkg_install_dir = '@0@/pkgconfig'.format(get_option('libdir')) configure_file(input : 'pygobject-@0@.pc.in'.format(platform_version), output : 'pygobject-@0@.pc'.format(platform_version), configuration : pkgconf, install_dir : pkg_install_dir) if pygobject_version_minor.is_odd() py_version = '@0@.dev0'.format(pygobject_version) else py_version = pygobject_version endif pkginfo_conf = configuration_data() pkginfo_conf.set('VERSION', py_version) configure_file(input : 'METADATA.in', output : 'METADATA', configuration : pkginfo_conf, install_dir : python.get_install_dir(pure : false) / 'PyGObject-@0@.dist-info'.format(py_version)) endif pygobject_dep = declare_dependency( include_directories: include_directories('gi'), dependencies: [gobject_dep, ffi_dep], version: meson.project_version(), ) subdir('gi') subdir('pygtkcompat') with_tests = get_option('tests') if with_tests gi_tests = subproject('gobject-introspection-tests', default_options : ['cairo=' + cairo_dep.found().to_string()]) # We cannot depend on gobject-introspection-1.0 fallback if we also need GLib to build. # All we need is the g-ir-scanner and friends if glib_dep.type_name() != 'internal' dependency('gobject-introspection-1.0', version : gi_version_req, fallback: ['gobject-introspection', 'girepo_dep']) endif subdir('tests') endif devenv = environment() devenv.prepend('PYTHONPATH', [ meson.current_source_dir(), meson.current_build_dir(), ]) meson.add_devenv(devenv) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/meson_options.txt0000664000000000000000000000050615074673150016004 0ustar00rootrootoption('python', type : 'string', value : 'python3') option('pycairo', type : 'feature', value : 'auto', description : 'build with pycairo integration') option('tests', type : 'boolean', value : true, description : 'build unit tests') option('wheel', type : 'boolean', value : false, description : 'build for a Python wheel') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/pygobject-3.0.pc.in0000664000000000000000000000130115074673150015556 0ustar00rootrootprefix=@prefix@ exec_prefix=@exec_prefix@ includedir=@includedir@ datarootdir=@datarootdir@ datadir=@datadir@ # you can use the --variable=pygobjectincludedir argument to # pkg-config to get this value. You might want to use this to # install additional headers. pygobjectincludedir=${includedir}/pygobject-3.0 Name: PyGObject Description: Python bindings for GObject Requires: gobject-2.0 Requires.private: libffi Version: @VERSION@ Cflags: -I${pygobjectincludedir} # overridesdir has now moved to the gi module # third parties can access it in a python script: # # import gi # installdir = gi._overridesdir # # the version of python you run the script from # will determine the actual overrides path ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/pygobject.doap0000664000000000000000000000504415074673150015204 0ustar00rootroot PyGObject Python bindings for GObject Introspection GObject is a object system used by GTK, GStreamer and other libraries. PyGObject provides a convenient wrapper for use in Python programs when accessing GObject libraries. Like the GObject library itself PyGObject is licensed under the GNU LGPL, so is suitable for use in both free software and proprietary applications. It is already in use in many applications ranging from small single purpose scripts up to large full featured applications. PyGObject now dynamically accesses any GObject libraries that uses GObject Introspection. It replaces the need for separate modules such as PyGTK, GIO and python-gnome to build a full GNOME 3.0 application. Once new functionality is added to gobject library it is instantly available as a Python API without the need for intermediate Python glue. C Python Ignacio Casal Quinteiro icq Christoph Reiter creiter Arjan Molenaar amolenaar Dan Yeaw danyeaw ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/pygtkcompat/__init__.py0000664000000000000000000000006715074673150017024 0ustar00rootrootfrom .pygtkcompat import enable __all__ = ["enable"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/pygtkcompat/meson.build0000664000000000000000000000017315074673150017053 0ustar00rootrootpython_sources = [ '__init__.py', 'pygtkcompat.py'] python.install_sources(python_sources, subdir : 'pygtkcompat' ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/pygtkcompat/pygtkcompat.py0000664000000000000000000000202315074673150017621 0ustar00rootroot# Copyright (C) 2011-2012 Johan Dahlin # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA """PyGTK compatibility layer. DEPRECATED. DO NOT USE. """ def enable(): 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" ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/pyproject.toml0000664000000000000000000000567315074673150015275 0ustar00rootroot[project] name = "PyGObject" description = "Python bindings for GObject Introspection" readme = 'README.rst' license = { file = 'COPYING' } authors = [ { name="James Henstridge", email="james@daa.com.au" } ] maintainers = [ { name="Christoph Reiter", email="creiter@src.gnome.org" }, { name="Arjan Molenaar", email="amolenaar@gnome.org" }, { name="Dan Yeaw", email="danyeaw@gnome.org" }, { name="Ignacio Casal Quinteiro", email="icq@gnome.org" }, ] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Programming Language :: C", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules", ] requires-python = ">=3.9" dependencies = [ "pycairo>=1.16" ] dynamic = ["version"] [project.urls] Homepage = "https://pygobject.gnome.org" Repository = "https://gitlab.gnome.org/GNOME/pygobject.git" Changelog = "https://gitlab.gnome.org/GNOME/pygobject/-/blob/main/NEWS" [tool.pdm.dev-dependencies] lint = [ "pre-commit", ] build = [ # Setuptools 74 removed msvccompiler, required by g-ir-scanner (<1.82.0) # See https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/515 "setuptools<74", "meson-python", "ninja", "pycairo", ] test = [ "pytest", "pytest-cov", ] docs = [ "sphinx", "pydata-sphinx-theme", "sphinx-copybutton>=0.5.2", ] [tool.pdm.options] install = [ "--no-isolation", "--config-setting=setup-args=-Dtests=true", "--config-setting=setup-args=-Dbuildtype=debug", "--config-setting=editable-verbose=true", ] build = [ "--no-wheel", "--config-setting=setup-args=-Dtests=true", ] [tool.meson-python.args] setup = ["-Dtests=false", "-Dwheel=true", "--wrap-mode=nofallback"] dist = ["--include-subprojects"] [tool.pytest.ini_options] testpaths = [ "tests", ] python_files = "test_*.py" addopts = [ "--import-mode=importlib", ] [tool.ruff] extend-include = ["docs/**/*.rst"] extend-exclude = ["subprojects", "COPYING"] [tool.ruff.lint] extend-select = [ "UP", # pyupgrade "E", # pycodestyle error "W", # pycodestyle warning "D", # pydocstyle "R", # refactor "C4", # flake8-comprehensions "ASYNC", # flake8-async "EXE", # flake8-executable "T20", # flake8-print "SIM", # flake8-simplify "RUF", # extra ruff rules "PERF", # perflint ] ignore = [ "D1", "D211", "D203", "D213", "D4", "D205", "E402", "E501", "E731", "E722", "RUF012", ] [tool.ruff.lint.per-file-ignores] "docs/tutorials/**/*py" = ["T20", "SIM905"] "fixup-lcov-paths.py" = ["T20"] [tool.ruff.format] docstring-code-format = true [build-system] build-backend = "mesonpy" requires = ["meson-python>=0.12.1", "pycairo>=1.16"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/subprojects/glib.wrap0000664000000000000000000000021115074673150016513 0ustar00rootroot[wrap-git] directory=glib url=https://gitlab.gnome.org/GNOME/glib.git push-url=git@gitlab.gnome.org:GNOME/glib.git revision=main depth=1 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/.clang-format0000664000000000000000000000055115056773103024737 0ustar00rootroot# SPDX-License-Identifier: MIT # SPDX-FileCopyrightText: 2024 Philip Chimento BasedOnStyle: GNU BinPackParameters: false BreakBeforeBinaryOperators: None ContinuationIndentWidth: 2 SpaceAfterCStyleCast: true # clang-format makes weird choices re. enforcing line limits. # Currently, humans can still do this better. ColumnLimit: 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/.editorconfig0000664000000000000000000000041115056773103025034 0ustar00rootroot# SPDX-License-Identifier: MIT # SPDX-FileCopyrightText: 2024 Philip Chimento root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true [*.{c,h}] indent_size = 2 indent_style = space ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/.gitlab-ci.yml0000664000000000000000000000143615056773103025023 0ustar00rootroot# SPDX-License-Identifier: MIT # SPDX-FileCopyrightText: 2024 Philip Chimento include: - project: Infrastructure/freedesktop-ci-templates file: templates/alpine.yml ref: 6a40df92957c8ce9ee741aaccc5daaaf70545b1e stages: - image-build - check variables: FDO_UPSTREAM_REPO: GNOME/gobject-introspection-tests .gitests.alpine: variables: FDO_DISTRIBUTION_TAG: '2024-09-11.0' build-alpine-image: extends: - .fdo.container-build@alpine - .gitests.alpine stage: image-build variables: FDO_DISTRIBUTION_PACKAGES: reuse license-check: extends: - .fdo.distribution-image@alpine - .gitests.alpine stage: check dependencies: [] # don't check artifacts from container build script: - reuse --version - reuse lint ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/.reuse/dep50000664000000000000000000000022315056773103024341 0ustar00rootrootFormat: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Files: docs/* README.md Copyright: No rights reserved License: CC0-1.0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/LICENSES/CC0-1.0.txt0000664000000000000000000001561015056773103025175 0ustar00rootrootCreative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/LICENSES/GPL-2.0-or-later.txt0000664000000000000000000004167115056773103027004 0ustar00rootrootGNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/LICENSES/LGPL-2.0-or-later.txt0000664000000000000000000006045515056773103027121 0ustar00rootrootGNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. one line to give the library's name and an idea of what it does. Copyright (C) year name of author This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. signature of Ty Coon, 1 April 1990 Ty Coon, President of Vice That's all there is to it! ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/LICENSES/LGPL-2.1-or-later.txt0000664000000000000000000006262115056773103027117 0ustar00rootrootGNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. one line to give the library's name and an idea of what it does. Copyright (C) year name of author This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. signature of Ty Coon, 1 April 1990 Ty Coon, President of Vice That's all there is to it! ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/LICENSES/MIT.txt0000664000000000000000000000206615056773103024766 0ustar00rootrootMIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/README.md0000664000000000000000000000600715056773103023645 0ustar00rootroot# GObject Introspection Tests This is a git submodule containing C source files. These files are compiled into shared libraries intended for testing language bindings for the GNOME platform. They are also used to test the `g-ir-scanner` tool from [gobject-introspection]. [gobject-introspection]: https://gitlab.gnome.org/GNOME/gobject-introspection ## Available modules **Regress** test suite — a library designed as a general regression test suite, accumulated over the lifetime of gobject-introspection. Consists of `regress.c`, `annotation.c`, `drawable.c`, `foo.c`, and their associated header files. **GIMarshallingTests** suite — a library designed to exercise how every kind of C value used in GNOME platform APIs is converted to and from native values from the language binding. **Utility** test suite — a library for testing external type references. **WarnLib** test suite — a library with a number of conditions that `g-ir-scanner` will warn about, used to test how language bindings deal with typelibs that contain non-ideal C code. ## How to Use in a Dynamic Language Binding Include this repository as a git submodule in your sources. ```sh git submodule add https://gitlab.gnome.org/GNOME/gobject-introspection-tests.git ``` If you use the Meson build system, you can also add it as a Meson subproject, and simply write: ```meson gi_tests = subproject('gobject-introspection-tests') ``` The subproject exports variables `gimarshallingtests_typelib`, `regress_typelib`, `utility_typelib`, and `warnlib_typelib` which you can access with `gi_tests.get_variable('regress_typelib')` etc. You will have to decide which modules you want to use. Most language bindings will want to use at least Regress and GIMarshallingTests. Now you can write tests that load the module, call each of its functions with the expected input, and check for the expected output. You will need to add the build folder to the environment variables `LD_LIBRARY_PATH` and `GI_TYPELIB_PATH`, something like this: ```meson tests_environment = environment() gi_tests_builddir = meson.project_build_root() / 'subprojects' / 'gobject-introspection-tests' tests_environment.prepend('LD_LIBRARY_PATH', gi_tests_builddir) tests_environment.prepend('GI_TYPELIB_PATH', gi_tests_builddir) ``` and then pass `env: tests_environment` in your call to `test()`. If your language binding supports installed tests, you will have to install the built modules manually, to a private location where your installed tests can find them. Do not install them in the default typelibs directory, where they may conflict with other language bindings' installed tests. Depending on how your build system is structured it might look something like this, using GIMarshallingTests as an example: ```meson gi_tests = subproject('gobject-introspection-tests', default_options: ['install_dir=@0@'.format(installed_tests_dir)]) ``` For build systems other than Meson, simply ignore the `meson.build` file and add code to your build system to build the modules as if it was a regular subdirectory. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/annotation.c0000664000000000000000000005614315056773103024712 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2008-2009 Dan Winship SPDX-FileCopyrightText: 2008-2010 Colin Walters SPDX-FileCopyrightText: 2008-2011 Johan Dahlin SPDX-FileCopyrightText: 2008 Owen Taylor SPDX-FileCopyrightText: 2008 Tristan Van Berkom SPDX-FileCopyrightText: 2009 Andreas Rottmann SPDX-FileCopyrightText: 2010 litl, LLC SPDX-FileCopyrightText: 2010 Pavel Holejsovsky SPDX-FileCopyrightText: 2010 Red Hat, Inc. SPDX-FileCopyrightText: 2011 Jasper St. Pierre SPDX-FileCopyrightText: 2015 Christoph Reiter */ #include #include "annotation.h" char backslash_parsing_tester = '\\'; G_DEFINE_TYPE (RegressAnnotationObject, regress_annotation_object, G_TYPE_OBJECT); enum { PROP_0, PROP_STRING_PROPERTY, PROP_FUNCTION_PROPERTY, PROP_TAB_PROPERTY }; enum { STRING_SIGNAL, LIST_SIGNAL, DOC_EMPTY_ARG_PARSING, ATTRIBUTE_SIGNAL, LAST_SIGNAL }; static guint regress_annotation_object_signals[LAST_SIGNAL] = { 0 }; static void regress_annotation_object_set_property (GObject *object, guint prop_id, const GValue *value G_GNUC_UNUSED, GParamSpec *pspec) { switch (prop_id) { case PROP_STRING_PROPERTY: break; case PROP_FUNCTION_PROPERTY: break; case PROP_TAB_PROPERTY: break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void regress_annotation_object_get_property (GObject *object, guint prop_id, GValue *value G_GNUC_UNUSED, GParamSpec *pspec) { switch (prop_id) { case PROP_STRING_PROPERTY: break; case PROP_FUNCTION_PROPERTY: break; case PROP_TAB_PROPERTY: break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void regress_annotation_object_finalize (GObject *gobj) { RegressAnnotationObject *self = (RegressAnnotationObject *)gobj; if (self->destroy_notify) self->destroy_notify(self->user_data); G_OBJECT_CLASS(regress_annotation_object_parent_class)->finalize(gobj); } static void regress_annotation_object_class_init (RegressAnnotationObjectClass *klass) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (klass); gobject_class->set_property = regress_annotation_object_set_property; gobject_class->get_property = regress_annotation_object_get_property; gobject_class->finalize = regress_annotation_object_finalize; /** * RegressAnnotationObject::string-signal: * @regress_annotation: the regress_annotation object * @string: (type utf8): a string * * This is a signal which has a broken signal handler, * it says it's pointer but it's actually a string. * * Since: 1.0 * Deprecated: 1.2: Use other-signal instead */ regress_annotation_object_signals[STRING_SIGNAL] = g_signal_new ("string-signal", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, (GSignalCMarshaller) g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * RegressAnnotationObject::list-signal: * @regress_annotation: the regress_annotation object * @list: (type GLib.List) (element-type utf8) (transfer container): a list of strings * * This is a signal which takes a list of strings, but it's not * known by GObject as it's only marked as G_TYPE_POINTER */ regress_annotation_object_signals[LIST_SIGNAL] = g_signal_new ("list-signal", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, (GSignalCMarshaller) g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * RegressAnnotationObject::doc-empty-arg-parsing: * @regress_annotation: the regress_annotation object * @arg1: * * This signal tests an empty document argument (@arg1) */ regress_annotation_object_signals[DOC_EMPTY_ARG_PARSING] = g_signal_new ("doc-empty-arg-parsing", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, (GSignalCMarshaller) g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * RegressAnnotationObject::attribute-signal: * @regress_annotation: the regress_annotation object * @arg1: (attributes some.annotation.foo1=val1): a value * @arg2: (attributes some.annotation.foo2=val2): another value * * This signal tests a signal with attributes. * * Returns: (attributes some.annotation.foo3=val3): the return value */ regress_annotation_object_signals[ATTRIBUTE_SIGNAL] = g_signal_new ("attribute-signal", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, /* marshaller */ G_TYPE_STRING, 2, G_TYPE_STRING, G_TYPE_STRING); /** * RegressAnnotationObject:string-property: * * This is a property which is a string * * Since: 1.0 * Deprecated: 1.2: Use better-string-property instead */ g_object_class_install_property (gobject_class, PROP_STRING_PROPERTY, g_param_spec_string ("string-property", "String property", "This property is a string", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * RegressAnnotationObject:function-property: (type RegressAnnotationCallback) */ g_object_class_install_property (gobject_class, PROP_FUNCTION_PROPERTY, g_param_spec_pointer ("function-property", "Function property", "This property is a function pointer", G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /* clang-format off */ /** * RegressAnnotationObject:tab-property: * * This is a property annotation intentionally indented with a mix * of tabs and strings to test the tab handling capabilities of the scanner. * * Since: 1.2 */ g_object_class_install_property (gobject_class, PROP_TAB_PROPERTY, g_param_spec_string ("tab-property", "Tab property", "This property is a thing", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /* clang-format on */ } static void regress_annotation_object_init (RegressAnnotationObject *object G_GNUC_UNUSED) { } /** * regress_annotation_object_method: * @object: a #GObject * * Return value: an int **/ gint regress_annotation_object_method (RegressAnnotationObject *object G_GNUC_UNUSED) { return 1; } /** * regress_annotation_object_out: * @object: a #GObject * @outarg: (out): This is an argument test * * This is a test for out arguments * * Return value: an int */ gint regress_annotation_object_out (RegressAnnotationObject *object G_GNUC_UNUSED, int *outarg) { *outarg = 2; return 1; } /** * regress_annotation_object_in: * @object: a #GObject * @inarg: (in) (transfer none): This is an argument test * * This is a test for in arguments * * Return value: an int */ gint regress_annotation_object_in (RegressAnnotationObject *object G_GNUC_UNUSED, int *inarg) { return *inarg; } /** * regress_annotation_object_inout: * @object: a #GObject * @inoutarg: (inout): This is an argument test * * This is a test for out arguments * * Return value: an int */ gint regress_annotation_object_inout (RegressAnnotationObject *object G_GNUC_UNUSED, int *inoutarg) { return *inoutarg += 1; } /** * regress_annotation_object_inout2: * @object: a #GObject * @inoutarg: (inout): This is an argument test * * This is a second test for out arguments * * Return value: an int */ gint regress_annotation_object_inout2 (RegressAnnotationObject *object G_GNUC_UNUSED, int *inoutarg) { return *inoutarg += 1; } /** * regress_annotation_object_inout3: * @object: a #GObject * @inoutarg: (inout) (allow-none): This is an argument test * * This is a 3th test for out arguments * * Return value: an int */ gint regress_annotation_object_inout3 (RegressAnnotationObject *object G_GNUC_UNUSED, int *inoutarg) { if (inoutarg) return *inoutarg + 1; return 1; } /** * regress_annotation_object_calleeowns: * @object: a #GObject * @toown: (out): a #GObject * * This is a test for out arguments; GObject defaults to transfer * * Return value: an int */ gint regress_annotation_object_calleeowns (RegressAnnotationObject *object G_GNUC_UNUSED, GObject **toown G_GNUC_UNUSED) { return 1; } /** * regress_annotation_object_calleesowns: * @object: a #GObject * @toown1: (out) (transfer full): a #GObject * @toown2: (out) (transfer none): a #GObject * * This is a test for out arguments, one transferred, other not * * Return value: an int */ gint regress_annotation_object_calleesowns (RegressAnnotationObject *object G_GNUC_UNUSED, GObject **toown1 G_GNUC_UNUSED, GObject **toown2 G_GNUC_UNUSED) { return 1; } /** * regress_annotation_object_get_strings: * @object: a #GObject * * This is a test for returning a list of strings, where * each string needs to be freed. * * Return value: (element-type utf8) (transfer full): list of strings */ GList * regress_annotation_object_get_strings (RegressAnnotationObject *object G_GNUC_UNUSED) { GList *list = NULL; list = g_list_prepend (list, g_strdup ("regress_annotation")); list = g_list_prepend (list, g_strdup ("bar")); return list; } /** * regress_annotation_object_get_hash: * @object: a #GObject * * This is a test for returning a hash table mapping strings to * objects. * * Return value: (element-type utf8 GObject) (transfer full): hash table */ GHashTable * regress_annotation_object_get_hash (RegressAnnotationObject *object) { GHashTable *hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); g_hash_table_insert (hash, g_strdup ("one"), g_object_ref (object)); g_hash_table_insert (hash, g_strdup ("two"), g_object_ref (object)); return hash; } /** * regress_annotation_object_with_voidp: * @data: Opaque pointer handle */ void regress_annotation_object_with_voidp (RegressAnnotationObject *object G_GNUC_UNUSED, void *data G_GNUC_UNUSED) { } /** * regress_annotation_object_get_objects: * @object: a #GObject * * This is a test for returning a list of objects. * The list itself should be freed, but not the internal objects, * intentionally similar example to gtk_container_get_children * * Return value: (element-type RegressAnnotationObject) (transfer container): list of objects */ GSList * regress_annotation_object_get_objects (RegressAnnotationObject *object) { GSList *list = NULL; list = g_slist_prepend (list, object); return list; } /** * regress_annotation_object_create_object: * @object: a #GObject * * Test returning a caller-owned object * * Return value: (transfer full): The object **/ GObject * regress_annotation_object_create_object (RegressAnnotationObject *object) { return G_OBJECT (g_object_ref (object)); } /** * regress_annotation_object_use_buffer: * @object: a #GObject * **/ void regress_annotation_object_use_buffer (RegressAnnotationObject *object G_GNUC_UNUSED, guchar *bytes G_GNUC_UNUSED) { } /** * regress_annotation_object_compute_sum: * @object: a #GObject * @nums: (array): Sequence of numbers * * Test taking a zero-terminated array **/ void regress_annotation_object_compute_sum (RegressAnnotationObject *object G_GNUC_UNUSED, int *nums G_GNUC_UNUSED) { } /** * regress_annotation_object_compute_sum_n: * @object: a #GObject * @nums: (array length=n_nums zero-terminated=0): Sequence of * numbers that are zero-terminated * @n_nums: Length of number array * * Test taking an array with length parameter **/ void regress_annotation_object_compute_sum_n (RegressAnnotationObject *object G_GNUC_UNUSED, int *nums G_GNUC_UNUSED, int n_nums G_GNUC_UNUSED) { } /** * regress_annotation_object_compute_sum_nz: * @object: a #RegressAnnotationObject * @nums: (array length=n_nums zero-terminated): Sequence of numbers that * are zero-terminated * @n_nums: Length of number array * * Test taking a zero-terminated array with length parameter **/ void regress_annotation_object_compute_sum_nz (RegressAnnotationObject *object G_GNUC_UNUSED, int *nums G_GNUC_UNUSED, int n_nums G_GNUC_UNUSED) { } /** * regress_annotation_object_parse_args: * @object: a #RegressAnnotationObject * @argc: (inout): Length of the argument vector * @argv: (inout) (array length=argc zero-terminated=1): Argument vector * * Test taking a zero-terminated array with length parameter **/ void regress_annotation_object_parse_args (RegressAnnotationObject *object G_GNUC_UNUSED, int *argc G_GNUC_UNUSED, char ***argv G_GNUC_UNUSED) { } /** * regress_annotation_object_string_out: * @object: a #RegressAnnotationObject * @str_out: (out) (transfer full): string return value * * Test returning a string as an out parameter * * Returns: some boolean **/ gboolean regress_annotation_object_string_out (RegressAnnotationObject *object G_GNUC_UNUSED, char **str_out G_GNUC_UNUSED) { return FALSE; } /** * regress_annotation_object_foreach: * @object: a #RegressAnnotationObject * @func: (scope call): Callback to invoke * @user_data: Callback user data * * Test taking a call-scoped callback **/ void regress_annotation_object_foreach (RegressAnnotationObject *object G_GNUC_UNUSED, RegressAnnotationForeachFunc func G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) { } /** * regress_annotation_object_set_data: * @object: a #RegressAnnotationObject * @data: (array length=length): The data * @length: Length of the data * * Test taking a guchar * with a length. **/ void regress_annotation_object_set_data (RegressAnnotationObject *object G_GNUC_UNUSED, const guchar *data G_GNUC_UNUSED, gsize length G_GNUC_UNUSED) { } /** * regress_annotation_object_set_data2: * @object: a #RegressAnnotationObject * @data: (array length=length) (element-type gint8): The data * @length: Length of the data * * Test taking a gchar * with a length. **/ void regress_annotation_object_set_data2 (RegressAnnotationObject *object G_GNUC_UNUSED, const gchar *data G_GNUC_UNUSED, gsize length G_GNUC_UNUSED) { } /** * regress_annotation_object_set_data3: * @object: a #RegressAnnotationObject * @data: (array length=length) (element-type guint8): The data * @length: Length of the data * * Test taking a gchar * with a length, overriding the array element * type. **/ void regress_annotation_object_set_data3 (RegressAnnotationObject *object G_GNUC_UNUSED, gpointer data G_GNUC_UNUSED, gsize length G_GNUC_UNUSED) { } /** * regress_annotation_object_allow_none: * @object: a #GObject * @somearg: (allow-none): * * Returns: (transfer none): %NULL always **/ GObject * regress_annotation_object_allow_none (RegressAnnotationObject *object G_GNUC_UNUSED, const gchar *somearg G_GNUC_UNUSED) { return NULL; } /** * regress_annotation_object_notrans: * @object: a #GObject * * Returns: (transfer none): An object, not referenced **/ GObject * regress_annotation_object_notrans (RegressAnnotationObject *object G_GNUC_UNUSED) { return NULL; } /** * regress_annotation_object_do_not_use: * @object: a #GObject * * Returns: (transfer none): %NULL always * Deprecated: 0.12: Use regress_annotation_object_create_object() instead. **/ GObject * regress_annotation_object_do_not_use (RegressAnnotationObject *object G_GNUC_UNUSED) { return NULL; } /** * regress_annotation_object_watch: (skip) * @object: A #RegressAnnotationObject * @func: The callback * @user_data: The callback data * * This is here just for the sake of being overriden by its * regress_annotation_object_watch_full(). */ void regress_annotation_object_watch (RegressAnnotationObject *object G_GNUC_UNUSED, RegressAnnotationForeachFunc func G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) { } /** * regress_annotation_object_watch_full: (rename-to regress_annotation_object_watch) * @object: A #RegressAnnotationObject * @func: The callback * @user_data: The callback data * @destroy: Destroy notification * * Test overriding via the "Rename To" annotation. */ void regress_annotation_object_watch_full (RegressAnnotationObject *object, RegressAnnotationForeachFunc func G_GNUC_UNUSED, gpointer user_data, GDestroyNotify destroy) { object->user_data = user_data; object->destroy_notify = destroy; } /** * regress_annotation_object_hidden_self: * @object: (type RegressAnnotationObject): A #RegressAnnotationObject **/ void regress_annotation_object_hidden_self (gpointer object G_GNUC_UNUSED) { } /** * regress_annotation_init: * @argc: (inout): The number of args. * @argv: (inout) (array length=argc): The arguments. **/ void regress_annotation_init (int *argc G_GNUC_UNUSED, char ***argv G_GNUC_UNUSED) { } /** * regress_annotation_return_array: * @length: (out): Number of return values * * Return value: (transfer full) (array length=length): The return value **/ char ** regress_annotation_return_array (int *length G_GNUC_UNUSED) { return NULL; } /** * regress_annotation_string_zero_terminated: * * Return value: (transfer full) (array zero-terminated=1): The return value **/ char ** regress_annotation_string_zero_terminated (void) { return NULL; } /** * regress_annotation_string_zero_terminated_out: * @out: (array zero-terminated=1) (inout): **/ void regress_annotation_string_zero_terminated_out (char ***out G_GNUC_UNUSED) { } /** * regress_annotation_versioned: * * Since: 0.6 **/ void regress_annotation_versioned (void) { } /** * regress_annotation_string_array_length: * @n_properties: * @properties: (array length=n_properties) (element-type utf8): */ void regress_annotation_string_array_length (guint n_properties G_GNUC_UNUSED, const gchar *const properties[] G_GNUC_UNUSED) { } /** * regress_annotation_object_extra_annos: (attributes org.foobar=testvalue) */ void regress_annotation_object_extra_annos (RegressAnnotationObject *object G_GNUC_UNUSED) { } static void *regress_annotation_user_data; static GDestroyNotify regress_annotation_destroy_notify; /** * regress_annotation_custom_destroy: * @callback: (destroy destroy) (closure data): Destroy notification * * Test messing up the heuristic of closure/destroy-notification * detection, and fixing it via annotations. */ void regress_annotation_custom_destroy (RegressAnnotationCallback callback G_GNUC_UNUSED, RegressAnnotationNotifyFunc destroy, gpointer data) { regress_annotation_user_data = data; regress_annotation_destroy_notify = destroy; } /** * regress_annotation_custom_destroy_cleanup: * * Use in tests for bindings with managed memory, to clean up the callback * passed to regress_annotation_custom_destroy(). */ void regress_annotation_custom_destroy_cleanup (void) { if (regress_annotation_destroy_notify) regress_annotation_destroy_notify(regress_annotation_user_data); } /** * regress_annotation_get_source_file: * * Return value: (type filename) (transfer full): Source file */ char * regress_annotation_get_source_file (void) { return NULL; } /** * regress_annotation_set_source_file: * @fname: (type filename): Source file * */ void regress_annotation_set_source_file (const char *fname G_GNUC_UNUSED) { } /** * regress_annotation_ptr_array: * @array: (element-type GObject.Value): the array */ void regress_annotation_ptr_array (GPtrArray *array G_GNUC_UNUSED) { } /** * regress_annotation_attribute_func: * @object: A #RegressAnnotationObject. * @data: (attributes some.annotation=value another.annotation=blahvalue): Some data. * * Returns: (attributes some.other.annotation=value2 yet.another.annotation=another_value): The return value. */ gint regress_annotation_attribute_func (RegressAnnotationObject *object G_GNUC_UNUSED, const gchar *data G_GNUC_UNUSED) { return 42; } /** * regress_annotation_invalid_regress_annotation: * @foo: some text (e.g. example) or else */ void regress_annotation_invalid_regress_annotation (int foo G_GNUC_UNUSED) { } char backslash_parsing_tester_2 = '\\'; /** * regress_annotation_test_parsing_bug630862: * * See https://bugzilla.gnome.org/show_bug.cgi?id=630862 * * Returns: (transfer none): An object, note the colon:in here */ GObject * regress_annotation_test_parsing_bug630862 (void) { return NULL; } /* clang-format off */ /** * regress_annotation_space_after_comment_bug631690: * * Explicitly test having a space after the ** here. */ void regress_annotation_space_after_comment_bug631690 (void) { } /* clang-format on */ /** * regress_annotation_return_filename: * * Returns: (type filename): An annotated filename */ gchar * regress_annotation_return_filename (void) { return g_strdup ("a utf-8 filename"); } /** * regress_annotation_transfer_floating: * @object: (in) (transfer floating): an object * * Returns: (transfer floating): A floating object */ GObject * regress_annotation_transfer_floating (GObject *object G_GNUC_UNUSED) { return NULL; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/annotation.h0000664000000000000000000002322115056773103024706 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2008-2009 Dan Winship SPDX-FileCopyrightText: 2008-2010 Colin Walters SPDX-FileCopyrightText: 2008-2011 Johan Dahlin SPDX-FileCopyrightText: 2008 Owen Taylor SPDX-FileCopyrightText: 2008 Tommi Komulainen SPDX-FileCopyrightText: 2008 Tristan Van Berkom SPDX-FileCopyrightText: 2009-2010 Andreas Rottmann SPDX-FileCopyrightText: 2010 litl, LLC SPDX-FileCopyrightText: 2010 Pavel Holejsovsky SPDX-FileCopyrightText: 2010 Red Hat, Inc. SPDX-FileCopyrightText: 2011 Jasper St. Pierre SPDX-FileCopyrightText: 2013 Stef Walter SPDX-FileCopyrightText: 2015 Christoph Reiter SPDX-FileCopyrightText: 2020 Centricular */ #pragma once #include #include #include "gitestmacros.h" typedef enum /*< flags,prefix=ANN >*/ { ANN_FLAG_FOO = 1, ANN_FLAG_BAR = 2, /** * ANN_FLAG_FOOBAR: * * Since: 1.4 */ ANN_FLAG_FOOBAR = 3, } RegressAnnotationBitfield; /** * RegressAnnotationCallback: * @in: (in) (transfer none): array of ints * * This is a callback. * Return value: (transfer none): array of ints */ typedef const gint *(*RegressAnnotationCallback) (const gint *in); /** * RegressAnnotationListCallback: * @in: (in) (transfer none) (element-type utf8): list of strings * * This is a callback taking a list. * Return value: (transfer container) (element-type utf8): list of strings */ typedef GList *(*RegressAnnotationListCallback) (GList *in); /** * RegressAnnotationNotifyFunc: * @data: (closure): The user data * * This is a callback with a 'closure' argument that is not named * 'user_data' and hence has to be annotated. */ typedef void (*RegressAnnotationNotifyFunc) (gpointer data); /** * RegressAnnotationObject: (attributes org.example.Test=cows) * * This is an object used to test annotations. */ typedef struct _RegressAnnotationObject RegressAnnotationObject; typedef struct _RegressAnnotationObjectClass RegressAnnotationObjectClass; typedef void (*RegressAnnotationForeachFunc) (RegressAnnotationObject *object, const char *item, gpointer user_data); struct _RegressAnnotationObject { GObject parent_instance; /*< private >*/ void *user_data; GDestroyNotify destroy_notify; }; struct _RegressAnnotationObjectClass { GObjectClass parent_class; }; GI_TEST_EXTERN GType regress_annotation_object_get_type (void); GI_TEST_EXTERN gint regress_annotation_object_method (RegressAnnotationObject *object); GI_TEST_EXTERN gint regress_annotation_object_out (RegressAnnotationObject *object, int *outarg); GI_TEST_EXTERN GObject *regress_annotation_object_create_object (RegressAnnotationObject *object); GI_TEST_EXTERN GObject *regress_annotation_object_allow_none (RegressAnnotationObject *object, const gchar *somearg); GI_TEST_EXTERN GObject *regress_annotation_object_notrans (RegressAnnotationObject *object); GI_TEST_EXTERN gint regress_annotation_object_inout (RegressAnnotationObject *object, int *inoutarg); GI_TEST_EXTERN gint regress_annotation_object_inout2 (RegressAnnotationObject *object, int *inoutarg); GI_TEST_EXTERN gint regress_annotation_object_inout3 (RegressAnnotationObject *object, int *inoutarg); GI_TEST_EXTERN gint regress_annotation_object_in (RegressAnnotationObject *object, int *inarg); GI_TEST_EXTERN gint regress_annotation_object_calleeowns (RegressAnnotationObject *object, GObject **toown); GI_TEST_EXTERN gint regress_annotation_object_calleesowns (RegressAnnotationObject *object, GObject **toown1, GObject **toown2); GI_TEST_EXTERN GList *regress_annotation_object_get_strings (RegressAnnotationObject *object); GI_TEST_EXTERN GHashTable *regress_annotation_object_get_hash (RegressAnnotationObject *object); GI_TEST_EXTERN void regress_annotation_object_with_voidp (RegressAnnotationObject *object, void *data); GI_TEST_EXTERN GSList *regress_annotation_object_get_objects (RegressAnnotationObject *object); GI_TEST_EXTERN void regress_annotation_object_use_buffer (RegressAnnotationObject *object, guchar *bytes); GI_TEST_EXTERN void regress_annotation_object_compute_sum (RegressAnnotationObject *object, int *nums); GI_TEST_EXTERN void regress_annotation_object_compute_sum_n (RegressAnnotationObject *object, int *nums, int n_nums); GI_TEST_EXTERN void regress_annotation_object_compute_sum_nz (RegressAnnotationObject *object, int *nums, int n_nums); GI_TEST_EXTERN void regress_annotation_object_parse_args (RegressAnnotationObject *object, int *argc, char ***argv); GI_TEST_EXTERN gboolean regress_annotation_object_string_out (RegressAnnotationObject *object, char **str_out); GI_TEST_EXTERN void regress_annotation_object_foreach (RegressAnnotationObject *object, RegressAnnotationForeachFunc func, gpointer user_data); GI_TEST_EXTERN void regress_annotation_object_set_data (RegressAnnotationObject *object, const guchar *data, gsize length); GI_TEST_EXTERN void regress_annotation_object_set_data2 (RegressAnnotationObject *object, const gchar *data, gsize length); GI_TEST_EXTERN void regress_annotation_object_set_data3 (RegressAnnotationObject *object, gpointer data, gsize length); GI_TEST_EXTERN GObject *regress_annotation_object_do_not_use (RegressAnnotationObject *object); GI_TEST_EXTERN void regress_annotation_object_watch (RegressAnnotationObject *object, RegressAnnotationForeachFunc func, gpointer user_data); GI_TEST_EXTERN void regress_annotation_object_watch_full (RegressAnnotationObject *object, RegressAnnotationForeachFunc func, gpointer user_data, GDestroyNotify destroy); GI_TEST_EXTERN void regress_annotation_object_hidden_self (gpointer object); GI_TEST_EXTERN void regress_annotation_init (int *argc, char ***argv); GI_TEST_EXTERN char **regress_annotation_return_array (int *length); GI_TEST_EXTERN void regress_annotation_versioned (void); GI_TEST_EXTERN char **regress_annotation_string_zero_terminated (void); GI_TEST_EXTERN void regress_annotation_string_zero_terminated_out (char ***out); GI_TEST_EXTERN void regress_annotation_string_array_length (guint n_properties, const gchar *const properties[]); GI_TEST_EXTERN void regress_annotation_object_extra_annos (RegressAnnotationObject *object); GI_TEST_EXTERN void regress_annotation_custom_destroy (RegressAnnotationCallback callback, RegressAnnotationNotifyFunc destroy, gpointer data); GI_TEST_EXTERN void regress_annotation_custom_destroy_cleanup (void); GI_TEST_EXTERN char *regress_annotation_get_source_file (void); GI_TEST_EXTERN void regress_annotation_set_source_file (const char *fname); GI_TEST_EXTERN gint regress_annotation_attribute_func (RegressAnnotationObject *object, const gchar *data); GI_TEST_EXTERN void regress_annotation_invalid_regress_annotation (int foo); /** * RegressAnnotationStruct: * * This is a test of an array of object in an field of a struct. */ struct RegressAnnotationStruct { RegressAnnotationObject *objects[10]; }; /** * RegressAnnotationFields: * @field1: Some documentation * @arr: (array length=len): an array of length @len * @len: the length of array * * This is a struct for testing field documentation and annotations */ struct RegressAnnotationFields { int field1; guchar *arr; gulong len; /** * RegressAnnotationFields.field4: * * A new field, breaking ABI is fun! * * Since: 1.4 */ guint field4; }; GI_TEST_EXTERN void regress_annotation_ptr_array (GPtrArray *array); GI_TEST_EXTERN GObject *regress_annotation_test_parsing_bug630862 (void); GI_TEST_EXTERN void regress_annotation_space_after_comment_bug631690 (void); GI_TEST_EXTERN gchar *regress_annotation_return_filename (void); GI_TEST_EXTERN GObject *regress_annotation_transfer_floating (GObject *object); /* This one we can handle properly */ #define REGRESS_ANNOTATION_CALCULATED_DEFINE (10 * 10) /** * REGRESS_ANNOTATION_CALCULATED_LARGE: (value 10000000000UL) * * Constant to define a calculated large value * * Since: 1.4 */ #define REGRESS_ANNOTATION_CALCULATED_LARGE (1000 * G_GINT64_CONSTANT (10000000)) /** * REGRESS_ANNOTATION_CALCULATED_LARGE_DIV: (value 1000000UL) * * Constant to define a calculated large value */ #define REGRESS_ANNOTATION_CALCULATED_LARGE_DIV (1000 / G_GINT64_CONSTANT (10000000)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/docs/provenance.txt0000664000000000000000000000455515056773103026225 0ustar00rootrootThis repository was split off of gobject-introspection at commit c39cb45. All commits not containing tests were pruned from the history using git-filter-repo (https://github.com/newren/git-filter-repo/) at commit ac50405. Created by: $ git clone git@ssh.gitlab.gnome.org:GNOME/gobject-introspection.git gobject-introspection-tests $ cd gobject-introspection-tests $ git filter-repo --paths-from-file ../renames.txt $ git filter-repo --invert-paths --paths-from-file ../removals.txt $ git branch | grep -v main | xargs git branch -D $ git tag | xargs git tag -d Contents of renames.txt: gir/everything.c==>everything.c gir/everything.h==>everything.h gir/gimarshallingtests.c==>gimarshallingtests.c gir/gimarshallingtests.h==>gimarshallingtests.h tests/everything/everything.c==>everything.c tests/everything/everything.h==>everything.h tests/everything/gitesttypes.c==>gitesttypes.c tests/everything/gitesttypes.h==>gitesttypes.h tests/gimarshallingtests.c==>gimarshallingtests.c tests/gimarshallingtests.h==>gimarshallingtests.h tests/gitestmacros.h==>gitestmacros.h tests/parser/foo-object.h==>foo.h tests/parser/foo.c==>foo.c tests/parser/utility.c==>utility.c tests/parser/utility.h==>utility.h tests/scanner/annotation.c==>annotation.c tests/scanner/annotation.h==>annotation.h tests/scanner/drawable.c==>drawable.c tests/scanner/drawable.h==>drawable.h tests/scanner/everything.c==>everything.c tests/scanner/everything.h==>everything.h tests/scanner/foo-object.h==>foo.h tests/scanner/foo.c==>foo.c tests/scanner/foo.h==>foo.h tests/scanner/regress.c==>regress.c tests/scanner/regress.h==>regress.h tests/scanner/warnlib.c==>warnlib.c tests/scanner/warnlib.h==>warnlib.h tests/scanner/utility.c==>utility.c tests/scanner/utility.h==>utility.h tests/types/gitesttypes.c==>gitesttypes.c tests/types/gitesttypes.h==>gitesttypes.h Contents of removals.txt: glob:*.am glob:*.pc.in glob:*.rst glob:*.txt .dir-locals.el .flake8 .gitignore .gitlab-ci .gitlab-ci.yml .readthedocs.yaml .topdeps .topmsg acinclude.m4 AUTHORS autogen.sh build ChangeLog ChangeLog.pre-git common.mk config.h.win32.in configure.ac CONTRIBUTORS COPYING.tools docs examples g-ir-diff gcov.mak gidl gidl.dtd gir girepository giscanner gobject-introspection.doap gtk-doc-shave.patch HACKING m4 MAINTAINERS Makefile.introspection meson.build misc mypy.ini NEWS README README.msvc relaxng scripts src subprojects tests TODO tools win32 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/drawable.c0000664000000000000000000000330215056773103024306 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2008 Colin Walters SPDX-FileCopyrightText: 2008 Johan Bilien SPDX-FileCopyrightText: 2008 Johan Dahlin */ #include #include "drawable.h" G_DEFINE_ABSTRACT_TYPE (RegressTestInheritDrawable, regress_test_inherit_drawable, G_TYPE_OBJECT); static void regress_test_inherit_drawable_class_init (RegressTestInheritDrawableClass *klass G_GNUC_UNUSED) { } static void regress_test_inherit_drawable_init (RegressTestInheritDrawable *drawable G_GNUC_UNUSED) { } void regress_test_inherit_drawable_do_foo (RegressTestInheritDrawable *drawable G_GNUC_UNUSED, int x G_GNUC_UNUSED) { } /** * regress_test_inherit_drawable_get_origin: * @drawable: * @x: (out): * @y: (out): */ void regress_test_inherit_drawable_get_origin (RegressTestInheritDrawable *drawable G_GNUC_UNUSED, int *x, int *y) { *x = 0; *y = 0; } /** * regress_test_inherit_drawable_get_size: * @drawable: * @width: (out): * @height: (out): */ void regress_test_inherit_drawable_get_size (RegressTestInheritDrawable *drawable G_GNUC_UNUSED, guint *width, guint *height) { *width = 42; *height = 42; } void regress_test_inherit_drawable_do_foo_maybe_throw (RegressTestInheritDrawable *drawable G_GNUC_UNUSED, int x, GError **error) { if (x != 42) g_set_error (error, G_IO_ERROR, 12, "The answer should be 42!"); } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/drawable.h0000664000000000000000000000252215056773103024316 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2008 Colin Walters SPDX-FileCopyrightText: 2008 Johan Bilien SPDX-FileCopyrightText: 2008 Johan Dahlin */ #pragma once #include #include #include "gitestmacros.h" typedef struct _RegressTestInheritDrawable RegressTestInheritDrawable; typedef struct _RegressTestInheritDrawableClass RegressTestInheritDrawableClass; struct _RegressTestInheritDrawable { GObject parent_instance; }; struct _RegressTestInheritDrawableClass { GObjectClass parent_class; }; GI_TEST_EXTERN GType regress_test_inherit_drawable_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN void regress_test_inherit_drawable_do_foo (RegressTestInheritDrawable *drawable, int x); GI_TEST_EXTERN void regress_test_inherit_drawable_get_origin (RegressTestInheritDrawable *drawable, int *x, int *y); GI_TEST_EXTERN void regress_test_inherit_drawable_get_size (RegressTestInheritDrawable *drawable, guint *width, guint *height); GI_TEST_EXTERN void regress_test_inherit_drawable_do_foo_maybe_throw (RegressTestInheritDrawable *drawable, int x, GError **error); typedef struct _RegressTestInheritPixmapObjectClass RegressTestInheritPixmapObjectClass; struct _RegressTestInheritPixmapObjectClass { RegressTestInheritDrawableClass parent_class; }; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/foo.c0000664000000000000000000005516115056773103023322 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2007-2010 Johan Dahlin SPDX-FileCopyrightText: 2008-2010 Colin Walters SPDX-FileCopyrightText: 2008 Jürg Billeter SPDX-FileCopyrightText: 2008 Philip Van Hoof SPDX-FileCopyrightText: 2009, 2011-2012 Dan Winship SPDX-FileCopyrightText: 2010 Collabora, Ltd. SPDX-FileCopyrightText: 2010 litl, LLC SPDX-FileCopyrightText: 2010 Sugar Labs SPDX-FileCopyrightText: 2011 Owen Taylor SPDX-FileCopyrightText: 2011 Red Hat, Inc. SPDX-FileCopyrightText: 2011 Torsten Schönfeld SPDX-FileCopyrightText: 2018 Christoph Reiter SPDX-FileCopyrightText: 2020 Centricular SPDX-FileCopyrightText: 2024 Simon McVittie SPDX-FileCopyrightText: 2024 Philip Chimento */ #include #include "foo.h" /** * SECTION:standalone_section * * This documentation section isn't associated with an object * in particular, but it should be serialized in the gir nevertheless. */ /* A hidden type not exposed publicly, similar to GUPNP's XML wrapper object */ typedef struct _RegressFooHidden RegressFooHidden; void regress_foo_private_function (RegressFooObject *regress_foo); void regress_foo_do_regress_foo (RegressFooInterface *self, int x); RegressFooHidden *regress_foo_hidden_copy (const RegressFooHidden *boxed); void regress_foo_hidden_free (RegressFooHidden *boxed); GType regress_foo_hidden_get_type (void); RegressFooBoxed *regress_foo_boxed_copy (const RegressFooBoxed *boxed); void regress_foo_boxed_free (RegressFooBoxed *boxed); void regress_foo_dbus_data_free (RegressFooDBusData *boxed); RegressFooDBusData *regress_foo_dbus_data_copy (const RegressFooDBusData *boxed); typedef struct { int i; } PrivateStruct; void regress_foo_private_function (RegressFooObject *regress_foo G_GNUC_UNUSED) { } GType regress_foo_interface_get_type (void) { static GType object_type = 0; if (!object_type) { object_type = g_type_register_static_simple (G_TYPE_INTERFACE, "RegressFooInterface", sizeof (RegressFooInterfaceIface), NULL, 0, NULL, 0); g_type_interface_add_prerequisite (object_type, G_TYPE_OBJECT); } return object_type; } void regress_foo_interface_do_regress_foo (RegressFooInterface *self, int x) { REGRESS_FOO_INTERFACE_GET_INTERFACE (self)->do_regress_foo (self, x); } void regress_foo_interface_static_method (int x G_GNUC_UNUSED) { } enum { PROP_0, PROP_STRING, PROP_HIDDEN }; enum { SIGNAL, LAST_SIGNAL }; static guint regress_foo_object_signals[LAST_SIGNAL] = { 0 }; static void regress_foo_regress_foo_interface_init (gpointer g_iface, gpointer iface_data G_GNUC_UNUSED) { RegressFooInterfaceIface *iface = (RegressFooInterfaceIface *) g_iface; iface->do_regress_foo = regress_foo_do_regress_foo; } enum { SUBIFACE_DESTROY_EVENT, SUBIFACE_LAST_SIGNAL }; static void regress_foo_sub_interface_class_init (gpointer g_class, gpointer class_data); static guint regress_foo_subiface_signals[SUBIFACE_LAST_SIGNAL] = { 0 }; GType regress_foo_sub_interface_get_type (void) { static GType object_type = 0; if (!object_type) { object_type = g_type_register_static_simple (G_TYPE_INTERFACE, "RegressFooSubInterface", sizeof (RegressFooSubInterfaceIface), regress_foo_sub_interface_class_init, 0, NULL, 0); g_type_interface_add_prerequisite (object_type, REGRESS_FOO_TYPE_INTERFACE); } return object_type; } static void regress_foo_sub_interface_class_init (gpointer g_class G_GNUC_UNUSED, gpointer class_data G_GNUC_UNUSED) { regress_foo_subiface_signals[SUBIFACE_DESTROY_EVENT] = g_signal_new ("destroy-event", REGRESS_FOO_TYPE_SUBINTERFACE, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (RegressFooSubInterfaceIface, destroy_event), NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE); } void regress_foo_sub_interface_do_bar (RegressFooSubInterface *self) { REGRESS_FOO_SUBINTERFACE_GET_INTERFACE (self)->do_bar (self); } /** * regress_foo_sub_interface_do_baz: * @self: * @callback: (scope call): * @user_data: */ void regress_foo_sub_interface_do_baz (RegressFooSubInterface *self, GCallback callback, gpointer user_data) { REGRESS_FOO_SUBINTERFACE_GET_INTERFACE (self)->do_baz (self, callback, user_data); } G_DEFINE_TYPE_EXTENDED (RegressFooObject, regress_foo_object, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (REGRESS_FOO_TYPE_INTERFACE, regress_foo_regress_foo_interface_init)); static void regress_foo_object_set_property (GObject *object, guint prop_id, const GValue *value G_GNUC_UNUSED, GParamSpec *pspec) { switch (prop_id) { case PROP_STRING: break; case PROP_HIDDEN: break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void regress_foo_object_get_property (GObject *object, guint prop_id, GValue *value G_GNUC_UNUSED, GParamSpec *pspec) { switch (prop_id) { case PROP_STRING: break; case PROP_HIDDEN: break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void regress_foo_object_class_init (RegressFooObjectClass *klass) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (klass); gobject_class->set_property = regress_foo_object_set_property; gobject_class->get_property = regress_foo_object_get_property; g_object_class_install_property (gobject_class, PROP_STRING, g_param_spec_string ("string", "String nick", "The String Property Blurb", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_HIDDEN, g_param_spec_boxed ("hidden", "hidden property", "should not be exposed", regress_foo_hidden_get_type (), G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); regress_foo_object_signals[SIGNAL] = g_signal_new ("signal", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, (GSignalCMarshaller) g_cclosure_marshal_STRING__OBJECT_POINTER, G_TYPE_STRING, 2, G_TYPE_OBJECT, G_TYPE_POINTER); } static void regress_foo_object_init (RegressFooObject *object G_GNUC_UNUSED) { } RegressFooObject * regress_foo_object_new (void) { return g_object_new (REGRESS_FOO_TYPE_OBJECT, NULL); } GObject * regress_foo_object_new_as_super (void) { return g_object_new (REGRESS_FOO_TYPE_OBJECT, NULL); } /** * regress_foo_object_external_type: * @object: a #RegressFooObject * * Returns: (transfer none): %NULL always */ UtilityObject * regress_foo_object_external_type (RegressFooObject *object G_GNUC_UNUSED) { return NULL; } void regress_foo_object_various (RegressFooObject *object G_GNUC_UNUSED, void *data G_GNUC_UNUSED, GType some_type G_GNUC_UNUSED) { } void regress_foo_object_take_all (RegressFooObject *object G_GNUC_UNUSED, int x G_GNUC_UNUSED, ...) { } void regress_foo_do_regress_foo (RegressFooInterface *self G_GNUC_UNUSED, int x G_GNUC_UNUSED) { } void regress_foo_object_is_it_time_yet (RegressFooObject *object G_GNUC_UNUSED, time_t time G_GNUC_UNUSED) { } void regress_foo_object_seek (RegressFooObject *object G_GNUC_UNUSED, off_t offset G_GNUC_UNUSED) { } /** * regress_foo_object_new_cookie: (skip) * @object: * @target: * * Not sure why this test is here... */ RegressFooObjectCookie regress_foo_object_new_cookie (RegressFooObject *object G_GNUC_UNUSED, const char *target G_GNUC_UNUSED) { return NULL; } const char * regress_foo_object_get_name (RegressFooObject *object G_GNUC_UNUSED) { return "regress_foo"; } char * regress_foo_object_dup_name (RegressFooObject *object G_GNUC_UNUSED) { return g_strdup ("regress_foo"); } void regress_foo_object_handle_glyph (RegressFooObject *object G_GNUC_UNUSED, UtilityGlyph glyph G_GNUC_UNUSED) { } gboolean regress_foo_object_virtual_method (RegressFooObject *object, int first_param) { RegressFooObjectClass *klass = REGRESS_FOO_OBJECT_GET_CLASS (object); if (!klass->virtual_method) return FALSE; return klass->virtual_method (object, first_param); } /** * regress_foo_object_read: (virtual read_fn) * @object: obj * @offset: offset * @length: length * * Read some stuff. */ void regress_foo_object_read (RegressFooObject *object G_GNUC_UNUSED, int offset G_GNUC_UNUSED, int length G_GNUC_UNUSED) { } /** * regress_foo_object_static_meth: * * Returns: */ int regress_foo_object_static_meth (void) { return 77; } /** * regress_foo_object_skipped_method: (skip) * @object: obj * * This is only useful from C. */ void regress_foo_object_skipped_method (RegressFooObject *object G_GNUC_UNUSED) { } G_DEFINE_ABSTRACT_TYPE (RegressFooSubobject, regress_foo_subobject, REGRESS_FOO_TYPE_OBJECT); static void regress_foo_subobject_class_init (RegressFooSubobjectClass *klass G_GNUC_UNUSED) { } static void regress_foo_subobject_init (RegressFooSubobject *object G_GNUC_UNUSED) { } /** * regress_foo_object_get_default: * * This function is intended to match clutter_stage_get_default which * uses a C sugar return type. * * Return value: (type RegressFooSubobject) (transfer none): The global #RegressFooSubobject */ RegressFooObject * regress_foo_object_get_default (void) { return NULL; } int regress_foo_init (void) { return REGRESS_FOO_SUCCESS_INT; } /** * regress_foo_init_argv: * @argc: * @argv: (array length=argc) (allow-none): */ int regress_foo_init_argv (int argc G_GNUC_UNUSED, char **argv G_GNUC_UNUSED) { return REGRESS_FOO_SUCCESS_INT; } /** * regress_foo_init_argv_address: * @argc: (inout): * @argv: (array length=argc) (inout) (allow-none): */ int regress_foo_init_argv_address (int *argc G_GNUC_UNUSED, char ***argv G_GNUC_UNUSED) { return REGRESS_FOO_SUCCESS_INT; } GType regress_foo_enum_type_get_type (void) { static GType etype = 0; if (G_UNLIKELY (etype == 0)) { static const GEnumValue values[] = { { REGRESS_FOO_ENUM_ALPHA, "REGRESS_FOO_ENUM_ALPHA", "alpha" }, { REGRESS_FOO_ENUM_BETA, "REGRESS_FOO_ENUM_BETA", "beta" }, { REGRESS_FOO_ENUM_DELTA, "REGRESS_FOO_ENUM_DELTA", "delta" }, { 0, NULL, NULL } }; etype = g_enum_register_static (g_intern_static_string ("RegressFooEnumType"), values); } return etype; } int regress_foo_enum_method (RegressFooEnumType regress_foo_enum G_GNUC_UNUSED) { return 0; } int regress_foo_enum_type_method (RegressFooEnumType regress_foo_enum) { return (regress_foo_enum + 1) % 3; } RegressFooEnumType regress_foo_enum_type_returnv (int x) { return (x + 1) % 3; } GType regress_foo_flags_type_get_type (void) { static GType etype = 0; if (G_UNLIKELY (etype == 0)) { static const GFlagsValue values[] = { { REGRESS_FOO_FLAGS_FIRST, "REGRESS_FOO_FLAGS_FIRST", "first" }, { REGRESS_FOO_FLAGS_SECOND, "REGRESS_FOO_FLAGS_SECOND", "second" }, { REGRESS_FOO_FLAGS_THIRD, "REGRESS_FOO_FLAGS_THIRD", "third" }, { 0, NULL, NULL } }; etype = g_flags_register_static (g_intern_static_string ("RegressFooFlagsType"), values); } return etype; } struct _RegressFooBoxed { int private; }; RegressFooBoxed * regress_foo_boxed_copy (const RegressFooBoxed *boxed) { #if GLIB_CHECK_VERSION(2, 67, 5) return (RegressFooBoxed *) g_memdup2 (boxed, sizeof (RegressFooBoxed)); #else return (RegressFooBoxed *) g_memdup (boxed, sizeof (RegressFooBoxed)); #endif } void regress_foo_boxed_free (RegressFooBoxed *boxed) { g_slice_free (RegressFooBoxed, boxed); } GType regress_foo_boxed_get_type (void) { static GType our_type = 0; if (our_type == 0) our_type = g_boxed_type_register_static ("RegressFooBoxed", (GBoxedCopyFunc) regress_foo_boxed_copy, (GBoxedFreeFunc) regress_foo_boxed_free); return our_type; } RegressFooBoxed * regress_foo_boxed_new (void) { return g_slice_new0 (RegressFooBoxed); } void regress_foo_boxed_method (RegressFooBoxed *boxed G_GNUC_UNUSED) { } /* RegressFooDbus */ struct _RegressFooDBusData { double private; }; RegressFooDBusData * regress_foo_dbus_data_copy (const RegressFooDBusData *boxed) { #if GLIB_CHECK_VERSION(2, 67, 5) return (RegressFooDBusData *) g_memdup2 (boxed, sizeof (RegressFooDBusData)); #else return (RegressFooDBusData *) g_memdup (boxed, sizeof (RegressFooDBusData)); #endif } void regress_foo_dbus_data_free (RegressFooDBusData *boxed) { g_slice_free (RegressFooDBusData, boxed); } GType regress_foo_dbus_data_get_type (void) { static GType our_type = 0; if (our_type == 0) our_type = g_boxed_type_register_static ("RegressFooDBusData", (GBoxedCopyFunc) regress_foo_dbus_data_copy, (GBoxedFreeFunc) regress_foo_dbus_data_free); return our_type; } static RegressFooBRect * regress_foo_brect_copy (const RegressFooBRect *boxed) { #if GLIB_CHECK_VERSION(2, 67, 5) return (RegressFooBRect *) g_memdup2 (boxed, sizeof (RegressFooBRect)); #else return (RegressFooBRect *) g_memdup (boxed, sizeof (RegressFooBRect)); #endif } GType regress_foo_brect_get_type (void) { static GType our_type = 0; if (our_type == 0) our_type = g_boxed_type_register_static ("RegressFooBRect", (GBoxedCopyFunc) regress_foo_brect_copy, (GBoxedFreeFunc) g_free); return our_type; } RegressFooBRect * regress_foo_brect_new (double x, double y) { RegressFooBRect *retval = g_new(RegressFooBRect, 1); retval->x = x; retval->y = y; return retval; } void regress_foo_brect_add (RegressFooBRect *b1 G_GNUC_UNUSED, RegressFooBRect *b2 G_GNUC_UNUSED) { } static RegressFooBUnion * regress_foo_bunion_copy (const RegressFooBUnion *boxed) { #if GLIB_CHECK_VERSION(2, 67, 5) return (RegressFooBUnion *) g_memdup2 (boxed, sizeof (RegressFooBUnion)); #else return (RegressFooBUnion *) g_memdup (boxed, sizeof (RegressFooBUnion)); #endif } GType regress_foo_bunion_get_type (void) { static GType our_type = 0; if (our_type == 0) our_type = g_boxed_type_register_static ("RegressFooBUnion", (GBoxedCopyFunc) regress_foo_bunion_copy, (GBoxedFreeFunc) g_free); return our_type; } RegressFooBUnion * regress_foo_bunion_new (void) { return g_new0(RegressFooBUnion, 1); } void regress_foo_test_unsigned (unsigned int uint G_GNUC_UNUSED) { } /** * regress_foo_test_string_array: * @array: (array zero-terminated=1): */ void regress_foo_test_string_array (char **array G_GNUC_UNUSED) { } /** * regress_foo_test_string_array_with_g: * @array: (array zero-terminated=1): */ void regress_foo_test_string_array_with_g (gchar **array G_GNUC_UNUSED) { } /** * regress_foo_test_array: * * Returns: (element-type utf8) (transfer container): */ GArray * regress_foo_test_array (void) { return NULL; } /** * regress_foo_rectangle_new: (skip) * * This is a C convenience constructor; we have to (skip) * it because it's not a boxed type. */ RegressFooRectangle * regress_foo_rectangle_new (int x, int y, int width, int height) { RegressFooRectangle *r = g_slice_new (RegressFooRectangle); r->x = x; r->y = y; r->width = width; r->height = height; return r; } /** * regress_foo_rectangle_add: * @r1: add to this rect * @r2: source rectangle */ void regress_foo_rectangle_add (RegressFooRectangle *r1 G_GNUC_UNUSED, const RegressFooRectangle *r2 G_GNUC_UNUSED) { } void regress_foo_method_external_references (UtilityObject *object G_GNUC_UNUSED, UtilityEnumType e G_GNUC_UNUSED, UtilityFlagType f G_GNUC_UNUSED, UtilityStruct s G_GNUC_UNUSED) { } /* RegressFooHidden */ struct _RegressFooHidden { char *frob; }; RegressFooHidden * regress_foo_hidden_copy (const RegressFooHidden *boxed) { #if GLIB_CHECK_VERSION(2, 67, 5) return (RegressFooHidden *) g_memdup2 (boxed, sizeof (RegressFooHidden)); #else return (RegressFooHidden *) g_memdup (boxed, sizeof (RegressFooHidden)); #endif } void regress_foo_hidden_free (RegressFooHidden *boxed) { g_slice_free (RegressFooHidden, boxed); } GType regress_foo_hidden_get_type (void) { static GType our_type = 0; if (our_type == 0) our_type = g_boxed_type_register_static ("RegressFooHidden", (GBoxedCopyFunc) regress_foo_hidden_copy, (GBoxedFreeFunc) regress_foo_hidden_free); return our_type; } GType regress_foo_error_get_type (void) { static GType etype = 0; if (G_UNLIKELY (etype == 0)) { static const GEnumValue values[] = { { REGRESS_FOO_ERROR_GOOD, "REGRESS_FOO_ERROR_GOOD", "good" }, { REGRESS_FOO_ERROR_BAD, "REGRESS_FOO_ERROR_BAD", "bad" }, { REGRESS_FOO_ERROR_UGLY, "REGRESS_FOO_ERROR_UGLY", "ugly" }, { 0, NULL, NULL } }; etype = g_enum_register_static (g_intern_static_string ("RegressFooError"), values); } return etype; } GQuark regress_foo_error_quark (void) { return g_quark_from_static_string ("regress_foo-error-quark"); } void regress_foo_some_variant (guint x G_GNUC_UNUSED, va_list args G_GNUC_UNUSED) { } GType regress_foo_tile_handler_get_type (void); /* This setup of a totally hidden parent class matches * http://bugzilla.gnome.org/show_bug.cgi?id=561360 */ #define REGRESS_FOO_TYPE_TILE_HANDLER (regress_foo_tile_handler_get_type ()) #define REGRESS_FOO_TILE_HANDLER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_FOO_TYPE_TILE_HANDLER, RegressFooTileHandler)) #define REGRESS_FOO_IS_TILE_HANDLER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_FOO_TYPE_TILE_HANDLER)) struct _RegressFooTileHandler { RegressFooObject parent_instance; }; struct _RegressFooTileHandlerClass { RegressFooObjectClass parent_class; }; typedef struct _RegressFooTileHandler RegressFooTileHandler; typedef struct _RegressFooTileHandlerClass RegressFooTileHandlerClass; G_DEFINE_TYPE (RegressFooTileHandler, regress_foo_tile_handler, REGRESS_FOO_TYPE_OBJECT); static void regress_foo_tile_handler_class_init (RegressFooTileHandlerClass *klass G_GNUC_UNUSED) { } static void regress_foo_tile_handler_init (RegressFooTileHandler *object G_GNUC_UNUSED) { } struct _RegressFooBuffer { RegressFooTileHandler parent_instance; }; struct _RegressFooBufferClass { RegressFooTileHandlerClass parent_class; }; G_DEFINE_TYPE (RegressFooBuffer, regress_foo_buffer, REGRESS_FOO_TYPE_TILE_HANDLER); static void regress_foo_buffer_class_init (RegressFooBufferClass *klass G_GNUC_UNUSED) { } static void regress_foo_buffer_init (RegressFooBuffer *object G_GNUC_UNUSED) { } void regress_foo_buffer_some_method (RegressFooBuffer *buffer G_GNUC_UNUSED) { } struct _RegressFooOtherObject { GObject parent_instance; }; struct _RegressFooOtherObjectClass { GObjectClass parent_class; }; G_DEFINE_TYPE (RegressFooOtherObject, regress_foo_other_object, G_TYPE_OBJECT); static void regress_foo_other_object_class_init (RegressFooOtherObjectClass *klass G_GNUC_UNUSED) { } static void regress_foo_other_object_init (RegressFooOtherObject *object G_GNUC_UNUSED) { } #define REGRESS_FOO_DEFINE_SHOULD_NOT_BE_EXPOSED "should not be exposed" /** * regress_foo_skip_me: (skip) * @fs: a #RegressFooSkippable * * Does something that's only interesting from C and should not be * exposed to language bindings. */ void regress_foo_skip_me (RegressFooSkippable fs G_GNUC_UNUSED) { } /** * RegressFooForeignStruct: (foreign) * */ RegressFooForeignStruct * regress_foo_foreign_struct_new (void) { return g_slice_new0 (RegressFooForeignStruct); } RegressFooForeignStruct * regress_foo_foreign_struct_copy (RegressFooForeignStruct *original) { RegressFooForeignStruct *copy; copy = regress_foo_foreign_struct_new (); copy->regress_foo = original->regress_foo; return copy; } /** * regress_foo_test_varargs_callback: (skip) * */ void regress_foo_test_varargs_callback (gint i G_GNUC_UNUSED, RegressFooVarargsCallback callback G_GNUC_UNUSED) { } /** * regress_foo_test_varargs_callback2: (skip) * */ void regress_foo_test_varargs_callback2 (RegressFooVarargsCallback callback G_GNUC_UNUSED) { } /** * regress_foo_test_varargs_callback3: (skip) * */ void regress_foo_test_varargs_callback3 (RegressFooVarargsCallback callback G_GNUC_UNUSED, RegressFooVarargsCallback callback2 G_GNUC_UNUSED) { } /** * regress_foo_object_a_global_method: * @obj: a #UtilityObject * * This shouldn't be scanned as a method of UtilityObject. */ void regress_foo_object_a_global_method (UtilityObject *obj G_GNUC_UNUSED) { } /** * regress_foo_object_append_new_stack_layer: * * This shouldn't be scanned as a constructor. * * Returns: (transfer none): */ RegressFooOtherObject * regress_foo_object_append_new_stack_layer (RegressFooObject *obj G_GNUC_UNUSED, int x G_GNUC_UNUSED) { return NULL; } /** * regress_foo_not_a_constructor_new: * * This should be scanned as a top-level function, and shouldn't cause * a "Can't find matching type for constructor" warning. * * Returns: (transfer none): */ RegressFooObject * regress_foo_not_a_constructor_new (void) { return NULL; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/foo.h0000664000000000000000000003732315056773103023327 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2007-2010 Johan Dahlin SPDX-FileCopyrightText: 2008-2010 Colin Walters SPDX-FileCopyrightText: 2008-2009, 2011-2012 Dan Winship SPDX-FileCopyrightText: 2008 Jürg Billeter SPDX-FileCopyrightText: 2008 Lucas Rocha SPDX-FileCopyrightText: 2008 Marc-Andre Lureau SPDX-FileCopyrightText: 2008 Philip Van Hoof SPDX-FileCopyrightText: 2008 Tommi Komulainen SPDX-FileCopyrightText: 2009 Andreas Rottmann SPDX-FileCopyrightText: 2009 Robert Carr SPDX-FileCopyrightText: 2010 Collabora, Ltd. SPDX-FileCopyrightText: 2010 litl, LLC SPDX-FileCopyrightText: 2010 Sugar Labs SPDX-FileCopyrightText: 2011 Red Hat, Inc. SPDX-FileCopyrightText: 2011 Torsten Schönfeld SPDX-FileCopyrightText: 2018 Philip Chimento SPDX-FileCopyrightText: 2018 Tomasz MiÄ…sko SPDX-FileCopyrightText: 2024 Simon McVittie */ #pragma once #include #include /* off_t, time_t */ #include /* GAsyncReadyCallback */ #include #include #include "gitestmacros.h" #include "utility.h" #define REGRESS_FOO_SUCCESS_INT 0x1138 #define REGRESS_FOO_DEFINE_SHOULD_BE_EXPOSED "should be exposed" #define REGRESS_FOO_PIE_IS_TASTY 3.14159 #define REGRESS_FOO_TYPE_INTERFACE (regress_foo_interface_get_type ()) #define REGRESS_FOO_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_FOO_TYPE_INTERFACE, RegressFooInterface)) #define REGRESS_FOO_IS_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_FOO_TYPE_INTERFACE)) #define REGRESS_FOO_INTERFACE_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), REGRESS_FOO_TYPE_INTERFACE, RegressFooInterfaceIface)) #define REGRESS_FOO_TYPE_SUBINTERFACE (regress_foo_sub_interface_get_type ()) #define REGRESS_FOO_SUBINTERFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_FOO_TYPE_SUBINTERFACE, RegressFooSubInterface)) #define REGRESS_FOO_IS_SUBINTERFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_FOO_TYPE_SUBINTERFACE)) #define REGRESS_FOO_SUBINTERFACE_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), REGRESS_FOO_TYPE_SUBINTERFACE, RegressFooSubInterfaceIface)) #define REGRESS_FOO_TYPE_OBJECT (regress_foo_object_get_type ()) #define REGRESS_FOO_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_FOO_TYPE_OBJECT, RegressFooObject)) #define REGRESS_FOO_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_FOO_TYPE_OBJECT)) #define REGRESS_FOO_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), REGRESS_FOO_TYPE_OBJECT)) #define REGRESS_FOO_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), REGRESS_FOO_TYPE_OBJECT, RegressFooObjectClass)) #define REGRESS_FOO_TYPE_SUBOBJECT (regress_foo_subobject_get_type ()) #define REGRESS_FOO_SUBOBJECT(subobject) (G_TYPE_CHECK_INSTANCE_CAST ((subobject), REGRESS_FOO_TYPE_SUBOBJECT, RegressFooSubobject)) #define REGRESS_FOO_IS_SUBOBJECT(subobject) (G_TYPE_CHECK_INSTANCE_TYPE ((subobject), REGRESS_FOO_TYPE_SUBOBJECT)) #define REGRESS_FOO_TYPE_BUFFER (regress_foo_buffer_get_type ()) #define REGRESS_FOO_BUFFER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_FOO_TYPE_BUFFER, RegressFooBuffer)) #define REGRESS_FOO_IS_BUFFER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_FOO_TYPE_BUFFER)) #define REGRESS_FOO_TYPE_OTHER_OBJECT (regress_foo_other_object_get_type ()) #define REGRESS_FOO_OTHER_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_FOO_TYPE_OTHER_OBJECT, RegressFooOtherObject)) #define REGRESS_FOO_IS_OTHER_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_FOO_TYPE_OTHER_OBJECT)) typedef struct _RegressFooInterface RegressFooInterface; typedef struct _RegressFooInterfaceIface RegressFooInterfaceIface; typedef struct _RegressFooSubInterface RegressFooSubInterface; typedef struct _RegressFooSubInterfaceIface RegressFooSubInterfaceIface; typedef struct _RegressFooObject RegressFooObject; typedef struct _RegressFooObjectClass RegressFooObjectClass; typedef struct _RegressFooSubobject RegressFooSubobject; typedef struct _RegressFooSubobjectClass RegressFooSubobjectClass; typedef struct _RegressFooBuffer RegressFooBuffer; typedef struct _RegressFooBufferClass RegressFooBufferClass; typedef struct _RegressFooOtherObject RegressFooOtherObject; typedef struct _RegressFooOtherObjectClass RegressFooOtherObjectClass; struct _RegressFooInterfaceIface { GTypeInterface parent_iface; void (*do_regress_foo) (RegressFooInterface *self, int x); }; GI_TEST_EXTERN GType regress_foo_interface_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN void regress_foo_interface_do_regress_foo (RegressFooInterface *iface, int x); GI_TEST_EXTERN void regress_foo_interface_static_method (int x); struct _RegressFooSubInterfaceIface { GTypeInterface parent_iface; /* signals */ void (*destroy_event) (RegressFooSubInterface *self); /* virtual table */ void (*do_bar) (RegressFooSubInterface *self); void (*do_baz) (RegressFooSubInterface *self, GCallback callback, gpointer user_data); }; GI_TEST_EXTERN GType regress_foo_sub_interface_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN void regress_foo_sub_interface_do_bar (RegressFooSubInterface *self); GI_TEST_EXTERN void regress_foo_sub_interface_do_baz (RegressFooSubInterface *self, GCallback callback, gpointer user_data); struct _RegressFooObject { GObject parent_instance; int some_int; }; struct _RegressFooObjectClass { GObjectClass parent_class; gboolean (*virtual_method) (RegressFooObject *object, int first_param); /* Intended to match GFile */ void (*read_fn) (RegressFooObject *object, int offset, int length); /* Test reserved stuff */ GCallback _reserved[4]; }; GI_TEST_EXTERN gint regress_foo_init (void); GI_TEST_EXTERN int regress_foo_init_argv (int argc, char **argv); GI_TEST_EXTERN int regress_foo_init_argv_address (int *argc, char ***argv); GI_TEST_EXTERN GType regress_foo_object_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN RegressFooObject *regress_foo_object_new (void); GI_TEST_EXTERN UtilityObject *regress_foo_object_external_type (RegressFooObject *object); GI_TEST_EXTERN GObject *regress_foo_object_new_as_super (void); GI_TEST_EXTERN void regress_foo_object_various (RegressFooObject *object, void *data, GType some_type); GI_TEST_EXTERN void regress_foo_object_take_all (RegressFooObject *object, int x, ...); typedef gpointer RegressFooObjectCookie; GI_TEST_EXTERN RegressFooObjectCookie regress_foo_object_new_cookie (RegressFooObject *object, const char *target); GI_TEST_EXTERN void regress_foo_object_is_it_time_yet (RegressFooObject *object, time_t time); GI_TEST_EXTERN void regress_foo_object_seek (RegressFooObject *object, off_t offset); GI_TEST_EXTERN const char *regress_foo_object_get_name (RegressFooObject *object); GI_TEST_EXTERN char *regress_foo_object_dup_name (RegressFooObject *object); GI_TEST_EXTERN void regress_foo_object_handle_glyph (RegressFooObject *object, UtilityGlyph glyph); GI_TEST_EXTERN gboolean regress_foo_object_virtual_method (RegressFooObject *object, int first_param); GI_TEST_EXTERN void regress_foo_object_read (RegressFooObject *object, int offset, int length); GI_TEST_EXTERN int regress_foo_object_static_meth (void); GI_TEST_EXTERN void regress_foo_object_skipped_method (RegressFooObject *object); struct _RegressFooSubobject { RegressFooObject parent_instance; }; struct _RegressFooSubobjectClass { RegressFooObjectClass parent_class; }; GI_TEST_EXTERN GType regress_foo_subobject_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN RegressFooObject *regress_foo_object_get_default (void); GI_TEST_EXTERN GType regress_foo_buffer_get_type (void); GI_TEST_EXTERN void regress_foo_buffer_some_method (RegressFooBuffer *buffer); GI_TEST_EXTERN GType regress_foo_other_object_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN RegressFooObject *regress_foo_not_a_constructor_new (void); typedef enum { REGRESS_FOO_ENUM_ALPHA, REGRESS_FOO_ENUM_BETA, REGRESS_FOO_ENUM_DELTA } RegressFooEnumType; GI_TEST_EXTERN GType regress_foo_enum_type_get_type (void); GI_TEST_EXTERN int regress_foo_enum_method (RegressFooEnumType regress_foo_enum); GI_TEST_EXTERN int regress_foo_enum_type_method (RegressFooEnumType regress_foo_enum); GI_TEST_EXTERN RegressFooEnumType regress_foo_enum_type_returnv (int x); typedef enum { REGRESS_FOO_FLAGS_FIRST = 1 << 0, REGRESS_FOO_FLAGS_SECOND = 1 << 1, REGRESS_FOO_FLAGS_THIRD = 1 << 2 } RegressFooFlagsType; #define REGRESS_FOO_FLAGS_SECOND_AND_THIRD (REGRESS_FOO_FLAGS_SECOND | REGRESS_FOO_FLAGS_THIRD) GI_TEST_EXTERN GType regress_foo_flags_type_get_type (void); typedef enum { REGRESS_FOO_ENUM_UN = 1, REGRESS_FOO_ENUM_DEUX = 2, REGRESS_FOO_ENUM_TROIS = 3, REGRESS_FOO_ENUM_NEUF = 9 } RegressFooEnumNoType; typedef enum { REGRESS_FOO_FLAGS_ETT = 1 << 0, REGRESS_FOO_FLAGS_TVA = 1 << 1, REGRESS_FOO_FLAGS_FYRA = 1 << 2 } RegressFooFlagsNoType; typedef enum { REGRESS_FOO_ENUM_FULLNAME_ONE = 1, REGRESS_FOO_ENUM_FULLNAME_TWO, REGRESS_FOO_ENUM_FULLNAME_THREE } RegressFooEnumFullname; typedef enum { REGRESS_FOO_ADDRESS_INVALID, REGRESS_FOO_ADDRESS_IPV4, REGRESS_FOO_ADDRESS_IPV6 } RegressFooAddressType; typedef struct _RegressFooBoxed RegressFooBoxed; GI_TEST_EXTERN GType regress_foo_boxed_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN RegressFooBoxed *regress_foo_boxed_new (void); GI_TEST_EXTERN void regress_foo_boxed_method (RegressFooBoxed *boxed); /* This one tests capitalization handling with respect to DBus */ typedef struct _RegressFooDBusData RegressFooDBusData; GI_TEST_EXTERN GType regress_foo_dbus_data_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN void regress_foo_dbus_data_method (RegressFooDBusData *dbusdata); /* FIXME: Scanner does not support this yet GI_TEST_EXTERN const char *REGRESS_FOO_CONSTANT_STR = "regress_foo-constant-str"; GI_TEST_EXTERN const int REGRESS_FOO_CONSTANT_INT = 10; GI_TEST_EXTERN const float REGRESS_FOO_CONSTANT_FLOAT = 10; */ /* Callback */ typedef gboolean (*RegressFooCallback) (RegressFooObject *regress_foo, gboolean b, gpointer data); /* Invalid comments, should be ignored */ /* @ */ /* @: */ typedef struct _RegressFooStruct RegressFooStruct; typedef struct _RegressFooStructPrivate RegressFooStructPrivate; struct _RegressFooStruct { RegressFooStructPrivate *priv; int member; }; typedef struct _RegressFooRectangle RegressFooRectangle; struct _RegressFooRectangle { gint x; gint y; gint width; gint height; }; GI_TEST_EXTERN void regress_foo_method_external_references (UtilityObject *object, UtilityEnumType e, UtilityFlagType f, UtilityStruct s); GI_TEST_EXTERN void regress_foo_rectangle_add (RegressFooRectangle *r1, const RegressFooRectangle *r2); GI_TEST_EXTERN RegressFooRectangle *regress_foo_rectangle_new (int x, int y, int width, int height); typedef struct _RegressFooEventAny RegressFooEventAny; typedef struct _RegressFooEventExpose RegressFooEventExpose; typedef union _RegressFooEvent RegressFooEvent; struct _RegressFooEventAny { gint8 send_event; }; struct _RegressFooEventExpose { gint8 send_event; gint count; }; union _RegressFooEvent { int type; RegressFooEventAny any; RegressFooEventExpose expose; }; typedef void RegressFooXEvent; /* And now some boxed variants */ typedef struct _RegressFooBRect RegressFooBRect; struct _RegressFooBRect { double x; double y; }; GI_TEST_EXTERN GType regress_foo_brect_get_type (void); GI_TEST_EXTERN RegressFooBRect *regress_foo_brect_new (double x, double y); GI_TEST_EXTERN void regress_foo_brect_add (RegressFooBRect *b1, RegressFooBRect *b2); typedef union _RegressFooBUnion RegressFooBUnion; union _RegressFooBUnion { int type; double v; RegressFooBRect *rect; }; typedef union _RegressFooUnion RegressFooUnion; union _RegressFooUnion { int regress_foo; }; typedef struct _RegressFooUtilityStruct RegressFooUtilityStruct; struct _RegressFooUtilityStruct { UtilityStruct bar; }; typedef struct _RegressFooThingWithArray RegressFooThingWithArray; struct _RegressFooThingWithArray { int x; int y; char lines[80]; guchar *data; }; GI_TEST_EXTERN RegressFooBUnion *regress_foo_bunion_new (void); GI_TEST_EXTERN GType regress_foo_bunion_get_type (void); GI_TEST_EXTERN int regress_foo_bunion_get_contained_type (RegressFooBUnion *bunion); GI_TEST_EXTERN void regress_foo_test_unsigned (unsigned int unsigned_param); GI_TEST_EXTERN void regress_foo_test_unsigned_type (unsigned unsigned_param); GI_TEST_EXTERN void regress_foo_test_string_array (char **array); GI_TEST_EXTERN void regress_foo_test_string_array_with_g (gchar **array); GI_TEST_EXTERN GArray *regress_foo_test_array (void); GI_TEST_EXTERN const char *regress_foo_test_const_char_retval (void); GI_TEST_EXTERN const RegressFooStruct *regress_foo_test_const_struct_retval (void); GI_TEST_EXTERN void regress_foo_test_const_char_param (const char *param); GI_TEST_EXTERN void regress_foo_test_const_struct_param (const RegressFooStruct *param); typedef void (*RegressFooVarargsCallback) (const char *param, ...); GI_TEST_EXTERN void regress_foo_test_varargs_callback (gint i, RegressFooVarargsCallback callback); GI_TEST_EXTERN void regress_foo_test_varargs_callback2 (RegressFooVarargsCallback callback); GI_TEST_EXTERN void regress_foo_test_varargs_callback3 (RegressFooVarargsCallback callback, RegressFooVarargsCallback callback2); /* Make sure callbacks get the right scope by default */ GI_TEST_EXTERN void regress_foo_async_ready_callback (GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GI_TEST_EXTERN void regress_foo_destroy_notify_callback (RegressFooCallback callback, gpointer data, GDestroyNotify destroy); typedef enum { REGRESS_FOO_ERROR_GOOD, REGRESS_FOO_ERROR_BAD, REGRESS_FOO_ERROR_UGLY } RegressFooError; GI_TEST_EXTERN GType regress_foo_error_get_type (void); GI_TEST_EXTERN GQuark regress_foo_error_quark (void); typedef enum { REGRESS_FOO_LAYER_DESKTOP = 0, REGRESS_FOO_LAYER_BOTTOM = 1, REGRESS_FOO_LAYER_NORMAL = 2, REGRESS_FOO_LAYER_TOP = 4, /* Same as DOCK; see EWMH and bug 330717 */ REGRESS_FOO_LAYER_DOCK = 4, REGRESS_FOO_LAYER_FULLSCREEN = 5, REGRESS_FOO_LAYER_FOCUSED_WINDOW = 6, REGRESS_FOO_LAYER_OVERRIDE_REDIRECT = 7, REGRESS_FOO_LAYER_LAST = 8 } RegressFooStackLayer; typedef enum { REGRESS_FOO_SOME_SINGLE_ENUM } RegressFooASingle; /* Should be skipped */ GI_TEST_EXTERN void regress_foo_some_variant (guint x, va_list args); GI_TEST_EXTERN void regress_foo_some_variant_ptr (guint x, va_list *args); /** * RegressFooSkippable: (skip) * @REGRESS_FOO_SKIPPABLE_ONE: a skippable enum value * @REGRESS_FOO_SKIPPABLE_TWO: another skippable enum value * * Some type that is only interesting from C and should not be * exposed to language bindings. */ typedef enum { REGRESS_FOO_SKIPPABLE_ONE, REGRESS_FOO_SKIPPABLE_TWO } RegressFooSkippable; void regress_foo_skip_me (RegressFooSkippable fs); typedef struct _RegressFooForeignStruct RegressFooForeignStruct; struct _RegressFooForeignStruct { int regress_foo; }; GI_TEST_EXTERN RegressFooForeignStruct *regress_foo_foreign_struct_new (void); GI_TEST_EXTERN RegressFooForeignStruct *regress_foo_foreign_struct_copy (RegressFooForeignStruct *original); /* This one should be a global, not a method on UtilityObject since * it's a separate namespace. */ GI_TEST_EXTERN void regress_foo_object_a_global_method (UtilityObject *obj); GI_TEST_EXTERN RegressFooOtherObject *regress_foo_object_append_new_stack_layer (RegressFooObject *obj, int x); ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/gimarshallingtests.c0000664000000000000000000101160115056773103026433 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2010-2012 Collabora, Ltd. SPDX-FileCopyrightText: 2010 Johan Dahlin SPDX-FileCopyrightText: 2010 Sugar Labs SPDX-FileCopyrightText: 2010 Zach Goldberg SPDX-FileCopyrightText: 2011 Alex Eftimie SPDX-FileCopyrightText: 2011-2012 Canonical Ltd. SPDX-FileCopyrightText: 2011-2012 Colin Walters SPDX-FileCopyrightText: 2011 Dan Winship SPDX-FileCopyrightText: 2011-2012 Giovanni Campagna SPDX-FileCopyrightText: 2011 Ignacio Casal Quinteiro SPDX-FileCopyrightText: 2011-2012 Jasper St. Pierre SPDX-FileCopyrightText: 2011 Laszlo Pandy SPDX-FileCopyrightText: 2011 Red Hat, Inc. SPDX-FileCopyrightText: 2012 Bastian Winkler SPDX-FileCopyrightText: 2012 Epitech SPDX-FileCopyrightText: 2012 Gonzalo Odiard SPDX-FileCopyrightText: 2012-2013 Martin Pitt SPDX-FileCopyrightText: 2012-2013 Paolo Borelli SPDX-FileCopyrightText: 2012 Sebastian Pölsterl SPDX-FileCopyrightText: 2013 Simon Feltman SPDX-FileCopyrightText: 2014 Lionel Landwerlin SPDX-FileCopyrightText: 2014 RIFT.io, Inc. SPDX-FileCopyrightText: 2014 SuSE SPDX-FileCopyrightText: 2016 Endless Mobile, Inc. SPDX-FileCopyrightText: 2016-2018, 2023, 2025 Philip Chimento SPDX-FileCopyrightText: 2017 Christoph Reiter SPDX-FileCopyrightText: 2018 Tomasz MiÄ…sko SPDX-FileCopyrightText: 2019 Stéphane Seng SPDX-FileCopyrightText: 2020-2023 Marco Trevisan SPDX-FileCopyrightText: 2020, 2024 Simon McVittie SPDX-FileCopyrightText: 2021 Carlos Garnacho */ #include #include #include "gimarshallingtests.h" /* Unaligned buffer, for testing that language bindings can deal with pointers * allocated at arbitrary 1-byte alignments. */ static guint8 *unaligned_buffer = NULL; static const size_t UNALIGNED_BUFFER_SIZE = 33; /** * gi_marshalling_tests_cleanup_unaligned_buffer: * * It's OK not to call this and just leak the buffer, but if you are running * your tests with AddressSanitizer or valgrind, you should call this after * completing each unaligned buffer test. * * We can't send an unaligned buffer as (transfer full) because g_free() won't * work on it on Windows. */ void gi_marshalling_tests_cleanup_unaligned_buffer (void) { g_aligned_free_sized (unaligned_buffer, 8, UNALIGNED_BUFFER_SIZE); unaligned_buffer = NULL; } static const guint8 * init_unaligned_buffer (void) { if (unaligned_buffer) gi_marshalling_tests_cleanup_unaligned_buffer (); unaligned_buffer = g_aligned_alloc0 (1, UNALIGNED_BUFFER_SIZE, 8); for (size_t ix = 0; ix < UNALIGNED_BUFFER_SIZE; ix++) unaligned_buffer[ix] = (uintptr_t) (unaligned_buffer + ix) & 0x07; return unaligned_buffer + 1; } static void gi_marshalling_tests_boxed_struct_free (GIMarshallingTestsBoxedStruct *v); /* Booleans */ gboolean gi_marshalling_tests_boolean_return_true (void) { return TRUE; } gboolean gi_marshalling_tests_boolean_return_false (void) { return FALSE; } void gi_marshalling_tests_boolean_in_true (gboolean v) { g_assert (v == TRUE); } void gi_marshalling_tests_boolean_in_false (gboolean v) { g_assert (v == FALSE); } /** * gi_marshalling_tests_boolean_out_true: * @v: (out): */ void gi_marshalling_tests_boolean_out_true (gboolean *v) { *v = TRUE; } /** * gi_marshalling_tests_boolean_out_false: * @v: (out): */ void gi_marshalling_tests_boolean_out_false (gboolean *v) { *v = FALSE; } /** * gi_marshalling_tests_boolean_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_boolean_out_uninitialized (gboolean *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_boolean_inout_true_false: * @v: (inout): */ void gi_marshalling_tests_boolean_inout_true_false (gboolean *v) { g_assert (*v == TRUE); *v = FALSE; } /** * gi_marshalling_tests_boolean_inout_false_true: * @v: (inout): */ void gi_marshalling_tests_boolean_inout_false_true (gboolean *v) { g_assert (*v == FALSE); *v = TRUE; } /* Integers */ gint8 gi_marshalling_tests_int8_return_max (void) { return G_MAXINT8; } gint8 gi_marshalling_tests_int8_return_min (void) { return G_MININT8; } void gi_marshalling_tests_int8_in_max (gint8 v) { g_assert_cmpint (v, ==, G_MAXINT8); } void gi_marshalling_tests_int8_in_min (gint8 v) { g_assert_cmpint (v, ==, G_MININT8); } /** * gi_marshalling_tests_int8_out_max: * @v: (out): */ void gi_marshalling_tests_int8_out_max (gint8 *v) { *v = G_MAXINT8; } /** * gi_marshalling_tests_int8_out_min: * @v: (out): */ void gi_marshalling_tests_int8_out_min (gint8 *v) { *v = G_MININT8; } /** * gi_marshalling_tests_int8_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_int8_out_uninitialized (gint8 *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_int8_inout_max_min: * @v: (inout): */ void gi_marshalling_tests_int8_inout_max_min (gint8 *v) { g_assert_cmpint (*v, ==, G_MAXINT8); *v = G_MININT8; } /** * gi_marshalling_tests_int8_inout_min_max: * @v: (inout): */ void gi_marshalling_tests_int8_inout_min_max (gint8 *v) { g_assert_cmpint (*v, ==, G_MININT8); *v = G_MAXINT8; } guint8 gi_marshalling_tests_uint8_return (void) { return G_MAXUINT8; } void gi_marshalling_tests_uint8_in (guint8 v) { g_assert_cmpuint (v, ==, G_MAXUINT8); } /** * gi_marshalling_tests_uint8_out: * @v: (out): */ void gi_marshalling_tests_uint8_out (guint8 *v) { *v = G_MAXUINT8; } /** * gi_marshalling_tests_uint8_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_uint8_out_uninitialized (guint8 *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_uint8_inout: * @v: (inout): */ void gi_marshalling_tests_uint8_inout (guint8 *v) { g_assert_cmpuint (*v, ==, G_MAXUINT8); *v = 0; } gint16 gi_marshalling_tests_int16_return_max (void) { return G_MAXINT16; } gint16 gi_marshalling_tests_int16_return_min (void) { return G_MININT16; } void gi_marshalling_tests_int16_in_max (gint16 v) { g_assert_cmpint (v, ==, G_MAXINT16); } void gi_marshalling_tests_int16_in_min (gint16 v) { g_assert_cmpint (v, ==, G_MININT16); } /** * gi_marshalling_tests_int16_out_max: * @v: (out): */ void gi_marshalling_tests_int16_out_max (gint16 *v) { *v = G_MAXINT16; } /** * gi_marshalling_tests_int16_out_min: * @v: (out): */ void gi_marshalling_tests_int16_out_min (gint16 *v) { *v = G_MININT16; } /** * gi_marshalling_tests_int16_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_int16_out_uninitialized (gint16 *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_int16_inout_max_min: * @v: (inout): */ void gi_marshalling_tests_int16_inout_max_min (gint16 *v) { g_assert_cmpint (*v, ==, G_MAXINT16); *v = G_MININT16; } /** * gi_marshalling_tests_int16_inout_min_max: * @v: (inout): */ void gi_marshalling_tests_int16_inout_min_max (gint16 *v) { g_assert_cmpint (*v, ==, G_MININT16); *v = G_MAXINT16; } guint16 gi_marshalling_tests_uint16_return (void) { return G_MAXUINT16; } void gi_marshalling_tests_uint16_in (guint16 v) { g_assert_cmpuint (v, ==, G_MAXUINT16); } /** * gi_marshalling_tests_uint16_out: * @v: (out): */ void gi_marshalling_tests_uint16_out (guint16 *v) { *v = G_MAXUINT16; } /** * gi_marshalling_tests_uint16_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_uint16_out_uninitialized (guint16 *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_uint16_inout: * @v: (inout): */ void gi_marshalling_tests_uint16_inout (guint16 *v) { g_assert_cmpuint (*v, ==, G_MAXUINT16); *v = 0; } gint32 gi_marshalling_tests_int32_return_max (void) { return G_MAXINT32; } gint32 gi_marshalling_tests_int32_return_min (void) { return G_MININT32; } void gi_marshalling_tests_int32_in_max (gint32 v) { g_assert_cmpint (v, ==, G_MAXINT32); } void gi_marshalling_tests_int32_in_min (gint32 v) { g_assert_cmpint (v, ==, G_MININT32); } /** * gi_marshalling_tests_int32_out_max: * @v: (out): */ void gi_marshalling_tests_int32_out_max (gint32 *v) { *v = G_MAXINT32; } /** * gi_marshalling_tests_int32_out_min: * @v: (out): */ void gi_marshalling_tests_int32_out_min (gint32 *v) { *v = G_MININT32; } /** * gi_marshalling_tests_int32_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_int32_out_uninitialized (gint32 *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_int32_inout_max_min: * @v: (inout): */ void gi_marshalling_tests_int32_inout_max_min (gint32 *v) { g_assert_cmpint (*v, ==, G_MAXINT32); *v = G_MININT32; } /** * gi_marshalling_tests_int32_inout_min_max: * @v: (inout): */ void gi_marshalling_tests_int32_inout_min_max (gint32 *v) { g_assert_cmpint (*v, ==, G_MININT32); *v = G_MAXINT32; } guint32 gi_marshalling_tests_uint32_return (void) { return G_MAXUINT32; } void gi_marshalling_tests_uint32_in (guint32 v) { g_assert_cmpuint (v, ==, G_MAXUINT32); } /** * gi_marshalling_tests_uint32_out: * @v: (out): */ void gi_marshalling_tests_uint32_out (guint32 *v) { *v = G_MAXUINT32; } /** * gi_marshalling_tests_uint32_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_uint32_out_uninitialized (guint32 *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_uint32_inout: * @v: (inout): */ void gi_marshalling_tests_uint32_inout (guint32 *v) { g_assert_cmpuint (*v, ==, G_MAXUINT32); *v = 0; } gint64 gi_marshalling_tests_int64_return_max (void) { return G_MAXINT64; } gint64 gi_marshalling_tests_int64_return_min (void) { return G_MININT64; } void gi_marshalling_tests_int64_in_max (gint64 v) { g_assert_cmpint (v, ==, G_MAXINT64); } void gi_marshalling_tests_int64_in_min (gint64 v) { g_assert_cmpint (v, ==, G_MININT64); } /** * gi_marshalling_tests_int64_out_max: * @v: (out): */ void gi_marshalling_tests_int64_out_max (gint64 *v) { *v = G_MAXINT64; } /** * gi_marshalling_tests_int64_out_min: * @v: (out): */ void gi_marshalling_tests_int64_out_min (gint64 *v) { *v = G_MININT64; } /** * gi_marshalling_tests_int64_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_int64_out_uninitialized (gint64 *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_int64_inout_max_min: * @v: (inout): */ void gi_marshalling_tests_int64_inout_max_min (gint64 *v) { g_assert_cmpint (*v, ==, G_MAXINT64); *v = G_MININT64; } /** * gi_marshalling_tests_int64_inout_min_max: * @v: (inout): */ void gi_marshalling_tests_int64_inout_min_max (gint64 *v) { g_assert_cmpint (*v, ==, G_MININT64); *v = G_MAXINT64; } guint64 gi_marshalling_tests_uint64_return (void) { return G_MAXUINT64; } void gi_marshalling_tests_uint64_in (guint64 v) { g_assert_cmpuint (v, ==, G_MAXUINT64); } /** * gi_marshalling_tests_uint64_out: * @v: (out): */ void gi_marshalling_tests_uint64_out (guint64 *v) { *v = G_MAXUINT64; } /** * gi_marshalling_tests_uint64_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_uint64_out_uninitialized (guint64 *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_uint64_inout: * @v: (inout): */ void gi_marshalling_tests_uint64_inout (guint64 *v) { g_assert_cmpuint (*v, ==, G_MAXUINT64); *v = 0; } gshort gi_marshalling_tests_short_return_max (void) { return G_MAXSHORT; } gshort gi_marshalling_tests_short_return_min (void) { return G_MINSHORT; } void gi_marshalling_tests_short_in_max (gshort short_) { g_assert_cmpint (short_, ==, G_MAXSHORT); } void gi_marshalling_tests_short_in_min (gshort short_) { g_assert_cmpint (short_, ==, G_MINSHORT); } /** * gi_marshalling_tests_short_out_max: * @short_: (out): */ void gi_marshalling_tests_short_out_max (gshort *short_) { *short_ = G_MAXSHORT; } /** * gi_marshalling_tests_short_out_min: * @short_: (out): */ void gi_marshalling_tests_short_out_min (gshort *short_) { *short_ = G_MINSHORT; } /** * gi_marshalling_tests_short_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_short_out_uninitialized (gshort *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_short_inout_max_min: * @short_: (inout): */ void gi_marshalling_tests_short_inout_max_min (gshort *short_) { g_assert_cmpint (*short_, ==, G_MAXSHORT); *short_ = G_MINSHORT; } /** * gi_marshalling_tests_short_inout_min_max: * @short_: (inout): */ void gi_marshalling_tests_short_inout_min_max (gshort *short_) { g_assert_cmpint (*short_, ==, G_MINSHORT); *short_ = G_MAXSHORT; } gushort gi_marshalling_tests_ushort_return (void) { return G_MAXUSHORT; } void gi_marshalling_tests_ushort_in (gushort ushort_) { g_assert_cmpuint (ushort_, ==, G_MAXUSHORT); } /** * gi_marshalling_tests_ushort_out: * @ushort_: (out): */ void gi_marshalling_tests_ushort_out (gushort *ushort_) { *ushort_ = G_MAXUSHORT; } /** * gi_marshalling_tests_ushort_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_ushort_out_uninitialized (gushort *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_ushort_inout: * @ushort_: (inout): */ void gi_marshalling_tests_ushort_inout (gushort *ushort_) { g_assert_cmpuint (*ushort_, ==, G_MAXUSHORT); *ushort_ = 0; } gint gi_marshalling_tests_int_return_max (void) { return G_MAXINT; } gint gi_marshalling_tests_int_return_min (void) { return G_MININT; } void gi_marshalling_tests_int_in_max (gint int_) { g_assert_cmpint (int_, ==, G_MAXINT); } void gi_marshalling_tests_int_in_min (gint int_) { g_assert_cmpint (int_, ==, G_MININT); } /** * gi_marshalling_tests_int_out_max: * @int_: (out): */ void gi_marshalling_tests_int_out_max (gint *int_) { *int_ = G_MAXINT; } /** * gi_marshalling_tests_int_out_min: * @int_: (out): */ void gi_marshalling_tests_int_out_min (gint *int_) { *int_ = G_MININT; } /** * gi_marshalling_tests_int_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_int_out_uninitialized (gint *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_int_inout_max_min: * @int_: (inout): */ void gi_marshalling_tests_int_inout_max_min (gint *int_) { g_assert_cmpint (*int_, ==, G_MAXINT); *int_ = G_MININT; } /** * gi_marshalling_tests_int_inout_min_max: * @int_: (inout): */ void gi_marshalling_tests_int_inout_min_max (gint *int_) { g_assert_cmpint (*int_, ==, G_MININT); *int_ = G_MAXINT; } guint gi_marshalling_tests_uint_return (void) { return G_MAXUINT; } void gi_marshalling_tests_uint_in (guint uint_) { g_assert_cmpuint (uint_, ==, G_MAXUINT); } /** * gi_marshalling_tests_uint_out: * @uint_: (out): */ void gi_marshalling_tests_uint_out (guint *uint_) { *uint_ = G_MAXUINT; } /** * gi_marshalling_tests_uint_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_uint_out_uninitialized (guint *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_uint_inout: * @uint_: (inout): */ void gi_marshalling_tests_uint_inout (guint *uint_) { g_assert_cmpuint (*uint_, ==, G_MAXUINT); *uint_ = 0; } glong gi_marshalling_tests_long_return_max (void) { return G_MAXLONG; } glong gi_marshalling_tests_long_return_min (void) { return G_MINLONG; } void gi_marshalling_tests_long_in_max (glong long_) { g_assert_cmpint (long_, ==, G_MAXLONG); } void gi_marshalling_tests_long_in_min (glong long_) { g_assert_cmpint (long_, ==, G_MINLONG); } /** * gi_marshalling_tests_long_out_max: * @long_: (out): */ void gi_marshalling_tests_long_out_max (glong *long_) { *long_ = G_MAXLONG; } /** * gi_marshalling_tests_long_out_min: * @long_: (out): */ void gi_marshalling_tests_long_out_min (glong *long_) { *long_ = G_MINLONG; } /** * gi_marshalling_tests_long_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_long_out_uninitialized (glong *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_long_inout_max_min: * @long_: (inout): */ void gi_marshalling_tests_long_inout_max_min (glong *long_) { g_assert_cmpint (*long_, ==, G_MAXLONG); *long_ = G_MINLONG; } /** * gi_marshalling_tests_long_inout_min_max: * @long_: (inout): */ void gi_marshalling_tests_long_inout_min_max (glong *long_) { g_assert_cmpint (*long_, ==, G_MINLONG); *long_ = G_MAXLONG; } gulong gi_marshalling_tests_ulong_return (void) { return G_MAXULONG; } void gi_marshalling_tests_ulong_in (gulong ulong_) { g_assert_cmpuint (ulong_, ==, G_MAXULONG); } /** * gi_marshalling_tests_ulong_out: * @ulong_: (out): */ void gi_marshalling_tests_ulong_out (gulong *ulong_) { *ulong_ = G_MAXULONG; } /** * gi_marshalling_tests_ulong_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_ulong_out_uninitialized (gulong *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_ulong_inout: * @ulong_: (inout): */ void gi_marshalling_tests_ulong_inout (gulong *ulong_) { g_assert_cmpuint (*ulong_, ==, G_MAXULONG); *ulong_ = 0; } gssize gi_marshalling_tests_ssize_return_max (void) { return G_MAXSSIZE; } gssize gi_marshalling_tests_ssize_return_min (void) { return G_MINSSIZE; } void gi_marshalling_tests_ssize_in_max (gssize ssize) { g_assert_cmpint (ssize, ==, G_MAXSSIZE); } void gi_marshalling_tests_ssize_in_min (gssize ssize) { g_assert_cmpint (ssize, ==, G_MINSSIZE); } /** * gi_marshalling_tests_ssize_out_max: * @ssize: (out): */ void gi_marshalling_tests_ssize_out_max (gssize *ssize) { *ssize = G_MAXSSIZE; } /** * gi_marshalling_tests_ssize_out_min: * @ssize: (out): */ void gi_marshalling_tests_ssize_out_min (gssize *ssize) { *ssize = G_MINSSIZE; } /** * gi_marshalling_tests_ssize_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_ssize_out_uninitialized (gssize *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_ssize_inout_max_min: * @ssize: (inout): */ void gi_marshalling_tests_ssize_inout_max_min (gssize *ssize) { g_assert_cmpint (*ssize, ==, G_MAXSSIZE); *ssize = G_MINSSIZE; } /** * gi_marshalling_tests_ssize_inout_min_max: * @ssize: (inout): */ void gi_marshalling_tests_ssize_inout_min_max (gssize *ssize) { g_assert_cmpint (*ssize, ==, G_MINSSIZE); *ssize = G_MAXSSIZE; } gsize gi_marshalling_tests_size_return (void) { return G_MAXSIZE; } void gi_marshalling_tests_size_in (gsize size) { g_assert_cmpuint (size, ==, G_MAXSIZE); } /** * gi_marshalling_tests_size_out: * @size: (out): */ void gi_marshalling_tests_size_out (gsize *size) { *size = G_MAXSIZE; } /** * gi_marshalling_tests_size_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_size_out_uninitialized (gsize *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_size_inout: * @size: (inout): */ void gi_marshalling_tests_size_inout (gsize *size) { g_assert_cmpuint (*size, ==, G_MAXSIZE); *size = 0; } gfloat gi_marshalling_tests_float_return (void) { return G_MAXFLOAT; } void gi_marshalling_tests_float_in (gfloat v) { g_assert_cmpfloat (v, ==, G_MAXFLOAT); } /** * gi_marshalling_tests_float_out: * @v: (out): */ void gi_marshalling_tests_float_out (gfloat *v) { *v = G_MAXFLOAT; } #define NONCANONICAL_NAN_BIT_PATTERN_32 0xfffb1236; #define NONCANONICAL_NAN_BIT_PATTERN_64 0xfffb1236fedcba98; static gfloat noncanonical_nan_float (void) { gfloat retval; if (sizeof (gfloat) == sizeof (guint32)) { guint32 bit_pattern = NONCANONICAL_NAN_BIT_PATTERN_32; memcpy (&retval, &bit_pattern, sizeof (gfloat)); } else { g_assert (sizeof (gfloat) == sizeof (guint64) && "gfloat must be 32 or 64 bits"); guint64 bit_pattern = NONCANONICAL_NAN_BIT_PATTERN_64; memcpy (&retval, &bit_pattern, sizeof (gfloat)); } return retval; } /** * gi_marshalling_tests_float_noncanonical_nan_out: * @v: (out): */ void gi_marshalling_tests_float_noncanonical_nan_out (gfloat *v) { *v = noncanonical_nan_float (); } /** * gi_marshalling_tests_float_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_float_out_uninitialized (gfloat *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_float_inout: * @v: (inout): */ void gi_marshalling_tests_float_inout (gfloat *v) { g_assert_cmpfloat (*v, ==, G_MAXFLOAT); *v = G_MINFLOAT; } gdouble gi_marshalling_tests_double_return (void) { return G_MAXDOUBLE; } void gi_marshalling_tests_double_in (gdouble v) { g_assert_cmpfloat (v, ==, G_MAXDOUBLE); } /** * gi_marshalling_tests_double_out: * @v: (out): */ void gi_marshalling_tests_double_out (gdouble *v) { *v = G_MAXDOUBLE; } static gdouble noncanonical_nan_double (void) { gdouble retval; g_assert (sizeof (gdouble) == sizeof (guint64) && "gdouble must be 64 bits"); guint64 bit_pattern = NONCANONICAL_NAN_BIT_PATTERN_64; memcpy (&retval, &bit_pattern, sizeof (gdouble)); return retval; } /** * gi_marshalling_tests_double_noncanonical_nan_out: * @v: (out): */ void gi_marshalling_tests_double_noncanonical_nan_out (gdouble *v) { *v = noncanonical_nan_double (); } /** * gi_marshalling_tests_double_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_double_out_uninitialized (gdouble *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_double_inout: * @v: (inout): */ void gi_marshalling_tests_double_inout (gdouble *v) { g_assert_cmpfloat (*v, ==, G_MAXDOUBLE); *v = G_MINDOUBLE; } time_t gi_marshalling_tests_time_t_return (void) { return 1234567890; } void gi_marshalling_tests_time_t_in (time_t v) { g_assert_cmpuint (v, ==, 1234567890); } /** * gi_marshalling_tests_time_t_out: * @v: (out): */ void gi_marshalling_tests_time_t_out (time_t *v) { *v = 1234567890; } /** * gi_marshalling_tests_time_t_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_time_t_out_uninitialized (time_t *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_time_t_inout: * @v: (inout): */ void gi_marshalling_tests_time_t_inout (time_t *v) { g_assert_cmpuint (*v, ==, 1234567890); *v = 0; } off_t gi_marshalling_tests_off_t_return (void) { return 1234567890; } void gi_marshalling_tests_off_t_in (off_t v) { g_assert_cmpuint (v, ==, 1234567890); } /** * gi_marshalling_tests_off_t_out: * @v: (out): */ void gi_marshalling_tests_off_t_out (off_t *v) { *v = 1234567890; } /** * gi_marshalling_tests_off_t_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_off_t_out_uninitialized (off_t *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_off_t_inout: * @v: (inout): */ void gi_marshalling_tests_off_t_inout (off_t *v) { g_assert_cmpuint (*v, ==, 1234567890); *v = 0; } #ifdef G_OS_UNIX dev_t gi_marshalling_tests_dev_t_return (void) { return 1234567890; } void gi_marshalling_tests_dev_t_in (dev_t v) { g_assert_cmpuint (v, ==, 1234567890); } /** * gi_marshalling_tests_dev_t_out: * @v: (out): */ void gi_marshalling_tests_dev_t_out (dev_t *v) { *v = 1234567890; } /** * gi_marshalling_tests_dev_t_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_dev_t_out_uninitialized (dev_t *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_dev_t_inout: * @v: (inout): */ void gi_marshalling_tests_dev_t_inout (dev_t *v) { g_assert_cmpuint (*v, ==, 1234567890); *v = 0; } gid_t gi_marshalling_tests_gid_t_return (void) { return 65534; } void gi_marshalling_tests_gid_t_in (gid_t v) { g_assert_cmpuint (v, ==, 65534); } /** * gi_marshalling_tests_gid_t_out: * @v: (out): */ void gi_marshalling_tests_gid_t_out (gid_t *v) { *v = 65534; } /** * gi_marshalling_tests_gid_t_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_gid_t_out_uninitialized (gid_t *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gid_t_inout: * @v: (inout): */ void gi_marshalling_tests_gid_t_inout (gid_t *v) { g_assert_cmpuint (*v, ==, 65534); *v = 0; } pid_t gi_marshalling_tests_pid_t_return (void) { return 12345; } void gi_marshalling_tests_pid_t_in (pid_t v) { g_assert_cmpuint (v, ==, 12345); } /** * gi_marshalling_tests_pid_t_out: * @v: (out): */ void gi_marshalling_tests_pid_t_out (pid_t *v) { *v = 12345; } /** * gi_marshalling_tests_pid_t_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_pid_t_out_uninitialized (pid_t *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_pid_t_inout: * @v: (inout): */ void gi_marshalling_tests_pid_t_inout (pid_t *v) { g_assert_cmpuint (*v, ==, 12345); *v = 0; } socklen_t gi_marshalling_tests_socklen_t_return (void) { return 123; } void gi_marshalling_tests_socklen_t_in (socklen_t v) { g_assert_cmpuint (v, ==, 123); } /** * gi_marshalling_tests_socklen_t_out: * @v: (out): */ void gi_marshalling_tests_socklen_t_out (socklen_t *v) { *v = 123; } /** * gi_marshalling_tests_socklen_t_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_socklen_t_out_uninitialized (socklen_t *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_socklen_t_inout: * @v: (inout): */ void gi_marshalling_tests_socklen_t_inout (socklen_t *v) { g_assert_cmpuint (*v, ==, 123); *v = 0; } uid_t gi_marshalling_tests_uid_t_return (void) { return 65534; } void gi_marshalling_tests_uid_t_in (uid_t v) { g_assert_cmpuint (v, ==, 65534); } /** * gi_marshalling_tests_uid_t_out: * @v: (out): */ void gi_marshalling_tests_uid_t_out (uid_t *v) { *v = 65534; } /** * gi_marshalling_tests_uid_t_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_uid_t_out_uninitialized (uid_t *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_uid_t_inout: * @v: (inout): */ void gi_marshalling_tests_uid_t_inout (uid_t *v) { g_assert_cmpuint (*v, ==, 65534); *v = 0; } #endif /* G_OS_UNIX */ GType gi_marshalling_tests_gtype_return (void) { return G_TYPE_NONE; } GType gi_marshalling_tests_gtype_string_return (void) { return G_TYPE_STRING; } void gi_marshalling_tests_gtype_in (GType gtype) { g_assert (gtype == G_TYPE_NONE); } void gi_marshalling_tests_gtype_string_in (GType gtype) { g_assert (gtype == G_TYPE_STRING); } /** * gi_marshalling_tests_gtype_out: * @gtype: (out): */ void gi_marshalling_tests_gtype_out (GType *gtype) { *gtype = G_TYPE_NONE; } /** * gi_marshalling_tests_gtype_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_gtype_out_uninitialized (GType *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gtype_string_out: * @gtype: (out): */ void gi_marshalling_tests_gtype_string_out (GType *gtype) { *gtype = G_TYPE_STRING; } /** * gi_marshalling_tests_gtype_inout: * @gtype: (inout): */ void gi_marshalling_tests_gtype_inout (GType *gtype) { g_assert (*gtype == G_TYPE_NONE); *gtype = G_TYPE_INT; } const gchar * gi_marshalling_tests_utf8_none_return (void) { return GI_MARSHALLING_TESTS_CONSTANT_UTF8; } gchar * gi_marshalling_tests_utf8_full_return (void) { return g_strdup (GI_MARSHALLING_TESTS_CONSTANT_UTF8); } void gi_marshalling_tests_utf8_none_in (const gchar *utf8) { g_assert_cmpstr (GI_MARSHALLING_TESTS_CONSTANT_UTF8, ==, utf8); } /** * gi_marshalling_tests_utf8_full_in: * @utf8: (transfer full): */ void gi_marshalling_tests_utf8_full_in (gchar *utf8) { g_assert_cmpstr (GI_MARSHALLING_TESTS_CONSTANT_UTF8, ==, utf8); g_free (utf8); } /** * gi_marshalling_tests_utf8_as_uint8array_in: * @array: (array length=len) (element-type guint8): Byte data that happens to be UTF-8 * @len: Length * * Takes data that happens to be UTF-8 as a byte array, to test * binding conversion from their string type (e.g. JavaScript's * UTF-16) to UTF-8. */ void gi_marshalling_tests_utf8_as_uint8array_in (const guint8 *array, gsize len) { gsize orig_len = strlen (GI_MARSHALLING_TESTS_CONSTANT_UTF8); g_assert_cmpint (orig_len, ==, len); g_assert (memcmp (GI_MARSHALLING_TESTS_CONSTANT_UTF8, array, len) == 0); } /** * gi_marshalling_tests_utf8_none_out: * @utf8: (out) (transfer none): */ void gi_marshalling_tests_utf8_none_out (const gchar **utf8) { *utf8 = GI_MARSHALLING_TESTS_CONSTANT_UTF8; } /** * gi_marshalling_tests_utf8_none_out_uninitialized: * @v: (out) (transfer none): */ gboolean gi_marshalling_tests_utf8_none_out_uninitialized (const gchar **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_utf8_full_out: * @utf8: (out) (transfer full): */ void gi_marshalling_tests_utf8_full_out (gchar **utf8) { *utf8 = g_strdup (GI_MARSHALLING_TESTS_CONSTANT_UTF8); } /** * gi_marshalling_tests_utf8_dangling_out: * @utf8: (out) (transfer full): */ void gi_marshalling_tests_utf8_dangling_out (gchar **utf8 G_GNUC_UNUSED) { /* Intentionally don't touch the pointer to see how the bindings handle this case. Bindings should be robust against broken C functions and can initialize even OUT vlues to NULL. */ } /** * gi_marshalling_tests_utf8_none_inout: * @utf8: (inout) (transfer none): */ void gi_marshalling_tests_utf8_none_inout (const gchar **utf8) { g_assert_cmpstr (GI_MARSHALLING_TESTS_CONSTANT_UTF8, ==, *utf8); *utf8 = ""; } /** * gi_marshalling_tests_utf8_full_inout: * @utf8: (inout) (transfer full): */ void gi_marshalling_tests_utf8_full_inout (gchar **utf8) { g_assert_cmpstr (GI_MARSHALLING_TESTS_CONSTANT_UTF8, ==, *utf8); g_free (*utf8); *utf8 = g_strdup (""); } /** * gi_marshalling_tests_init_function: * @n_args: (inout) (allow-none): number of args * @argv: (inout) (array length=n_args) (allow-none): args * * This is like gtk_init(). */ gboolean gi_marshalling_tests_init_function (gint *n_args, char ***argv) { if (n_args == NULL) return TRUE; if (*n_args == 0) return TRUE; (*n_args)--; g_assert (argv != NULL); /* we have transfer ownership full, so we need to free the element ourself */ g_free ((*argv)[*n_args]); (*argv)[*n_args] = NULL; return TRUE; } /** * gi_marshalling_tests_array_fixed_int_return: * * Returns: (array fixed-size=4): */ const gint * gi_marshalling_tests_array_fixed_int_return (void) { static gint ints[] = { -1, 0, 1, 2 }; return ints; } /** * gi_marshalling_tests_array_fixed_short_return: * * Returns: (array fixed-size=4): */ const gshort * gi_marshalling_tests_array_fixed_short_return (void) { static gshort shorts[] = { -1, 0, 1, 2 }; return shorts; } /** * gi_marshalling_tests_array_fixed_return_unaligned: * * Note that the buffer will leak unless you call * gi_marshalling_tests_cleanup_unaligned_buffer(). * * Returns: (array fixed-size=32) (transfer none): */ const guint8 * gi_marshalling_tests_array_fixed_return_unaligned (void) { return init_unaligned_buffer (); } /** * gi_marshalling_tests_array_fixed_int_in: * @ints: (array fixed-size=4): */ void gi_marshalling_tests_array_fixed_int_in (const gint *ints) { g_assert_cmpint (ints[0], ==, -1); g_assert_cmpint (ints[1], ==, 0); g_assert_cmpint (ints[2], ==, 1); g_assert_cmpint (ints[3], ==, 2); } /** * gi_marshalling_tests_array_fixed_caller_allocated_out: * @ints: (out caller-allocates) (array fixed-size=4): */ void gi_marshalling_tests_array_fixed_caller_allocated_out (gint *ints) { ints[0] = -1; ints[1] = 0; ints[2] = 1; ints[3] = 2; } /** * gi_marshalling_tests_array_fixed_short_in: * @shorts: (array fixed-size=4): */ void gi_marshalling_tests_array_fixed_short_in (const gshort *shorts) { g_assert_cmpint (shorts[0], ==, -1); g_assert_cmpint (shorts[1], ==, 0); g_assert_cmpint (shorts[2], ==, 1); g_assert_cmpint (shorts[3], ==, 2); } /** * gi_marshalling_tests_array_fixed_out: * @ints: (out) (array fixed-size=4) (transfer none): */ void gi_marshalling_tests_array_fixed_out (gint **ints) { static gint values[] = { -1, 0, 1, 2 }; *ints = values; } /** * gi_marshalling_tests_array_fixed_out_uninitialized: * @v: (out) (array fixed-size=4) (transfer none): */ gboolean gi_marshalling_tests_array_fixed_out_uninitialized (gint **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_array_fixed_out_unaligned: * @v: (out) (array fixed-size=32) (transfer none): * * Note that the buffer will leak unless you call * gi_marshalling_tests_cleanup_unaligned_buffer(). */ void gi_marshalling_tests_array_fixed_out_unaligned (const guint8 **v) { *v = init_unaligned_buffer (); } /** * gi_marshalling_tests_array_fixed_out_struct: * @structs: (out) (array fixed-size=2) (transfer none): */ void gi_marshalling_tests_array_fixed_out_struct (GIMarshallingTestsSimpleStruct **structs) { static GIMarshallingTestsSimpleStruct *values; if (values == NULL) { values = g_new (GIMarshallingTestsSimpleStruct, 2); values[0].long_ = 7; values[0].int8 = 6; values[1].long_ = 6; values[1].int8 = 7; } *structs = values; } /** * gi_marshalling_tests_array_fixed_out_struct_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_array_fixed_out_struct_uninitialized (GIMarshallingTestsSimpleStruct **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_array_fixed_caller_allocated_struct_out: * @structs: (out caller-allocates) (array fixed-size=4): */ void gi_marshalling_tests_array_fixed_caller_allocated_struct_out (GIMarshallingTestsSimpleStruct *structs) { structs[0].long_ = -2; structs[0].int8 = -1; structs[1].long_ = 1; structs[1].int8 = 2; structs[2].long_ = 3; structs[2].int8 = 4; structs[3].long_ = 5; structs[3].int8 = 6; } /** * gi_marshalling_tests_array_fixed_inout: * @ints: (inout) (array fixed-size=4) (transfer none): */ void gi_marshalling_tests_array_fixed_inout (gint **ints) { static gint values[] = { 2, 1, 0, -1 }; g_assert_cmpint ((*ints)[0], ==, -1); g_assert_cmpint ((*ints)[1], ==, 0); g_assert_cmpint ((*ints)[2], ==, 1); g_assert_cmpint ((*ints)[3], ==, 2); *ints = values; } /** * gi_marshalling_tests_array_return: * * Returns: (array length=length): */ const gint * gi_marshalling_tests_array_return (gint *length) { static gint ints[] = { -1, 0, 1, 2 }; *length = 4; return ints; } /** * gi_marshalling_tests_array_return_etc: * @first: * @length: (out): * @last: * @sum: (out): * * Returns: (array length=length): */ const gint * gi_marshalling_tests_array_return_etc (gint first, gint *length, gint last, gint *sum) { static gint ints[] = { -1, 0, 1, 2 }; ints[0] = first; ints[3] = last; *sum = first + last; *length = 4; return ints; } /** * gi_marshalling_tests_array_return_unaligned: * @len: (out): * * Note that the buffer will leak unless you call * gi_marshalling_tests_cleanup_unaligned_buffer(). * * Returns: (array length=len): */ const guint8 * gi_marshalling_tests_array_return_unaligned (gsize *len) { *len = UNALIGNED_BUFFER_SIZE - 1; return init_unaligned_buffer (); } /** * gi_marshalling_tests_array_in: * @ints: (array length=length): * @length: */ void gi_marshalling_tests_array_in (const gint *ints, gint length) { g_assert_cmpint (length, ==, 4); g_assert_cmpint (ints[0], ==, -1); g_assert_cmpint (ints[1], ==, 0); g_assert_cmpint (ints[2], ==, 1); g_assert_cmpint (ints[3], ==, 2); } /** * gi_marshalling_tests_array_in_len_before: * @length: * @ints: (array length=length): */ void gi_marshalling_tests_array_in_len_before (gint length, const gint *ints) { gi_marshalling_tests_array_in (ints, length); } /** * gi_marshalling_tests_array_in_len_zero_terminated: * @ints: (array length=length zero-terminated): * @length: */ void gi_marshalling_tests_array_in_len_zero_terminated (const gint *ints, gint length) { g_assert_cmpint (length, ==, 4); g_assert_cmpint (ints[0], ==, -1); g_assert_cmpint (ints[1], ==, 0); g_assert_cmpint (ints[2], ==, 1); g_assert_cmpint (ints[3], ==, 2); /* One past the end, null terminator */ g_assert_cmpint (ints[4], ==, 0); } /** * gi_marshalling_tests_array_string_in: * @strings: (array length=length): */ void gi_marshalling_tests_array_string_in (const gchar **strings, gint length) { g_assert_cmpint (length, ==, 2); g_assert_cmpstr (strings[0], ==, "foo"); g_assert_cmpstr (strings[1], ==, "bar"); } /** * gi_marshalling_tests_array_uint8_in: * @chars: (array length=length): */ void gi_marshalling_tests_array_uint8_in (const guint8 *chars, gint length) { g_assert_cmpint (length, ==, 4); g_assert (chars[0] == 'a'); g_assert (chars[1] == 'b'); g_assert (chars[2] == 'c'); g_assert (chars[3] == 'd'); } /** * gi_marshalling_tests_array_int64_in: * @ints: (array length=length): * @length: */ void gi_marshalling_tests_array_int64_in (const gint64 *ints, gint length) { g_assert_cmpint (length, ==, 4); g_assert_cmpint (ints[0], ==, -1); g_assert_cmpint (ints[1], ==, 0); g_assert_cmpint (ints[2], ==, 1); g_assert_cmpint (ints[3], ==, 2); } /** * gi_marshalling_tests_array_uint64_in: * @ints: (array length=length): * @length: */ void gi_marshalling_tests_array_uint64_in (const guint64 *ints, gint length) { g_assert_cmpint (length, ==, 4); g_assert_cmpint (ints[0], ==, -1); g_assert_cmpint (ints[1], ==, 0); g_assert_cmpint (ints[2], ==, 1); g_assert_cmpint (ints[3], ==, 2); } /** * gi_marshalling_tests_array_unichar_in: * @chars: (array length=length): * @length: */ void gi_marshalling_tests_array_unichar_in (const gunichar *chars, gint length) { int ix; static const gunichar expected[] = GI_MARSHALLING_TESTS_CONSTANT_UCS4; g_assert_cmpint (length, ==, 12); for (ix = 0; ix < length; ix++) g_assert_cmpuint (chars[ix], ==, expected[ix]); } /** * gi_marshalling_tests_array_bool_in: * @bools: (array length=length): * @length: */ void gi_marshalling_tests_array_bool_in (const gboolean *bools, gint length) { g_assert_cmpint (length, ==, 4); g_assert_cmpint (bools[0], ==, TRUE); g_assert_cmpint (bools[1], ==, FALSE); g_assert_cmpint (bools[2], ==, TRUE); g_assert_cmpint (bools[3], ==, TRUE); } /** * gi_marshalling_tests_array_struct_in: * @structs: (array length=length): */ void gi_marshalling_tests_array_struct_in (GIMarshallingTestsBoxedStruct **structs, gint length) { g_assert_cmpint (length, ==, 3); g_assert_cmpint (structs[0]->long_, ==, 1); g_assert_cmpint (structs[1]->long_, ==, 2); g_assert_cmpint (structs[2]->long_, ==, 3); } /** * gi_marshalling_tests_array_struct_value_in: * @structs: (array length=length): */ void gi_marshalling_tests_array_struct_value_in (GIMarshallingTestsBoxedStruct *structs, gint length) { g_assert_cmpint (length, ==, 3); g_assert_cmpint (structs[0].long_, ==, 1); g_assert_cmpint (structs[1].long_, ==, 2); g_assert_cmpint (structs[2].long_, ==, 3); } /** * gi_marshalling_tests_array_simple_struct_in: * @structs: (array length=length): */ void gi_marshalling_tests_array_simple_struct_in (GIMarshallingTestsSimpleStruct *structs, gint length) { g_assert_cmpint (length, ==, 3); g_assert_cmpint (structs[0].long_, ==, 1); g_assert_cmpint (structs[1].long_, ==, 2); g_assert_cmpint (structs[2].long_, ==, 3); } /** * gi_marshalling_tests_multi_array_key_value_in: * @keys: (array length=length): * @values: (array length=length): */ void gi_marshalling_tests_multi_array_key_value_in (gint length, const gchar **keys, const GValue *values) { g_assert_cmpint (length, ==, 3); g_assert_cmpstr ("one", ==, keys[0]); g_assert_cmpint (g_value_get_int (&values[0]), ==, 1); g_assert_cmpstr ("two", ==, keys[1]); g_assert_cmpint (g_value_get_int (&values[1]), ==, 2); g_assert_cmpstr ("three", ==, keys[2]); g_assert_cmpint (g_value_get_int (&values[2]), ==, 3); } /** * gi_marshalling_tests_array_struct_take_in: * @structs: (array length=length) (transfer full): */ void gi_marshalling_tests_array_struct_take_in (GIMarshallingTestsBoxedStruct **structs, gint length) { gi_marshalling_tests_array_struct_in (structs, length); /* only really useful if run in valgrind actually */ gi_marshalling_tests_boxed_struct_free (structs[0]); gi_marshalling_tests_boxed_struct_free (structs[1]); gi_marshalling_tests_boxed_struct_free (structs[2]); g_free (structs); } /** * gi_marshalling_tests_array_enum_in: * @_enum: (array length=length) (transfer none): * @length: */ void gi_marshalling_tests_array_enum_in (GIMarshallingTestsEnum *v, gint length) { g_assert_cmpint (length, ==, 3); g_assert_cmpint (v[0], ==, GI_MARSHALLING_TESTS_ENUM_VALUE1); g_assert_cmpint (v[1], ==, GI_MARSHALLING_TESTS_ENUM_VALUE2); g_assert_cmpint (v[2], ==, GI_MARSHALLING_TESTS_ENUM_VALUE3); } /** * gi_marshalling_tests_array_flags_in: * @flags: (array length=length) (transfer none): * @length: */ void gi_marshalling_tests_array_flags_in (GIMarshallingTestsFlags *v, gint length) { g_assert_cmpint (length, ==, 3); g_assert_cmpint (v[0], ==, GI_MARSHALLING_TESTS_FLAGS_VALUE1); g_assert_cmpint (v[1], ==, GI_MARSHALLING_TESTS_FLAGS_VALUE2); g_assert_cmpint (v[2], ==, GI_MARSHALLING_TESTS_FLAGS_VALUE3); } /** * gi_marshalling_tests_array_in_guint64_len: * @ints: (array length=length) (transfer none): * @length: */ void gi_marshalling_tests_array_in_guint64_len (const gint *ints, guint64 length) { g_assert_cmpint (length, ==, 4); gi_marshalling_tests_array_in (ints, length); } /** * gi_marshalling_tests_array_in_guint8_len: * @ints: (array length=length) (transfer none): * @length: */ void gi_marshalling_tests_array_in_guint8_len (const gint *ints, guint8 length) { g_assert_cmpint (length, ==, 4); gi_marshalling_tests_array_in (ints, length); } /** * gi_marshalling_tests_array_out: * @ints: (out) (array length=length) (transfer none): */ void gi_marshalling_tests_array_out (gint **ints, gint *length) { static gint values[] = { -1, 0, 1, 2 }; *length = 4; *ints = values; } /** * gi_marshalling_tests_array_out_uninitialized: * @v: (out) (array length=length) (transfer none): * @length: */ gboolean gi_marshalling_tests_array_out_uninitialized (gint **v G_GNUC_UNUSED, gint *length G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_array_out_unaligned: * @v: (out) (array length=len) (transfer none): * @len: * * Note that the buffer will leak unless you call * gi_marshalling_tests_cleanup_unaligned_buffer(). */ void gi_marshalling_tests_array_out_unaligned (const guint8 **v, gsize *len) { *v = init_unaligned_buffer (); *len = UNALIGNED_BUFFER_SIZE - 1; } /** * gi_marshalling_tests_array_out_etc: * @first: * @ints: (out) (array length=length) (transfer none): * @length: (out): * @last: * @sum: (out): */ void gi_marshalling_tests_array_out_etc (gint first, gint **ints, gint *length, gint last, gint *sum) { static gint values[] = { -1, 0, 1, 2 }; values[0] = first; values[3] = last; *sum = first + last; *length = 4; *ints = values; } /** * gi_marshalling_tests_array_bool_out: * @bools: (out) (array length=length) (transfer none): */ void gi_marshalling_tests_array_bool_out (const gboolean **bools, gint *length) { static const gboolean values[] = { TRUE, FALSE, TRUE, TRUE }; *length = 4; *bools = values; } /** * gi_marshalling_tests_array_unichar_out: * @chars: (out) (array length=length) (transfer none): */ void gi_marshalling_tests_array_unichar_out (const gunichar **chars, gint *length) { static const gunichar values[] = GI_MARSHALLING_TESTS_CONSTANT_UCS4; *length = 12; *chars = values; } /** * gi_marshalling_tests_array_inout: * @ints: (inout) (array length=length) (transfer none): * @length: (inout): */ void gi_marshalling_tests_array_inout (gint **ints, gint *length) { static gint values[] = { -2, -1, 0, 1, 2 }; g_assert_cmpint (*length, ==, 4); g_assert_cmpint ((*ints)[0], ==, -1); g_assert_cmpint ((*ints)[1], ==, 0); g_assert_cmpint ((*ints)[2], ==, 1); g_assert_cmpint ((*ints)[3], ==, 2); *length = 5; *ints = values; } /** * gi_marshalling_tests_array_inout_etc: * @first: * @ints: (inout) (array length=length) (transfer none): * @length: (inout): * @last: * @sum: (out): */ void gi_marshalling_tests_array_inout_etc (gint first, gint **ints, gint *length, gint last, gint *sum) { static gint values[] = { -2, -1, 0, 1, 2 }; g_assert_cmpint (*length, ==, 4); g_assert_cmpint ((*ints)[0], ==, -1); g_assert_cmpint ((*ints)[1], ==, 0); g_assert_cmpint ((*ints)[2], ==, 1); g_assert_cmpint ((*ints)[3], ==, 2); values[0] = first; values[4] = last; *sum = first + last; *length = 5; *ints = values; } /** * gi_marshalling_tests_array_in_nonzero_nonlen: * @first: * @chars: (array): */ void gi_marshalling_tests_array_in_nonzero_nonlen (gint first G_GNUC_UNUSED, const guint8 *chars) { g_assert (chars[0] == 'a'); g_assert (chars[1] == 'b'); g_assert (chars[2] == 'c'); g_assert (chars[3] == 'd'); } /** * gi_marshalling_tests_array_zero_terminated_return: * * Returns: (array zero-terminated) (transfer none): */ const gchar ** gi_marshalling_tests_array_zero_terminated_return (void) { static const gchar *values[] = { "0", "1", "2", NULL }; return values; } /** * gi_marshalling_tests_array_zero_terminated_return_null: * * Returns: (array zero-terminated) (transfer none): */ gchar ** gi_marshalling_tests_array_zero_terminated_return_null (void) { return NULL; } /** * gi_marshalling_tests_array_zero_terminated_return_struct: * * Returns: (array zero-terminated) (transfer full): */ GIMarshallingTestsBoxedStruct ** gi_marshalling_tests_array_zero_terminated_return_struct (void) { GIMarshallingTestsBoxedStruct **ret = (GIMarshallingTestsBoxedStruct **) g_new (gpointer, 4); ret[0] = gi_marshalling_tests_boxed_struct_new (); ret[0]->long_ = 42; ret[1] = gi_marshalling_tests_boxed_struct_new (); ret[1]->long_ = 43; ret[2] = gi_marshalling_tests_boxed_struct_new (); ret[2]->long_ = 44; ret[3] = NULL; return ret; } /** * gi_marshalling_tests_array_zero_terminated_return_sequential_struct: * * Returns: (array zero-terminated) (transfer full): */ GIMarshallingTestsBoxedStruct * gi_marshalling_tests_array_zero_terminated_return_sequential_struct (void) { GIMarshallingTestsBoxedStruct *ret = (GIMarshallingTestsBoxedStruct *) g_new0 (GIMarshallingTestsBoxedStruct, 4); ret[0].long_ = 42; ret[1].long_ = 43; ret[2].long_ = 44; return ret; } /** * gi_marshalling_tests_array_zero_terminated_return_unichar: * * Returns: (array zero-terminated) (transfer full): */ gunichar * gi_marshalling_tests_array_zero_terminated_return_unichar (void) { static const gunichar value[] = GI_MARSHALLING_TESTS_CONSTANT_UCS4; gunichar *retval = g_new0 (gunichar, 13); memcpy (retval, value, 12 * sizeof (gunichar)); return retval; } /** * gi_marshalling_tests_array_zero_terminated_return_unaligned: * * Note that the buffer will leak unless you call * gi_marshalling_tests_cleanup_unaligned_buffer(). * * Returns: (array zero-terminated) (transfer none): */ const guint8 * gi_marshalling_tests_array_zero_terminated_return_unaligned (void) { return init_unaligned_buffer (); } /** * gi_marshalling_tests_array_zero_terminated_in: * @utf8s: (array zero-terminated) (transfer none): */ void gi_marshalling_tests_array_zero_terminated_in (gchar **utf8s) { g_assert (g_strv_length (utf8s)); g_assert_cmpstr (utf8s[0], ==, "0"); g_assert_cmpstr (utf8s[1], ==, "1"); g_assert_cmpstr (utf8s[2], ==, "2"); } /** * gi_marshalling_tests_array_zero_terminated_out: * @utf8s: (out) (array zero-terminated) (transfer none): */ void gi_marshalling_tests_array_zero_terminated_out (const gchar ***utf8s) { static const gchar *values[] = { "0", "1", "2", NULL }; *utf8s = values; } /** * gi_marshalling_tests_array_zero_terminated_out_uninitialized: * @v: (out) (array zero-terminated) (transfer none): */ gboolean gi_marshalling_tests_array_zero_terminated_out_uninitialized (const gchar ***v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_array_zero_terminated_out_unaligned: * @v: (out) (array zero-terminated) (transfer none): * * Note that the buffer will leak unless you call * gi_marshalling_tests_cleanup_unaligned_buffer(). */ void gi_marshalling_tests_array_zero_terminated_out_unaligned (const guint8 **v) { *v = init_unaligned_buffer (); } /** * gi_marshalling_tests_array_zero_terminated_inout: * @utf8s: (inout) (array zero-terminated) (transfer none): */ void gi_marshalling_tests_array_zero_terminated_inout (const gchar ***utf8s) { static const gchar *values[] = { "-1", "0", "1", "2", NULL }; g_assert (g_strv_length ((gchar **) (*utf8s))); g_assert_cmpstr ((*utf8s)[0], ==, "0"); g_assert_cmpstr ((*utf8s)[1], ==, "1"); g_assert_cmpstr ((*utf8s)[2], ==, "2"); *utf8s = values; } /** * gi_marshalling_tests_array_gvariant_none_in: * @variants: (array zero-terminated) (transfer none): * * Returns: (array zero-terminated) (transfer none): */ GVariant ** gi_marshalling_tests_array_gvariant_none_in (GVariant **variants) { /* Use a static container to detect if someone tries to free it */ static GVariant *private_container[3] = { NULL, NULL, NULL }; if (private_container[0] == NULL) { private_container[0] = g_variant_new_int32 (27); private_container[1] = g_variant_new_string ("Hello"); } g_assert (variants != NULL); g_assert_cmpint (g_variant_get_int32 (variants[0]), ==, 27); g_assert_cmpstr (g_variant_get_string (variants[1], NULL), ==, "Hello"); g_assert (variants[2] == NULL); return private_container; } /** * gi_marshalling_tests_array_gvariant_container_in: * @variants: (array zero-terminated) (transfer container): * * Returns: (array zero-terminated) (transfer container): */ GVariant ** gi_marshalling_tests_array_gvariant_container_in (GVariant **variants) { GVariant **container; g_assert (variants != NULL); g_assert_cmpint (g_variant_get_int32 (variants[0]), ==, 27); g_assert_cmpstr (g_variant_get_string (variants[1], NULL), ==, "Hello"); g_assert (variants[2] == NULL); container = g_new0 (GVariant *, 3); /* This is a floating reference, so it's fine for transfer container */ container[0] = g_variant_new_int32 (g_variant_get_int32 (variants[0])); container[1] = variants[1]; g_free (variants); return container; } /** * gi_marshalling_tests_array_gvariant_full_in: * @variants: (array zero-terminated) (transfer full): * * Returns: (array zero-terminated) (transfer full): */ GVariant ** gi_marshalling_tests_array_gvariant_full_in (GVariant **variants) { GVariant **container; g_assert (variants != NULL); g_assert_cmpint (g_variant_get_int32 (variants[0]), ==, 27); g_assert_cmpstr (g_variant_get_string (variants[1], NULL), ==, "Hello"); g_assert (variants[2] == NULL); /* To catch different behaviors we reconstruct one variant from scratch, * while taking the refernce of the other. Both approaches are legal with full * transfer in and out */ container = g_new0 (GVariant *, 3); container[0] = g_variant_ref_sink ( g_variant_new_int32 (g_variant_get_int32 (variants[0]))); g_variant_unref (variants[0]); /* In case the variant is floating, we want to transform it into a full * reference, so that's fully owned by the container like if the case * above, otherwise we just steal it since it has already a strong reference. */ container[1] = g_variant_take_ref (variants[1]); g_free (variants); return container; } /* The following tests expect the following arrays: * in: 🅰, β, c, d (the first two characters are U+1F170 and U+03B2) * out/return: a, b, ¢, 🔠 (the last two characters are U+00A2 and U+1F520) * This is intended to test the full capabilities of C arrays of a basic type. * UTF-8 strings and filenames are the only basic types that need to be released * as individual elements, so we test UTF-8 strings. We test ASCII characters, * basic multilingual plane characters, and astral plane characters in both the * in and out arrays. */ #define SQUARED_A "\xf0\x9f\x85\xb0" #define BETA "\xce\xb2" #define CENT "\xc2\xa2" #define ABCD "\xf0\x9f\x94\xa0" /** * gi_marshalling_tests_length_array_utf8_none_return: * * Returns: (array length=out_length) (transfer none): */ const gchar *const * gi_marshalling_tests_length_array_utf8_none_return (size_t *out_length) { static const gchar *array[] = { "a", "b", CENT, ABCD }; *out_length = 4; return array; } /** * gi_marshalling_tests_length_array_utf8_container_return: * * Returns: (array length=out_length) (transfer container): */ const gchar ** gi_marshalling_tests_length_array_utf8_container_return (size_t *out_length) { const gchar **array = g_new0 (const gchar *, 4); array[0] = "a"; array[1] = "b"; array[2] = CENT; array[3] = ABCD; *out_length = 4; return array; } /** * gi_marshalling_tests_length_array_utf8_full_return: * * Returns: (array length=out_length) (transfer full): */ gchar ** gi_marshalling_tests_length_array_utf8_full_return (size_t *out_length) { gchar **array = g_new0 (gchar *, 4); array[0] = g_strdup ("a"); array[1] = g_strdup ("b"); array[2] = g_strdup (CENT); array[3] = g_strdup (ABCD); *out_length = 4; return array; } /** * gi_marshalling_tests_length_array_utf8_none_in: * @array: (array length=length) (transfer none): */ void gi_marshalling_tests_length_array_utf8_none_in (const gchar *const *array, size_t length) { g_assert_cmpint (length, ==, 4); g_assert_cmpstr (array[0], ==, SQUARED_A); g_assert_cmpstr (array[1], ==, BETA); g_assert_cmpstr (array[2], ==, "c"); g_assert_cmpstr (array[3], ==, "d"); } /** * gi_marshalling_tests_length_array_utf8_container_in: * @array: (array length=length) (transfer container): */ void gi_marshalling_tests_length_array_utf8_container_in (const gchar **array, size_t length) { gi_marshalling_tests_length_array_utf8_none_in (array, length); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_length_array_utf8_full_in: * @array: (array length=length) (transfer full): */ void gi_marshalling_tests_length_array_utf8_full_in (gchar **array, size_t length) { gi_marshalling_tests_length_array_utf8_none_in ((const gchar *const *) array, length); g_clear_pointer (&array[0], g_free); g_clear_pointer (&array[1], g_free); g_clear_pointer (&array[2], g_free); g_clear_pointer (&array[3], g_free); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_length_array_utf8_none_out: * @array_out: (array length=out_length) (out) (transfer none): * @out_length: (out): */ void gi_marshalling_tests_length_array_utf8_none_out (const gchar *const **array_out, size_t *out_length) { *array_out = gi_marshalling_tests_length_array_utf8_none_return (out_length); } /** * gi_marshalling_tests_length_array_utf8_container_out: * @array_out: (array length=out_length) (out) (transfer container): */ void gi_marshalling_tests_length_array_utf8_container_out (const gchar ***array_out, size_t *out_length) { *array_out = gi_marshalling_tests_length_array_utf8_container_return (out_length); } /** * gi_marshalling_tests_length_array_utf8_full_out: * @array_out: (array length=out_length) (out) (transfer full): */ void gi_marshalling_tests_length_array_utf8_full_out (gchar ***array_out, size_t *out_length) { *array_out = gi_marshalling_tests_length_array_utf8_full_return (out_length); } /** * gi_marshalling_tests_length_array_utf8_none_inout: * @array_inout: (array length=inout_length) (inout) (transfer none): * @inout_length: (inout): */ void gi_marshalling_tests_length_array_utf8_none_inout (const gchar *const **array_inout, size_t *inout_length) { static const gchar *array_out[] = { "a", "b", CENT, ABCD }; g_assert_nonnull (inout_length); gi_marshalling_tests_length_array_utf8_none_in (*array_inout, *inout_length); *array_inout = array_out; *inout_length = 4; } /** * gi_marshalling_tests_length_array_utf8_container_inout: * @array_inout: (array length=inout_length) (inout) (transfer container): * @inout_length: (inout): */ void gi_marshalling_tests_length_array_utf8_container_inout (const gchar ***array_inout, size_t *inout_length) { const gchar **array_out = g_new0 (const gchar *, 4); g_assert_nonnull (inout_length); g_assert_nonnull (array_inout); gi_marshalling_tests_length_array_utf8_container_in (*array_inout, *inout_length); array_out[0] = "a"; array_out[1] = "b"; array_out[2] = CENT; array_out[3] = ABCD; *array_inout = array_out; *inout_length = 4; } /** * gi_marshalling_tests_length_array_utf8_full_inout: * @array_inout: (array length=inout_length) (inout) (transfer full): * @inout_length: (inout): */ void gi_marshalling_tests_length_array_utf8_full_inout (gchar ***array_inout, size_t *inout_length) { gchar **array_out = g_new0 (gchar *, 4); g_assert_nonnull (inout_length); g_assert_nonnull (array_inout); gi_marshalling_tests_length_array_utf8_full_in ( g_steal_pointer (array_inout), *inout_length); array_out[0] = g_strdup ("a"); array_out[1] = g_strdup ("b"); array_out[2] = g_strdup (CENT); array_out[3] = g_strdup (ABCD); *array_inout = array_out; *inout_length = 4; } /** * gi_marshalling_tests_length_array_utf8_optional_inout: * @inout_length: (inout) (optional): @array_inout's length * @array_inout: (inout) (array length=inout_length) (optional): array ["🅰", "β", "c", "d"] * * See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9524 */ void gi_marshalling_tests_length_array_utf8_optional_inout (int *inout_length, char **array_inout[]) { if (*inout_length > 0) gi_marshalling_tests_length_array_utf8_full_inout (array_inout, (size_t *) inout_length); else { gchar **array_out = g_new0 (gchar *, 2); g_assert_nonnull (inout_length); g_assert_nonnull (array_inout); array_out[0] = g_strdup ("a"); array_out[1] = g_strdup ("b"); *array_inout = array_out; *inout_length = 2; } } /** * gi_marshalling_tests_zero_terminated_array_utf8_none_return: * * Returns: (array zero-terminated) (transfer none): */ const gchar *const * gi_marshalling_tests_zero_terminated_array_utf8_none_return (void) { static const gchar *array[] = { "a", "b", CENT, ABCD, NULL }; return array; } /** * gi_marshalling_tests_zero_terminated_array_utf8_container_return: * * Returns: (array zero-terminated) (transfer container): */ const gchar ** gi_marshalling_tests_zero_terminated_array_utf8_container_return (void) { const gchar **array = g_new0 (const gchar *, 5); array[0] = "a"; array[1] = "b"; array[2] = CENT; array[3] = ABCD; return array; } /** * gi_marshalling_tests_zero_terminated_array_utf8_full_return: * * Returns: (array zero-terminated) (transfer full): */ gchar ** gi_marshalling_tests_zero_terminated_array_utf8_full_return (void) { gchar **array = g_new0 (gchar *, 5); array[0] = g_strdup ("a"); array[1] = g_strdup ("b"); array[2] = g_strdup (CENT); array[3] = g_strdup (ABCD); return array; } /** * gi_marshalling_tests_zero_terminated_array_utf8_none_in: * @array: (array zero-terminated) (transfer none): */ void gi_marshalling_tests_zero_terminated_array_utf8_none_in (const gchar *const *array) { g_assert_cmpstr (array[0], ==, SQUARED_A); g_assert_cmpstr (array[1], ==, BETA); g_assert_cmpstr (array[2], ==, "c"); g_assert_cmpstr (array[3], ==, "d"); g_assert_null (array[4]); } /** * gi_marshalling_tests_zero_terminated_array_utf8_container_in: * @array: (array zero-terminated) (transfer container): */ void gi_marshalling_tests_zero_terminated_array_utf8_container_in (const gchar **array) { gi_marshalling_tests_zero_terminated_array_utf8_none_in (array); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_zero_terminated_array_utf8_full_in: * @array: (array zero-terminated) (transfer full): */ void gi_marshalling_tests_zero_terminated_array_utf8_full_in (gchar **array) { gi_marshalling_tests_zero_terminated_array_utf8_none_in ((const gchar *const *) array); for (size_t i = 0; array && array[i] != NULL; i++) g_clear_pointer (&array[i], g_free); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_zero_terminated_array_utf8_none_out: * @array_out: (array zero-terminated) (out) (transfer none): */ void gi_marshalling_tests_zero_terminated_array_utf8_none_out (const gchar *const **array_out) { *array_out = gi_marshalling_tests_zero_terminated_array_utf8_none_return (); } /** * gi_marshalling_tests_zero_terminated_array_utf8_container_out: * @array_out: (array zero-terminated) (out) (transfer container): */ void gi_marshalling_tests_zero_terminated_array_utf8_container_out (const gchar ***array_out) { *array_out = gi_marshalling_tests_zero_terminated_array_utf8_container_return (); } /** * gi_marshalling_tests_zero_terminated_array_utf8_full_out: * @array_out: (array zero-terminated) (out) (transfer full): */ void gi_marshalling_tests_zero_terminated_array_utf8_full_out (gchar ***array_out) { *array_out = gi_marshalling_tests_zero_terminated_array_utf8_full_return (); } /** * gi_marshalling_tests_zero_terminated_array_utf8_none_inout: * @array_inout: (array zero-terminated) (inout) (transfer none): */ void gi_marshalling_tests_zero_terminated_array_utf8_none_inout (const gchar *const **array_inout) { static const gchar *array_out[] = { "a", "b", CENT, ABCD, NULL }; gi_marshalling_tests_zero_terminated_array_utf8_none_in (*array_inout); *array_inout = array_out; } /** * gi_marshalling_tests_zero_terminated_array_utf8_container_inout: * @array_inout: (array zero-terminated) (inout) (transfer container): */ void gi_marshalling_tests_zero_terminated_array_utf8_container_inout (const gchar ***array_inout) { const gchar **array_out = g_new0 (const gchar *, 5); gi_marshalling_tests_zero_terminated_array_utf8_container_in (*array_inout); array_out[0] = "a"; array_out[1] = "b"; array_out[2] = CENT; array_out[3] = ABCD; *array_inout = array_out; } /** * gi_marshalling_tests_zero_terminated_array_utf8_full_inout: * @array_inout: (array zero-terminated) (inout) (transfer full): */ void gi_marshalling_tests_zero_terminated_array_utf8_full_inout (gchar ***array_inout) { gchar **array_out = g_new0 (gchar *, 5); gi_marshalling_tests_zero_terminated_array_utf8_full_in ( g_steal_pointer (array_inout)); array_out[0] = g_strdup ("a"); array_out[1] = g_strdup ("b"); array_out[2] = g_strdup (CENT); array_out[3] = g_strdup (ABCD); *array_inout = array_out; } /** * gi_marshalling_tests_fixed_array_utf8_none_return: * * Returns: (array fixed-size=4) (transfer none): */ const gchar *const * gi_marshalling_tests_fixed_array_utf8_none_return (void) { static const gchar *array[] = { "a", "b", CENT, ABCD }; return array; } /** * gi_marshalling_tests_fixed_array_utf8_container_return: * * Returns: (array fixed-size=4) (transfer container): */ const gchar ** gi_marshalling_tests_fixed_array_utf8_container_return (void) { const gchar **array = g_new0 (const gchar *, 4); array[0] = "a"; array[1] = "b"; array[2] = CENT; array[3] = ABCD; return array; } /** * gi_marshalling_tests_fixed_array_utf8_full_return: * * Returns: (array fixed-size=4) (transfer full): */ gchar ** gi_marshalling_tests_fixed_array_utf8_full_return (void) { gchar **array = g_new0 (gchar *, 4); array[0] = g_strdup ("a"); array[1] = g_strdup ("b"); array[2] = g_strdup (CENT); array[3] = g_strdup (ABCD); return array; } /** * gi_marshalling_tests_fixed_array_utf8_none_in: * @array: (array fixed-size=4) (transfer none): */ void gi_marshalling_tests_fixed_array_utf8_none_in (const gchar *const *array) { g_assert_cmpstr (array[0], ==, SQUARED_A); g_assert_cmpstr (array[1], ==, BETA); g_assert_cmpstr (array[2], ==, "c"); g_assert_cmpstr (array[3], ==, "d"); } /** * gi_marshalling_tests_fixed_array_utf8_container_in: * @array: (array fixed-size=4) (transfer container): */ void gi_marshalling_tests_fixed_array_utf8_container_in (const gchar **array) { gi_marshalling_tests_fixed_array_utf8_none_in (array); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_fixed_array_utf8_full_in: * @array: (array fixed-size=4) (transfer full): */ void gi_marshalling_tests_fixed_array_utf8_full_in (gchar **array) { gi_marshalling_tests_fixed_array_utf8_none_in ((const gchar *const *) array); g_clear_pointer (&array[0], g_free); g_clear_pointer (&array[1], g_free); g_clear_pointer (&array[2], g_free); g_clear_pointer (&array[3], g_free); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_fixed_array_utf8_none_out: * @array_out: (array fixed-size=4) (out) (transfer none): */ void gi_marshalling_tests_fixed_array_utf8_none_out (const gchar *const **array_out) { *array_out = gi_marshalling_tests_fixed_array_utf8_none_return (); } /** * gi_marshalling_tests_fixed_array_utf8_container_out: * @array_out: (array fixed-size=4) (out) (transfer container): */ void gi_marshalling_tests_fixed_array_utf8_container_out (const gchar ***array_out) { *array_out = gi_marshalling_tests_fixed_array_utf8_container_return (); } /** * gi_marshalling_tests_fixed_array_utf8_full_out: * @array_out: (array fixed-size=4) (out) (transfer full): */ void gi_marshalling_tests_fixed_array_utf8_full_out (gchar ***array_out) { *array_out = gi_marshalling_tests_fixed_array_utf8_full_return (); } /** * gi_marshalling_tests_fixed_array_utf8_none_inout: * @array_inout: (array fixed-size=4) (inout) (transfer none): */ void gi_marshalling_tests_fixed_array_utf8_none_inout (const gchar *const **array_inout) { static const gchar *array_out[] = { "a", "b", CENT, ABCD }; gi_marshalling_tests_fixed_array_utf8_none_in (*array_inout); *array_inout = array_out; } /** * gi_marshalling_tests_fixed_array_utf8_container_inout: * @array_inout: (array fixed-size=4) (inout) (transfer container): */ void gi_marshalling_tests_fixed_array_utf8_container_inout (const gchar ***array_inout) { const gchar **array_out = g_new0 (const gchar *, 4); gi_marshalling_tests_fixed_array_utf8_container_in (*array_inout); array_out[0] = "a"; array_out[1] = "b"; array_out[2] = CENT; array_out[3] = ABCD; *array_inout = array_out; } /** * gi_marshalling_tests_fixed_array_utf8_full_inout: * @array_inout: (array fixed-size=4) (inout) (transfer full): */ void gi_marshalling_tests_fixed_array_utf8_full_inout (gchar ***array_inout) { gchar **array_out = g_new0 (gchar *, 4); gi_marshalling_tests_fixed_array_utf8_full_in ( g_steal_pointer (array_inout)); array_out[0] = g_strdup ("a"); array_out[1] = g_strdup ("b"); array_out[2] = g_strdup (CENT); array_out[3] = g_strdup (ABCD); *array_inout = array_out; } /** * gi_marshalling_tests_garray_int_none_return: * * Returns: (element-type gint) (transfer none): */ GArray * gi_marshalling_tests_garray_int_none_return (void) { static GArray *v = NULL; gint i; if (v == NULL) { v = g_array_new (TRUE, TRUE, sizeof (gint)); for (i = -1; i < 3; i++) g_array_append_val (v, i); } return v; } /** * gi_marshalling_tests_garray_uint64_none_return: * * Returns: (element-type guint64) (transfer none): */ GArray * gi_marshalling_tests_garray_uint64_none_return (void) { static GArray *array = NULL; guint64 i; if (array == NULL) { array = g_array_new (TRUE, TRUE, sizeof (guint64)); i = 0; g_array_append_val (array, i); i = G_MAXUINT64; g_array_append_val (array, i); } return array; } /** * gi_marshalling_tests_garray_utf8_none_return: * * Returns: (element-type utf8) (transfer none): */ GArray * gi_marshalling_tests_garray_utf8_none_return (void) { static GArray *array = NULL; static const gchar *values[] = { "0", "1", "2", NULL }; gint i; if (array == NULL) { array = g_array_new (TRUE, TRUE, sizeof (gchar *)); for (i = 0; values[i]; i++) g_array_append_val (array, values[i]); } return array; } /** * gi_marshalling_tests_garray_utf8_container_return: * * Returns: (element-type utf8) (transfer container): */ GArray * gi_marshalling_tests_garray_utf8_container_return (void) { GArray *array = NULL; static const gchar *values[] = { "0", "1", "2", NULL }; gint i; array = g_array_new (TRUE, TRUE, sizeof (gchar *)); for (i = 0; values[i]; i++) g_array_append_val (array, values[i]); return array; } /** * gi_marshalling_tests_garray_utf8_full_return: * * Returns: (element-type utf8) (transfer full): */ GArray * gi_marshalling_tests_garray_utf8_full_return (void) { GArray *array = NULL; static const gchar *values[] = { "0", "1", "2", NULL }; gint i; array = g_array_new (TRUE, TRUE, sizeof (gchar *)); for (i = 0; values[i]; i++) { gchar *str = g_strdup (values[i]); g_array_append_val (array, str); } return array; } /** * gi_marshalling_tests_garray_boxed_struct_full_return: * * Returns: (element-type GIMarshallingTestsBoxedStruct) (transfer full): */ GArray * gi_marshalling_tests_garray_boxed_struct_full_return (void) { GArray *array = NULL; static const glong long_values[] = { 42, 43, 44 }; gint i; array = g_array_new (TRUE, TRUE, sizeof (GIMarshallingTestsBoxedStruct)); g_array_set_size (array, 3); for (i = 0; i < 3; i++) { GIMarshallingTestsBoxedStruct *new_struct; new_struct = &g_array_index (array, GIMarshallingTestsBoxedStruct, i); memset (new_struct, 0, sizeof (GIMarshallingTestsSimpleStruct)); new_struct->long_ = long_values[i]; } return array; } /** * gi_marshalling_tests_garray_int_none_in: * @array_: (element-type gint) (transfer none): */ void gi_marshalling_tests_garray_int_none_in (GArray *array_) { g_assert_cmpint (array_->len, ==, 4); g_assert_cmpint (g_array_index (array_, gint, 0), ==, -1); g_assert_cmpint (g_array_index (array_, gint, 1), ==, 0); g_assert_cmpint (g_array_index (array_, gint, 2), ==, 1); g_assert_cmpint (g_array_index (array_, gint, 3), ==, 2); } /** * gi_marshalling_tests_garray_uint64_none_in: * @array_: (element-type guint64) (transfer none): */ void gi_marshalling_tests_garray_uint64_none_in (GArray *array_) { g_assert_cmpint (array_->len, ==, 2); g_assert_cmpint (g_array_index (array_, guint64, 0), ==, 0); g_assert_cmpint (g_array_index (array_, guint64, 1), ==, G_MAXUINT64); } /** * gi_marshalling_tests_garray_utf8_none_in: * @array_: (element-type utf8) (transfer none): */ void gi_marshalling_tests_garray_utf8_none_in (GArray *array_) { g_assert_cmpint (array_->len, ==, 3); g_assert_cmpstr (g_array_index (array_, gchar *, 0), ==, "0"); g_assert_cmpstr (g_array_index (array_, gchar *, 1), ==, "1"); g_assert_cmpstr (g_array_index (array_, gchar *, 2), ==, "2"); } /** * gi_marshalling_tests_garray_utf8_container_in: * @array_: (element-type utf8) (transfer container): */ void gi_marshalling_tests_garray_utf8_container_in (GArray *array_) { gi_marshalling_tests_garray_utf8_none_in (array_); g_array_unref (array_); } /** * gi_marshalling_tests_garray_utf8_full_in: * @array_: (element-type utf8) (transfer full): */ void gi_marshalling_tests_garray_utf8_full_in (GArray *array_) { gi_marshalling_tests_garray_utf8_none_in (array_); for (size_t ix = 0; ix < 3; ix++) g_clear_pointer (&g_array_index (array_, gchar *, ix), g_free); g_array_unref (array_); } /** * gi_marshalling_tests_garray_utf8_none_out: * @array_: (out) (element-type utf8) (transfer none): */ void gi_marshalling_tests_garray_utf8_none_out (GArray **array_) { static GArray *internal = NULL; static const gchar *values[] = { "0", "1", "2", NULL }; gint i; if (internal == NULL) { internal = g_array_new (TRUE, TRUE, sizeof (gchar *)); for (i = 0; values[i]; i++) g_array_append_val (internal, values[i]); } *array_ = internal; } /** * gi_marshalling_tests_garray_utf8_none_out_uninitialized: * @v: (out) (element-type utf8) (transfer none): */ gboolean gi_marshalling_tests_garray_utf8_none_out_uninitialized (GArray **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_garray_utf8_container_out: * @array_: (out) (element-type utf8) (transfer container): */ void gi_marshalling_tests_garray_utf8_container_out (GArray **array_) { static const gchar *values[] = { "0", "1", "2", NULL }; gint i; *array_ = NULL; *array_ = g_array_new (TRUE, TRUE, sizeof (gchar *)); for (i = 0; values[i]; i++) g_array_append_val (*array_, values[i]); } /** * gi_marshalling_tests_garray_utf8_container_out_uninitialized: * @v: (out) (element-type utf8) (transfer container): */ gboolean gi_marshalling_tests_garray_utf8_container_out_uninitialized (GArray **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_garray_utf8_full_out: * @array_: (out) (element-type utf8) (transfer full): */ void gi_marshalling_tests_garray_utf8_full_out (GArray **array_) { static const gchar *values[] = { "0", "1", "2", NULL }; gint i; *array_ = NULL; *array_ = g_array_new (TRUE, TRUE, sizeof (gchar *)); for (i = 0; values[i]; i++) { gchar *str = g_strdup (values[i]); g_array_append_val (*array_, str); } } /** * gi_marshalling_tests_garray_utf8_full_out_uninitialized: * @v: (out) (element-type utf8) (transfer full): */ gboolean gi_marshalling_tests_garray_utf8_full_out_uninitialized (GArray **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_garray_utf8_full_out_caller_allocated: * @array_: (out caller-allocates) (array) (element-type utf8) (transfer full): */ void gi_marshalling_tests_garray_utf8_full_out_caller_allocated (GArray *array_) { static const gchar *values[] = { "0", "1", "2", NULL }; gint i; g_array_set_size (array_, 0); for (i = 0; values[i]; i++) { gchar *str = g_strdup (values[i]); g_array_append_val (array_, str); } } /** * gi_marshalling_tests_garray_utf8_none_inout: * @array_: (inout) (element-type utf8) (transfer none): */ void gi_marshalling_tests_garray_utf8_none_inout (GArray **array_) { static GArray *internal = NULL; static const gchar *values[] = { "-2", "-1", "0", "1", NULL }; gint i; g_assert_cmpint ((*array_)->len, ==, 3); g_assert_cmpstr (g_array_index (*array_, gchar *, 0), ==, "0"); g_assert_cmpstr (g_array_index (*array_, gchar *, 1), ==, "1"); g_assert_cmpstr (g_array_index (*array_, gchar *, 2), ==, "2"); if (internal == NULL) { internal = g_array_new (TRUE, TRUE, sizeof (gchar *)); for (i = 0; values[i]; i++) g_array_append_val (internal, values[i]); } *array_ = internal; } /** * gi_marshalling_tests_garray_utf8_container_inout: * @array_: (inout) (element-type utf8) (transfer container): */ void gi_marshalling_tests_garray_utf8_container_inout (GArray **array_) { static const gchar *val1 = "-2"; static const gchar *val2 = "-1"; static const gchar *val3 = "0"; static const gchar *val4 = "1"; GArray *result; g_assert_cmpint ((*array_)->len, ==, 3); g_assert_cmpstr (g_array_index (*array_, gchar *, 0), ==, "0"); g_assert_cmpstr (g_array_index (*array_, gchar *, 1), ==, "1"); g_assert_cmpstr (g_array_index (*array_, gchar *, 2), ==, "2"); result = g_array_new (TRUE, TRUE, sizeof (gchar *)); g_array_append_val (result, val1); g_array_append_val (result, val2); g_array_append_val (result, val3); g_array_append_val (result, val4); g_array_unref (*array_); *array_ = result; } /** * gi_marshalling_tests_garray_utf8_full_inout: * @array_: (inout) (element-type utf8) (transfer full): */ void gi_marshalling_tests_garray_utf8_full_inout (GArray **array_) { static const gchar *val1 = "-1"; static const gchar *val2 = "-2"; gchar *val; GArray *result; g_assert_cmpint ((*array_)->len, ==, 3); g_assert_cmpstr (g_array_index (*array_, gchar *, 0), ==, "0"); g_assert_cmpstr (g_array_index (*array_, gchar *, 1), ==, "1"); g_assert_cmpstr (g_array_index (*array_, gchar *, 2), ==, "2"); result = g_array_new (TRUE, TRUE, sizeof (gchar *)); val = g_strdup (val2); g_array_append_val (result, val); val = g_strdup (val1); g_array_append_val (result, val); val = g_strdup ("0"); g_array_append_val (result, val); val = g_strdup ("1"); g_array_append_val (result, val); g_array_unref (*array_); *array_ = result; } /** * gi_marshalling_tests_garray_bool_none_in: * @array_: (element-type gboolean) (transfer none): */ void gi_marshalling_tests_garray_bool_none_in (GArray *array_) { g_assert_cmpint (array_->len, ==, 4); g_assert_cmpint (g_array_index (array_, gboolean, 0), ==, TRUE); g_assert_cmpint (g_array_index (array_, gboolean, 1), ==, FALSE); g_assert_cmpint (g_array_index (array_, gboolean, 2), ==, TRUE); g_assert_cmpint (g_array_index (array_, gboolean, 3), ==, TRUE); } /** * gi_marshalling_tests_garray_unichar_none_in: * @array_: (element-type gunichar) (transfer none): */ void gi_marshalling_tests_garray_unichar_none_in (GArray *array_) { unsigned ix; static const gunichar expected[] = GI_MARSHALLING_TESTS_CONSTANT_UCS4; g_assert_cmpint (array_->len, ==, 12); for (ix = 0; ix < array_->len; ix++) g_assert_cmpuint (g_array_index (array_, gunichar, ix), ==, expected[ix]); } /** * gi_marshalling_tests_gptrarray_utf8_none_return: * * Returns: (element-type utf8) (transfer none): */ GPtrArray * gi_marshalling_tests_gptrarray_utf8_none_return (void) { static GPtrArray *parray = NULL; static const gchar *values[] = { "0", "1", "2" }; gint i; if (parray == NULL) { parray = g_ptr_array_new (); for (i = 0; i < 3; i++) g_ptr_array_add (parray, (gpointer) values[i]); } return parray; } /** * gi_marshalling_tests_gptrarray_utf8_container_return: * * Returns: (element-type utf8) (transfer container): */ GPtrArray * gi_marshalling_tests_gptrarray_utf8_container_return (void) { GPtrArray *parray = NULL; static const gchar *values[] = { "0", "1", "2", NULL }; gint i; parray = g_ptr_array_new (); for (i = 0; values[i]; i++) g_ptr_array_add (parray, (gpointer) values[i]); return parray; } /** * gi_marshalling_tests_gptrarray_utf8_full_return: * * Returns: (element-type utf8) (transfer full): */ GPtrArray * gi_marshalling_tests_gptrarray_utf8_full_return (void) { GPtrArray *parray = NULL; static const gchar *values[] = { "0", "1", "2", NULL }; gint i; parray = g_ptr_array_new (); for (i = 0; values[i]; i++) { gchar *str = g_strdup (values[i]); g_ptr_array_add (parray, (gpointer) str); } return parray; } /** * gi_marshalling_tests_gptrarray_boxed_struct_full_return: * * Returns: (element-type GIMarshallingTestsBoxedStruct) (transfer full): */ GPtrArray * gi_marshalling_tests_gptrarray_boxed_struct_full_return (void) { GPtrArray *parray = NULL; static const glong long_values[] = { 42, 43, 44 }; gint i; parray = g_ptr_array_new (); for (i = 0; i < 3; i++) { GIMarshallingTestsBoxedStruct *new_struct = gi_marshalling_tests_boxed_struct_new (); new_struct->long_ = long_values[i]; g_ptr_array_add (parray, (gpointer) new_struct); } return parray; } /** * gi_marshalling_tests_gptrarray_utf8_none_in: * @parray_: (element-type utf8) (transfer none): */ void gi_marshalling_tests_gptrarray_utf8_none_in (GPtrArray *parray_) { g_assert_cmpint (parray_->len, ==, 3); g_assert_cmpstr (g_ptr_array_index (parray_, 0), ==, "0"); g_assert_cmpstr (g_ptr_array_index (parray_, 1), ==, "1"); g_assert_cmpstr (g_ptr_array_index (parray_, 2), ==, "2"); } /** * gi_marshalling_tests_gptrarray_utf8_container_in: * @parray_: (element-type utf8) (transfer container): */ void gi_marshalling_tests_gptrarray_utf8_container_in (GPtrArray *parray_) { gi_marshalling_tests_gptrarray_utf8_none_in (parray_); g_ptr_array_unref (parray_); } /** * gi_marshalling_tests_gptrarray_utf8_full_in: * @parray_: (element-type utf8) (transfer full): */ void gi_marshalling_tests_gptrarray_utf8_full_in (GPtrArray *parray_) { gi_marshalling_tests_gptrarray_utf8_none_in (parray_); for (size_t ix = 0; ix < 3; ix++) g_clear_pointer (&g_ptr_array_index (parray_, ix), g_free); g_ptr_array_unref (parray_); } /** * gi_marshalling_tests_gptrarray_utf8_none_out: * @parray_: (out) (element-type utf8) (transfer none): */ void gi_marshalling_tests_gptrarray_utf8_none_out (GPtrArray **parray_) { static GPtrArray *internal = NULL; static const gchar *values[] = { "0", "1", "2", NULL }; gint i; if (internal == NULL) { internal = g_ptr_array_new (); for (i = 0; values[i]; i++) g_ptr_array_add (internal, (gpointer) values[i]); } *parray_ = internal; } /** * gi_marshalling_tests_gptrarray_utf8_none_out_uninitialized: * @v: (out) (element-type utf8) (transfer none): */ gboolean gi_marshalling_tests_gptrarray_utf8_none_out_uninitialized (GPtrArray **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gptrarray_utf8_container_out: * @parray_: (out) (element-type utf8) (transfer container): */ void gi_marshalling_tests_gptrarray_utf8_container_out (GPtrArray **parray_) { static const gchar *values[] = { "0", "1", "2", NULL }; gint i; *parray_ = NULL; *parray_ = g_ptr_array_new (); for (i = 0; values[i]; i++) g_ptr_array_add (*parray_, (gpointer) values[i]); } /** * gi_marshalling_tests_gptrarray_utf8_container_out_uninitialized: * @v: (out) (element-type utf8) (transfer container): */ gboolean gi_marshalling_tests_gptrarray_utf8_container_out_uninitialized (GPtrArray **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gptrarray_utf8_full_out: * @parray_: (out) (element-type utf8) (transfer full): */ void gi_marshalling_tests_gptrarray_utf8_full_out (GPtrArray **parray_) { static const gchar *values[] = { "0", "1", "2", NULL }; gint i; *parray_ = NULL; *parray_ = g_ptr_array_new (); for (i = 0; values[i]; i++) { gchar *str = g_strdup (values[i]); g_ptr_array_add (*parray_, (gpointer) str); } } /** * gi_marshalling_tests_gptrarray_utf8_full_out_uninitialized: * @v: (out) (element-type utf8) (transfer full): */ gboolean gi_marshalling_tests_gptrarray_utf8_full_out_uninitialized (GPtrArray **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gptrarray_utf8_none_inout: * @parray_: (inout) (element-type utf8) (transfer none): */ void gi_marshalling_tests_gptrarray_utf8_none_inout (GPtrArray **parray_) { static GPtrArray *internal = NULL; static const gchar *values[] = { "-2", "-1", "0", "1", NULL }; gint i; g_assert_cmpint ((*parray_)->len, ==, 3); g_assert_cmpstr (g_ptr_array_index (*parray_, 0), ==, "0"); g_assert_cmpstr (g_ptr_array_index (*parray_, 1), ==, "1"); g_assert_cmpstr (g_ptr_array_index (*parray_, 2), ==, "2"); if (internal == NULL) { internal = g_ptr_array_new (); for (i = 0; values[i]; i++) g_ptr_array_add (internal, (gpointer) values[i]); } *parray_ = internal; } /** * gi_marshalling_tests_gptrarray_utf8_container_inout: * @parray_: (inout) (element-type utf8) (transfer container): */ void gi_marshalling_tests_gptrarray_utf8_container_inout (GPtrArray **parray_) { static const gchar *val1 = "-2"; static const gchar *val2 = "-1"; static const gchar *val3 = "0"; static const gchar *val4 = "1"; GPtrArray *result; g_assert_cmpint ((*parray_)->len, ==, 3); g_assert_cmpstr (g_ptr_array_index (*parray_, 0), ==, "0"); g_assert_cmpstr (g_ptr_array_index (*parray_, 1), ==, "1"); g_assert_cmpstr (g_ptr_array_index (*parray_, 2), ==, "2"); result = g_ptr_array_new (); g_ptr_array_add (result, (gpointer) val1); g_ptr_array_add (result, (gpointer) val2); g_ptr_array_add (result, (gpointer) val3); g_ptr_array_add (result, (gpointer) val4); g_ptr_array_unref (*parray_); *parray_ = result; } /** * gi_marshalling_tests_gptrarray_utf8_full_inout: * @parray_: (inout) (element-type utf8) (transfer full): */ void gi_marshalling_tests_gptrarray_utf8_full_inout (GPtrArray **parray_) { static const gchar *val1 = "-1"; static const gchar *val2 = "-2"; gchar *val; GPtrArray *result; g_assert_cmpint ((*parray_)->len, ==, 3); g_assert_cmpstr (g_ptr_array_index (*parray_, 0), ==, "0"); g_assert_cmpstr (g_ptr_array_index (*parray_, 1), ==, "1"); g_assert_cmpstr (g_ptr_array_index (*parray_, 2), ==, "2"); result = g_ptr_array_new (); val = g_strdup (val2); g_ptr_array_add (result, (gpointer) val); val = g_strdup (val1); g_ptr_array_add (result, (gpointer) val); val = g_strdup ("0"); g_ptr_array_add (result, (gpointer) val); val = g_strdup ("1"); g_ptr_array_add (result, (gpointer) val); g_ptr_array_unref (*parray_); *parray_ = result; } /** * gi_marshalling_tests_bytearray_full_return: * * Returns: (transfer full): */ GByteArray * gi_marshalling_tests_bytearray_full_return (void) { GByteArray *array = NULL; guint8 data[] = { '\0', '1', '\xFF', '3' }; array = g_byte_array_new (); g_byte_array_append (array, (const guint8 *) data, G_N_ELEMENTS (data)); return array; } /** * gi_marshalling_tests_bytearray_none_in: * @v: (element-type gint8) (transfer none): */ void gi_marshalling_tests_bytearray_none_in (GByteArray *v) { g_assert_cmpuint (v->len, ==, 4); g_assert_cmpuint (g_array_index (v, unsigned char, 0), ==, 0); g_assert_cmpuint (g_array_index (v, unsigned char, 1), ==, 49); g_assert_cmpuint (g_array_index (v, unsigned char, 2), ==, 0xFF); g_assert_cmpuint (g_array_index (v, unsigned char, 3), ==, 51); } /** * gi_marshalling_tests_bytearray_full_out: * @v: (out) (transfer full): */ void gi_marshalling_tests_bytearray_full_out (GByteArray **v) { *v = gi_marshalling_tests_bytearray_full_return (); } /** * gi_marshalling_tests_bytearray_full_inout: * @v: (inout) (transfer full): */ void gi_marshalling_tests_bytearray_full_inout (GByteArray **v) { gi_marshalling_tests_bytearray_none_in (*v); g_byte_array_unref (*v); guint8 data[] = { 'h', 'e', 'l', '\0', '\xFF' }; GByteArray *array = g_byte_array_new (); g_byte_array_append (array, (const guint8 *) data, G_N_ELEMENTS (data)); *v = array; } /** * gi_marshalling_tests_gbytes_full_return: * * Returns: (transfer full): */ GBytes * gi_marshalling_tests_gbytes_full_return (void) { static guint8 data[] = { 0, 49, 0xFF, 51 }; return g_bytes_new_static (data, G_N_ELEMENTS (data)); } /** * gi_marshalling_tests_gbytes_none_in: */ void gi_marshalling_tests_gbytes_none_in (GBytes *v) { const guint8 *data; gsize len; data = g_bytes_get_data (v, &len); g_assert_cmpuint (len, ==, 4); g_assert_cmpuint (data[0], ==, 0); g_assert_cmpuint (data[1], ==, 49); g_assert_cmpuint (data[2], ==, 0xFF); g_assert_cmpuint (data[3], ==, 51); } /** * gi_marshalling_tests_gstrv_return: * * Returns: (transfer full): an array of strings */ GStrv gi_marshalling_tests_gstrv_return (void) { GStrv values = g_new0 (gchar *, 4); values[0] = g_strdup ("0"); values[1] = g_strdup ("1"); values[2] = g_strdup ("2"); values[3] = NULL; return values; } /** * gi_marshalling_tests_gstrv_in: * @g_strv: */ void gi_marshalling_tests_gstrv_in (GStrv g_strv) { g_assert_cmpint (g_strv_length (g_strv), ==, 3); g_assert_cmpstr (g_strv[0], ==, "0"); g_assert_cmpstr (g_strv[1], ==, "1"); g_assert_cmpstr (g_strv[2], ==, "2"); } /** * gi_marshalling_tests_gstrv_out: * @g_strv: (out) (transfer none): */ void gi_marshalling_tests_gstrv_out (GStrv *g_strv) { static const gchar *values[] = { "0", "1", "2", NULL }; *g_strv = (gchar **) values; } /** * gi_marshalling_tests_gstrv_out_uninitialized: * @v: (out) (transfer none): */ gboolean gi_marshalling_tests_gstrv_out_uninitialized (GStrv *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gstrv_inout: * @g_strv: (inout) (transfer none): */ void gi_marshalling_tests_gstrv_inout (GStrv *g_strv) { static const gchar *values[] = { "-1", "0", "1", "2", NULL }; g_assert (g_strv_length (*g_strv) == 3); g_assert (strcmp ((*g_strv)[0], "0") == 0); g_assert (strcmp ((*g_strv)[1], "1") == 0); g_assert (strcmp ((*g_strv)[2], "2") == 0); *g_strv = (gchar **) values; } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_full_return: * * Returns: (array length=out_length) (element-type GStrv) (transfer full): */ GStrv * gi_marshalling_tests_length_array_of_gstrv_transfer_full_return (size_t *out_length) { GStrv *array = g_new0 (GStrv, 3); GStrv values; values = g_new0 (gchar *, 4); values[0] = g_strdup ("0"); values[1] = g_strdup ("1"); values[2] = g_strdup ("2"); values[3] = NULL; array[0] = g_steal_pointer (&values); values = g_new0 (gchar *, 4); values[0] = g_strdup ("3"); values[1] = g_strdup ("4"); values[2] = g_strdup ("5"); values[3] = NULL; array[1] = g_steal_pointer (&values); values = g_new0 (gchar *, 4); values[0] = g_strdup ("6"); values[1] = g_strdup ("7"); values[2] = g_strdup ("8"); values[3] = NULL; array[2] = g_steal_pointer (&values); *out_length = 3; return array; } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_container_return: * * Returns: (array length=out_length) (element-type GStrv) (transfer container): */ GStrv * gi_marshalling_tests_length_array_of_gstrv_transfer_container_return (size_t *out_length) { GStrv *array = g_new0 (GStrv, 3); static const gchar *values0[] = { "0", "1", "2", NULL }; static const gchar *values1[] = { "3", "4", "5", NULL }; static const gchar *values2[] = { "6", "7", "8", NULL }; array[0] = (GStrv) values0; array[1] = (GStrv) values1; array[2] = (GStrv) values2; *out_length = 3; return array; } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_none_return: * * Returns: (array length=out_length) (element-type GStrv) (transfer none): */ GStrv * gi_marshalling_tests_length_array_of_gstrv_transfer_none_return (size_t *out_length) { static const gchar *values0[] = { "0", "1", "2", NULL }; static const gchar *values1[] = { "3", "4", "5", NULL }; static const gchar *values2[] = { "6", "7", "8", NULL }; static const gchar **array[] = { values0, values1, values2 }; *out_length = 3; return (GStrv *) array; } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_none_in: * @array: (array length=length) (element-type GStrv) (transfer none): */ void gi_marshalling_tests_length_array_of_gstrv_transfer_none_in (GStrv *array, size_t length) { GStrv g_strv; g_assert_cmpint (length, ==, 3); g_strv = array[0]; g_assert_cmpint (g_strv_length (g_strv), ==, 3); g_assert_cmpstr (g_strv[0], ==, "0"); g_assert_cmpstr (g_strv[1], ==, "1"); g_assert_cmpstr (g_strv[2], ==, "2"); g_strv = array[1]; g_assert_cmpint (g_strv_length (g_strv), ==, 3); g_assert_cmpstr (g_strv[0], ==, "3"); g_assert_cmpstr (g_strv[1], ==, "4"); g_assert_cmpstr (g_strv[2], ==, "5"); g_strv = array[2]; g_assert_cmpint (g_strv_length (g_strv), ==, 3); g_assert_cmpstr (g_strv[0], ==, "6"); g_assert_cmpstr (g_strv[1], ==, "7"); g_assert_cmpstr (g_strv[2], ==, "8"); } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_container_in: * @array: (array length=length) (element-type GStrv) (transfer container): */ void gi_marshalling_tests_length_array_of_gstrv_transfer_container_in (GStrv *array, size_t length) { gi_marshalling_tests_length_array_of_gstrv_transfer_none_in (array, length); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_full_in: * @array: (array length=length) (element-type GStrv) (transfer full): */ void gi_marshalling_tests_length_array_of_gstrv_transfer_full_in (GStrv *array, size_t length) { gi_marshalling_tests_length_array_of_gstrv_transfer_none_in (array, length); g_clear_pointer (&array[0], g_strfreev); g_clear_pointer (&array[1], g_strfreev); g_clear_pointer (&array[2], g_strfreev); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_none_out: * @array_out: (array length=out_length) (out) (element-type GStrv) (transfer none): * @out_length: (out): */ void gi_marshalling_tests_length_array_of_gstrv_transfer_none_out (GStrv **array_out, size_t *out_length) { *array_out = gi_marshalling_tests_length_array_of_gstrv_transfer_none_return (out_length); } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_container_out: * @array_out: (array length=out_length) (out) (element-type GStrv) (transfer container): */ void gi_marshalling_tests_length_array_of_gstrv_transfer_container_out (GStrv **array_out, size_t *out_length) { *array_out = gi_marshalling_tests_length_array_of_gstrv_transfer_container_return (out_length); } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_full_out: * @array_out: (array length=out_length) (out) (element-type GStrv) (transfer full): */ void gi_marshalling_tests_length_array_of_gstrv_transfer_full_out (GStrv **array_out, size_t *out_length) { *array_out = gi_marshalling_tests_length_array_of_gstrv_transfer_full_return (out_length); } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_full_inout: * @array_inout: (array length=inout_length) (inout) (element-type GStrv) (transfer full): * @inout_length: (inout): */ void gi_marshalling_tests_length_array_of_gstrv_transfer_full_inout (GStrv **array_inout, size_t *inout_length) { GStrv *array = g_new0 (GStrv, 4); GStrv values; g_assert_nonnull (inout_length); g_assert_nonnull (array_inout); gi_marshalling_tests_length_array_of_gstrv_transfer_full_in ( g_steal_pointer (array_inout), *inout_length); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("0"); values[2] = g_strdup ("1"); values[3] = g_strdup ("2"); values[4] = NULL; array[0] = g_steal_pointer (&values); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("3"); values[2] = g_strdup ("4"); values[3] = g_strdup ("5"); values[4] = NULL; array[1] = g_steal_pointer (&values); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("6"); values[2] = g_strdup ("7"); values[3] = g_strdup ("8"); values[4] = NULL; array[2] = g_steal_pointer (&values); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("9"); values[2] = g_strdup ("10"); values[3] = g_strdup ("11"); values[4] = NULL; array[3] = g_steal_pointer (&values); *array_inout = (GStrv *) array; *inout_length = 4; } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_none_inout: * @array_inout: (array length=inout_length) (inout) (element-type GStrv) (transfer none): * @inout_length: (inout): */ void gi_marshalling_tests_length_array_of_gstrv_transfer_none_inout (GStrv **array_inout, size_t *inout_length) { static const gchar *values0[] = { "-1", "0", "1", "2", NULL }; static const gchar *values1[] = { "-1", "3", "4", "5", NULL }; static const gchar *values2[] = { "-1", "6", "7", "8", NULL }; static const gchar *values3[] = { "-1", "9", "10", "11", NULL }; static const gchar **array[] = { values0, values1, values2, values3 }; g_assert_nonnull (inout_length); gi_marshalling_tests_length_array_of_gstrv_transfer_none_in (*array_inout, *inout_length); *array_inout = (GStrv *) array; *inout_length = 4; } /** * gi_marshalling_tests_length_array_of_gstrv_transfer_container_inout: * @array_inout: (array length=inout_length) (inout) (element-type GStrv) (transfer container): * @inout_length: (inout): */ void gi_marshalling_tests_length_array_of_gstrv_transfer_container_inout (GStrv **array_inout, size_t *inout_length) { GStrv *array = g_new0 (GStrv, 4); static const gchar *values0[] = { "-1", "0", "1", "2", NULL }; static const gchar *values1[] = { "-1", "3", "4", "5", NULL }; static const gchar *values2[] = { "-1", "6", "7", "8", NULL }; static const gchar *values3[] = { "-1", "9", "10", "11", NULL }; g_assert_nonnull (inout_length); g_assert_nonnull (array_inout); gi_marshalling_tests_length_array_of_gstrv_transfer_container_in (*array_inout, *inout_length); array[0] = (GStrv) values0; array[1] = (GStrv) values1; array[2] = (GStrv) values2; array[3] = (GStrv) values3; *array_inout = (GStrv *) array; *inout_length = 4; } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_return: * * Returns: (array zero-terminated) (element-type GStrv) (transfer full): */ GStrv * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_return (void) { GStrv *array = g_new0 (GStrv, 4); GStrv values; values = g_new0 (gchar *, 4); values[0] = g_strdup ("0"); values[1] = g_strdup ("1"); values[2] = g_strdup ("2"); values[3] = NULL; array[0] = g_steal_pointer (&values); values = g_new0 (gchar *, 4); values[0] = g_strdup ("3"); values[1] = g_strdup ("4"); values[2] = g_strdup ("5"); values[3] = NULL; array[1] = g_steal_pointer (&values); values = g_new0 (gchar *, 4); values[0] = g_strdup ("6"); values[1] = g_strdup ("7"); values[2] = g_strdup ("8"); values[3] = NULL; array[2] = g_steal_pointer (&values); return array; } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_return: * * Returns: (array zero-terminated) (element-type GStrv) (transfer container): */ GStrv * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_return (void) { GStrv *array = g_new0 (GStrv, 4); static const gchar *values0[] = { "0", "1", "2", NULL }; static const gchar *values1[] = { "3", "4", "5", NULL }; static const gchar *values2[] = { "6", "7", "8", NULL }; array[0] = (GStrv) values0; array[1] = (GStrv) values1; array[2] = (GStrv) values2; array[3] = NULL; return array; } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_return: * * Returns: (array zero-terminated) (element-type GStrv) (transfer none): */ GStrv * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_return (void) { static const gchar *values0[] = { "0", "1", "2", NULL }; static const gchar *values1[] = { "3", "4", "5", NULL }; static const gchar *values2[] = { "6", "7", "8", NULL }; static const gchar **array[] = { values0, values1, values2, NULL }; return (GStrv *) array; } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_return: * * Returns: (array fixed-size=3) (element-type GStrv) (transfer full): */ GStrv * gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_return (void) { GStrv *array = g_new0 (GStrv, 3); GStrv values; values = g_new0 (gchar *, 4); values[0] = g_strdup ("0"); values[1] = g_strdup ("1"); values[2] = g_strdup ("2"); values[3] = NULL; array[0] = g_steal_pointer (&values); values = g_new0 (gchar *, 4); values[0] = g_strdup ("3"); values[1] = g_strdup ("4"); values[2] = g_strdup ("5"); values[3] = NULL; array[1] = g_steal_pointer (&values); values = g_new0 (gchar *, 4); values[0] = g_strdup ("6"); values[1] = g_strdup ("7"); values[2] = g_strdup ("8"); values[3] = NULL; array[2] = g_steal_pointer (&values); return array; } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_in: * @array: (array zero-terminated) (element-type GStrv) (transfer none): */ void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_in (GStrv *array) { GStrv g_strv; g_strv = array[0]; g_assert_cmpint (g_strv_length (g_strv), ==, 3); g_assert_cmpstr (g_strv[0], ==, "0"); g_assert_cmpstr (g_strv[1], ==, "1"); g_assert_cmpstr (g_strv[2], ==, "2"); g_strv = array[1]; g_assert_cmpint (g_strv_length (g_strv), ==, 3); g_assert_cmpstr (g_strv[0], ==, "3"); g_assert_cmpstr (g_strv[1], ==, "4"); g_assert_cmpstr (g_strv[2], ==, "5"); g_strv = array[2]; g_assert_cmpint (g_strv_length (g_strv), ==, 3); g_assert_cmpstr (g_strv[0], ==, "6"); g_assert_cmpstr (g_strv[1], ==, "7"); g_assert_cmpstr (g_strv[2], ==, "8"); g_assert_null (array[3]); } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_in: * @array: (array zero-terminated) (element-type GStrv) (transfer container): */ void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_in (GStrv *array) { gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_in (array); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_in: * @array: (array zero-terminated) (element-type GStrv) (transfer full): */ void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_in (GStrv *array) { gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_in (array); for (int i = 0; array && array[i] != NULL; i++) g_clear_pointer (&array[i], g_strfreev); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_out: * @array_out: (array zero-terminated) (out) (element-type GStrv) (transfer none): */ void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_out (GStrv **array_out) { *array_out = gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_return (); } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_out: * @array_out: (array zero-terminated) (out) (element-type GStrv) (transfer container): */ void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_out (GStrv **array_out) { *array_out = gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_return (); } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_out: * @array_out: (array zero-terminated) (out) (element-type GStrv) (transfer full): */ void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_out (GStrv **array_out) { *array_out = gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_return (); } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_inout: * @array_inout: (array zero-terminated) (inout) (element-type GStrv) (transfer full): */ void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_inout (GStrv **array_inout) { GStrv *array = g_new0 (GStrv, 5); GStrv values; gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_in ( g_steal_pointer (array_inout)); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("0"); values[2] = g_strdup ("1"); values[3] = g_strdup ("2"); values[4] = NULL; array[0] = g_steal_pointer (&values); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("3"); values[2] = g_strdup ("4"); values[3] = g_strdup ("5"); values[4] = NULL; array[1] = g_steal_pointer (&values); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("6"); values[2] = g_strdup ("7"); values[3] = g_strdup ("8"); values[4] = NULL; array[2] = g_steal_pointer (&values); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("9"); values[2] = g_strdup ("10"); values[3] = g_strdup ("11"); values[4] = NULL; array[3] = g_steal_pointer (&values); *array_inout = (GStrv *) array; } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_inout: * @array_inout: (array zero-terminated) (inout) (element-type GStrv) (transfer none): */ void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_inout (GStrv **array_inout) { static const gchar *values0[] = { "-1", "0", "1", "2", NULL }; static const gchar *values1[] = { "-1", "3", "4", "5", NULL }; static const gchar *values2[] = { "-1", "6", "7", "8", NULL }; static const gchar *values3[] = { "-1", "9", "10", "11", NULL }; static const gchar **array[] = { values0, values1, values2, values3, NULL }; gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_in (*array_inout); *array_inout = (GStrv *) array; } /** * gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_inout: * @array_inout: (array zero-terminated) (inout) (element-type GStrv) (transfer container): */ void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_inout (GStrv **array_inout) { GStrv *array = g_new0 (GStrv, 4); static const gchar *values0[] = { "-1", "0", "1", "2", NULL }; static const gchar *values1[] = { "-1", "3", "4", "5", NULL }; static const gchar *values2[] = { "-1", "6", "7", "8", NULL }; static const gchar *values3[] = { "-1", "9", "10", "11", NULL }; gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_in (*array_inout); array[0] = (GStrv) values0; array[1] = (GStrv) values1; array[2] = (GStrv) values2; array[3] = (GStrv) values3; *array_inout = (GStrv *) array; } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_return: * * Returns: (array fixed-size=3) (element-type GStrv) (transfer container): */ GStrv * gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_return (void) { GStrv *array = g_new0 (GStrv, 3); static const gchar *values0[] = { "0", "1", "2", NULL }; static const gchar *values1[] = { "3", "4", "5", NULL }; static const gchar *values2[] = { "6", "7", "8", NULL }; array[0] = (GStrv) values0; array[1] = (GStrv) values1; array[2] = (GStrv) values2; return array; } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_return: * * Returns: (array fixed-size=3) (element-type GStrv) (transfer none): */ GStrv * gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_return (void) { static const gchar *values0[] = { "0", "1", "2", NULL }; static const gchar *values1[] = { "3", "4", "5", NULL }; static const gchar *values2[] = { "6", "7", "8", NULL }; static const gchar **array[] = { values0, values1, values2 }; return (GStrv *) array; } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_in: * @array: (array fixed-size=3) (element-type GStrv) (transfer none): */ void gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_in (GStrv *array) { GStrv g_strv; g_strv = array[0]; g_assert_cmpint (g_strv_length (g_strv), ==, 3); g_assert_cmpstr (g_strv[0], ==, "0"); g_assert_cmpstr (g_strv[1], ==, "1"); g_assert_cmpstr (g_strv[2], ==, "2"); g_strv = array[1]; g_assert_cmpint (g_strv_length (g_strv), ==, 3); g_assert_cmpstr (g_strv[0], ==, "3"); g_assert_cmpstr (g_strv[1], ==, "4"); g_assert_cmpstr (g_strv[2], ==, "5"); g_strv = array[2]; g_assert_cmpint (g_strv_length (g_strv), ==, 3); g_assert_cmpstr (g_strv[0], ==, "6"); g_assert_cmpstr (g_strv[1], ==, "7"); g_assert_cmpstr (g_strv[2], ==, "8"); } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_in: * @array: (array fixed-size=3) (element-type GStrv) (transfer container): */ void gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_in (GStrv *array) { gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_in (array); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_in: * @array: (array fixed-size=3) (element-type GStrv) (transfer full): */ void gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_in (GStrv *array) { gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_in (array); g_clear_pointer (&array[0], g_strfreev); g_clear_pointer (&array[1], g_strfreev); g_clear_pointer (&array[2], g_strfreev); g_clear_pointer (&array, g_free); } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_out: * @array_out: (array fixed-size=3) (out) (element-type GStrv) (transfer none): */ void gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_out (GStrv **array_out) { *array_out = gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_return (); } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_out: * @array_out: (array fixed-size=3) (out) (element-type GStrv) (transfer container): */ void gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_out (GStrv **array_out) { *array_out = gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_return (); } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_out: * @array_out: (array fixed-size=3) (out) (element-type GStrv) (transfer full): */ void gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_out (GStrv **array_out) { *array_out = gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_return (); } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_inout: * @array_inout: (array fixed-size=3) (inout) (element-type GStrv) (transfer full): */ void gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_inout (GStrv **array_inout) { GStrv *array = g_new0 (GStrv, 3); GStrv values; gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_in ( g_steal_pointer (array_inout)); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("0"); values[2] = g_strdup ("1"); values[3] = g_strdup ("2"); values[4] = NULL; array[0] = g_steal_pointer (&values); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("3"); values[2] = g_strdup ("4"); values[3] = g_strdup ("5"); values[4] = NULL; array[1] = g_steal_pointer (&values); values = g_new0 (gchar *, 5); values[0] = g_strdup ("-1"); values[1] = g_strdup ("6"); values[2] = g_strdup ("7"); values[3] = g_strdup ("8"); values[4] = NULL; array[2] = g_steal_pointer (&values); *array_inout = (GStrv *) array; } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_inout: * @array_inout: (array fixed-size=3) (inout) (element-type GStrv) (transfer none): */ void gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_inout (GStrv **array_inout) { static const gchar *values0[] = { "-1", "0", "1", "2", NULL }; static const gchar *values1[] = { "-1", "3", "4", "5", NULL }; static const gchar *values2[] = { "-1", "6", "7", "8", NULL }; static const gchar **array[] = { values0, values1, values2 }; gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_in (*array_inout); *array_inout = (GStrv *) array; } /** * gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_inout: * @array_inout: (array fixed-size=3) (inout) (element-type GStrv) (transfer container): */ void gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_inout (GStrv **array_inout) { GStrv *array = g_new0 (GStrv, 3); static const gchar *values0[] = { "-1", "0", "1", "2", NULL }; static const gchar *values1[] = { "-1", "3", "4", "5", NULL }; static const gchar *values2[] = { "-1", "6", "7", "8", NULL }; gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_in (*array_inout); array[0] = (GStrv) values0; array[1] = (GStrv) values1; array[2] = (GStrv) values2; *array_inout = (GStrv *) array; } /** * gi_marshalling_tests_glist_int_none_return: * * Returns: (element-type gint) (transfer none): */ GList * gi_marshalling_tests_glist_int_none_return (void) { static GList *list = NULL; if (list == NULL) { list = g_list_append (list, GINT_TO_POINTER (-1)); list = g_list_append (list, GINT_TO_POINTER (0)); list = g_list_append (list, GINT_TO_POINTER (1)); list = g_list_append (list, GINT_TO_POINTER (2)); } return list; } /** * gi_marshalling_tests_glist_uint32_none_return: * * Returns: (element-type guint32) (transfer none): */ GList * gi_marshalling_tests_glist_uint32_none_return (void) { static GList *list = NULL; if (list == NULL) { list = g_list_append (list, GUINT_TO_POINTER (0)); list = g_list_append (list, GUINT_TO_POINTER (G_MAXUINT32)); } return list; } /** * gi_marshalling_tests_glist_utf8_none_return: * * Returns: (element-type utf8) (transfer none): */ GList * gi_marshalling_tests_glist_utf8_none_return (void) { static GList *list = NULL; if (list == NULL) { list = g_list_append (list, (gpointer) "0"); list = g_list_append (list, (gpointer) "1"); list = g_list_append (list, (gpointer) "2"); } return list; } /** * gi_marshalling_tests_glist_utf8_container_return: * * Returns: (element-type utf8) (transfer container): */ GList * gi_marshalling_tests_glist_utf8_container_return (void) { GList *list = NULL; list = g_list_append (list, (gpointer) "0"); list = g_list_append (list, (gpointer) "1"); list = g_list_append (list, (gpointer) "2"); return list; } /** * gi_marshalling_tests_glist_utf8_full_return: * * Returns: (element-type utf8) (transfer full): */ GList * gi_marshalling_tests_glist_utf8_full_return (void) { GList *list = NULL; list = g_list_append (list, g_strdup ("0")); list = g_list_append (list, g_strdup ("1")); list = g_list_append (list, g_strdup ("2")); return list; } /** * gi_marshalling_tests_glist_int_none_in: * @list: (element-type gint) (transfer none): */ void gi_marshalling_tests_glist_int_none_in (GList *list) { g_assert_cmpint (g_list_length (list), ==, 4); g_assert_cmpint (GPOINTER_TO_INT (g_list_nth_data (list, 0)), ==, -1); g_assert_cmpint (GPOINTER_TO_INT (g_list_nth_data (list, 1)), ==, 0); g_assert_cmpint (GPOINTER_TO_INT (g_list_nth_data (list, 2)), ==, 1); g_assert_cmpint (GPOINTER_TO_INT (g_list_nth_data (list, 3)), ==, 2); } /** * gi_marshalling_tests_glist_uint32_none_in: * @list: (element-type guint32) (transfer none): */ void gi_marshalling_tests_glist_uint32_none_in (GList *list) { g_assert_cmpint (g_list_length (list), ==, 2); g_assert_cmpint (GPOINTER_TO_UINT (g_list_nth_data (list, 0)), ==, 0); g_assert_cmpint (GPOINTER_TO_UINT (g_list_nth_data (list, 1)), ==, G_MAXUINT32); } /** * gi_marshalling_tests_glist_utf8_none_in: * @list: (element-type utf8) (transfer none): */ void gi_marshalling_tests_glist_utf8_none_in (GList *list) { g_assert_cmpint (g_list_length (list), ==, 3); g_assert_cmpint (strcmp (g_list_nth_data (list, 0), "0"), ==, 0); g_assert_cmpint (strcmp (g_list_nth_data (list, 1), "1"), ==, 0); g_assert_cmpint (strcmp (g_list_nth_data (list, 2), "2"), ==, 0); } /** * gi_marshalling_tests_glist_utf8_container_in: * @list: (element-type utf8) (transfer container): */ void gi_marshalling_tests_glist_utf8_container_in (GList *list) { gi_marshalling_tests_glist_utf8_none_in (list); g_list_free (list); } /** * gi_marshalling_tests_glist_utf8_full_in: * @list: (element-type utf8) (transfer full): */ void gi_marshalling_tests_glist_utf8_full_in (GList *list) { gi_marshalling_tests_glist_utf8_none_in (list); g_list_free_full (list, g_free); } /** * gi_marshalling_tests_glist_utf8_none_out: * @list: (out) (element-type utf8) (transfer none): */ void gi_marshalling_tests_glist_utf8_none_out (GList **list) { static GList *values = NULL; if (values == NULL) { values = g_list_append (values, (gpointer) "0"); values = g_list_append (values, (gpointer) "1"); values = g_list_append (values, (gpointer) "2"); } *list = values; } /** * gi_marshalling_tests_glist_utf8_none_out_uninitialized: * @v: (out) (element-type utf8) (transfer none): */ gboolean gi_marshalling_tests_glist_utf8_none_out_uninitialized (GList **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_glist_utf8_container_out: * @list: (out) (element-type utf8) (transfer container): */ void gi_marshalling_tests_glist_utf8_container_out (GList **list) { *list = NULL; *list = g_list_append (*list, (gpointer) "0"); *list = g_list_append (*list, (gpointer) "1"); *list = g_list_append (*list, (gpointer) "2"); } /** * gi_marshalling_tests_glist_utf8_container_out_uninitialized: * @v: (out) (element-type utf8) (transfer container): */ gboolean gi_marshalling_tests_glist_utf8_container_out_uninitialized (GList **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_glist_utf8_full_out: * @list: (out) (element-type utf8) (transfer full): */ void gi_marshalling_tests_glist_utf8_full_out (GList **list) { *list = NULL; *list = g_list_append (*list, g_strdup ("0")); *list = g_list_append (*list, g_strdup ("1")); *list = g_list_append (*list, g_strdup ("2")); } /** * gi_marshalling_tests_glist_utf8_full_out_uninitialized: * @v: (out) (element-type utf8) (transfer full): */ gboolean gi_marshalling_tests_glist_utf8_full_out_uninitialized (GList **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_glist_utf8_none_inout: * @list: (inout) (element-type utf8) (transfer none): */ void gi_marshalling_tests_glist_utf8_none_inout (GList **list) { static GList *values = NULL; g_assert_cmpint (g_list_length (*list), ==, 3); g_assert_cmpstr (g_list_nth_data (*list, 0), ==, "0"); g_assert_cmpstr (g_list_nth_data (*list, 1), ==, "1"); g_assert_cmpstr (g_list_nth_data (*list, 2), ==, "2"); if (values == NULL) { values = g_list_append (values, (gpointer) "-2"); values = g_list_append (values, (gpointer) "-1"); values = g_list_append (values, (gpointer) "0"); values = g_list_append (values, (gpointer) "1"); } *list = values; } /** * gi_marshalling_tests_glist_utf8_container_inout: * @list: (inout) (element-type utf8) (transfer container): */ void gi_marshalling_tests_glist_utf8_container_inout (GList **list) { GList *result = NULL; g_assert_cmpint (g_list_length (*list), ==, 3); g_assert_cmpstr (g_list_nth_data (*list, 0), ==, "0"); g_assert_cmpstr (g_list_nth_data (*list, 1), ==, "1"); g_assert_cmpstr (g_list_nth_data (*list, 2), ==, "2"); result = g_list_prepend (result, (gpointer) "1"); result = g_list_prepend (result, (gpointer) "0"); result = g_list_prepend (result, (gpointer) "-1"); result = g_list_prepend (result, (gpointer) "-2"); g_list_free (*list); *list = result; } /** * gi_marshalling_tests_glist_utf8_full_inout: * @list: (inout) (element-type utf8) (transfer full): */ void gi_marshalling_tests_glist_utf8_full_inout (GList **list) { GList *result = NULL; g_assert_cmpint (g_list_length (*list), ==, 3); g_assert_cmpstr (g_list_nth_data (*list, 0), ==, "0"); g_assert_cmpstr (g_list_nth_data (*list, 1), ==, "1"); g_assert_cmpstr (g_list_nth_data (*list, 2), ==, "2"); result = g_list_prepend (result, g_strdup ("1")); result = g_list_prepend (result, g_strdup ("0")); result = g_list_prepend (result, g_strdup ("-1")); result = g_list_prepend (result, g_strdup ("-2")); g_list_free_full (*list, g_free); *list = result; } /** * gi_marshalling_tests_gslist_int_none_return: * * Returns: (element-type gint) (transfer none): */ GSList * gi_marshalling_tests_gslist_int_none_return (void) { static GSList *list = NULL; if (list == NULL) { list = g_slist_prepend (list, GINT_TO_POINTER (-1)); list = g_slist_prepend (list, GINT_TO_POINTER (0)); list = g_slist_prepend (list, GINT_TO_POINTER (1)); list = g_slist_prepend (list, GINT_TO_POINTER (2)); list = g_slist_reverse (list); } return list; } /** * gi_marshalling_tests_gslist_utf8_none_return: * * Returns: (element-type utf8) (transfer none): */ GSList * gi_marshalling_tests_gslist_utf8_none_return (void) { static GSList *list = NULL; if (list == NULL) { list = g_slist_prepend (list, (gpointer) "0"); list = g_slist_prepend (list, (gpointer) "1"); list = g_slist_prepend (list, (gpointer) "2"); list = g_slist_reverse (list); } return list; } /** * gi_marshalling_tests_gslist_utf8_container_return: * * Returns: (element-type utf8) (transfer container): */ GSList * gi_marshalling_tests_gslist_utf8_container_return (void) { GSList *list = NULL; list = g_slist_prepend (list, (gpointer) "0"); list = g_slist_prepend (list, (gpointer) "1"); list = g_slist_prepend (list, (gpointer) "2"); list = g_slist_reverse (list); return list; } /** * gi_marshalling_tests_gslist_utf8_full_return: * * Returns: (element-type utf8) (transfer full): */ GSList * gi_marshalling_tests_gslist_utf8_full_return (void) { GSList *list = NULL; list = g_slist_prepend (list, g_strdup ("0")); list = g_slist_prepend (list, g_strdup ("1")); list = g_slist_prepend (list, g_strdup ("2")); list = g_slist_reverse (list); return list; } /** * gi_marshalling_tests_gslist_int_none_in: * @list: (element-type gint) (transfer none): */ void gi_marshalling_tests_gslist_int_none_in (GSList *list) { g_assert_cmpint (g_slist_length (list), ==, 4); g_assert_cmpint (GPOINTER_TO_INT (g_slist_nth_data (list, 0)), ==, -1); g_assert_cmpint (GPOINTER_TO_INT (g_slist_nth_data (list, 1)), ==, 0); g_assert_cmpint (GPOINTER_TO_INT (g_slist_nth_data (list, 2)), ==, 1); g_assert_cmpint (GPOINTER_TO_INT (g_slist_nth_data (list, 3)), ==, 2); } /** * gi_marshalling_tests_gslist_utf8_none_in: * @list: (element-type utf8) (transfer none): */ void gi_marshalling_tests_gslist_utf8_none_in (GSList *list) { g_assert_cmpint (g_slist_length (list), ==, 3); g_assert_cmpstr (g_slist_nth_data (list, 0), ==, "0"); g_assert_cmpstr (g_slist_nth_data (list, 1), ==, "1"); g_assert_cmpstr (g_slist_nth_data (list, 2), ==, "2"); } /** * gi_marshalling_tests_gslist_utf8_container_in: * @list: (element-type utf8) (transfer container): */ void gi_marshalling_tests_gslist_utf8_container_in (GSList *list) { gi_marshalling_tests_gslist_utf8_none_in (list); g_slist_free (list); } /** * gi_marshalling_tests_gslist_utf8_full_in: * @list: (element-type utf8) (transfer full): */ void gi_marshalling_tests_gslist_utf8_full_in (GSList *list) { gi_marshalling_tests_gslist_utf8_none_in (list); g_slist_free_full (list, g_free); } /** * gi_marshalling_tests_gslist_utf8_none_out: * @list: (out) (element-type utf8) (transfer none): */ void gi_marshalling_tests_gslist_utf8_none_out (GSList **list) { static GSList *values = NULL; if (values == NULL) { values = g_slist_prepend (values, (gpointer) "0"); values = g_slist_prepend (values, (gpointer) "1"); values = g_slist_prepend (values, (gpointer) "2"); values = g_slist_reverse (values); } *list = values; } /** * gi_marshalling_tests_gslist_utf8_none_out_uninitialized: * @v: (out) (element-type utf8) (transfer none): */ gboolean gi_marshalling_tests_gslist_utf8_none_out_uninitialized (GSList **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gslist_utf8_container_out: * @list: (out) (element-type utf8) (transfer container): */ void gi_marshalling_tests_gslist_utf8_container_out (GSList **list) { *list = NULL; *list = g_slist_prepend (*list, (gpointer) "0"); *list = g_slist_prepend (*list, (gpointer) "1"); *list = g_slist_prepend (*list, (gpointer) "2"); *list = g_slist_reverse (*list); } /** * gi_marshalling_tests_gslist_utf8_container_out_uninitialized: * @v: (out) (element-type utf8) (transfer container): */ gboolean gi_marshalling_tests_gslist_utf8_container_out_uninitialized (GSList **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gslist_utf8_full_out: * @list: (out) (element-type utf8) (transfer full): */ void gi_marshalling_tests_gslist_utf8_full_out (GSList **list) { *list = NULL; *list = g_slist_prepend (*list, g_strdup ("0")); *list = g_slist_prepend (*list, g_strdup ("1")); *list = g_slist_prepend (*list, g_strdup ("2")); *list = g_slist_reverse (*list); } /** * gi_marshalling_tests_gslist_utf8_full_out_uninitialized: * @v: (out) (element-type utf8) (transfer full): */ gboolean gi_marshalling_tests_gslist_utf8_full_out_uninitialized (GSList **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gslist_utf8_none_inout: * @list: (inout) (element-type utf8) (transfer none): */ void gi_marshalling_tests_gslist_utf8_none_inout (GSList **list) { static GSList *values = NULL; g_assert_cmpint (g_slist_length (*list), ==, 3); g_assert_cmpstr (g_slist_nth_data (*list, 0), ==, "0"); g_assert_cmpstr (g_slist_nth_data (*list, 1), ==, "1"); g_assert_cmpstr (g_slist_nth_data (*list, 2), ==, "2"); if (values == NULL) { values = g_slist_prepend (values, (gpointer) "-2"); values = g_slist_prepend (values, (gpointer) "-1"); values = g_slist_prepend (values, (gpointer) "0"); values = g_slist_prepend (values, (gpointer) "1"); values = g_slist_reverse (values); } *list = values; } /** * gi_marshalling_tests_gslist_utf8_container_inout: * @list: (inout) (element-type utf8) (transfer container): */ void gi_marshalling_tests_gslist_utf8_container_inout (GSList **list) { GSList *result = NULL; g_assert_cmpint (g_slist_length (*list), ==, 3); g_assert_cmpstr (g_slist_nth_data (*list, 0), ==, "0"); g_assert_cmpstr (g_slist_nth_data (*list, 1), ==, "1"); g_assert_cmpstr (g_slist_nth_data (*list, 2), ==, "2"); result = g_slist_prepend (result, (gpointer) "1"); result = g_slist_prepend (result, (gpointer) "0"); result = g_slist_prepend (result, (gpointer) "-1"); result = g_slist_prepend (result, (gpointer) "-2"); g_slist_free (*list); *list = result; } /** * gi_marshalling_tests_gslist_utf8_full_inout: * @list: (inout) (element-type utf8) (transfer full): */ void gi_marshalling_tests_gslist_utf8_full_inout (GSList **list) { GSList *result = NULL; g_assert_cmpint (g_slist_length (*list), ==, 3); g_assert_cmpstr (g_slist_nth_data (*list, 0), ==, "0"); g_assert_cmpstr (g_slist_nth_data (*list, 1), ==, "1"); g_assert_cmpstr (g_slist_nth_data (*list, 2), ==, "2"); result = g_slist_prepend (result, g_strdup ("1")); result = g_slist_prepend (result, g_strdup ("0")); result = g_slist_prepend (result, g_strdup ("-1")); result = g_slist_prepend (result, g_strdup ("-2")); g_slist_free_full (*list, g_free); *list = result; } /** * gi_marshalling_tests_ghashtable_int_none_return: * * Returns: (element-type gint gint) (transfer none): */ GHashTable * gi_marshalling_tests_ghashtable_int_none_return (void) { static GHashTable *hash_table = NULL; if (hash_table == NULL) { hash_table = g_hash_table_new (NULL, NULL); g_hash_table_insert (hash_table, GINT_TO_POINTER (-1), GINT_TO_POINTER (1)); g_hash_table_insert (hash_table, GINT_TO_POINTER (0), GINT_TO_POINTER (0)); g_hash_table_insert (hash_table, GINT_TO_POINTER (1), GINT_TO_POINTER (-1)); g_hash_table_insert (hash_table, GINT_TO_POINTER (2), GINT_TO_POINTER (-2)); } return hash_table; } /** * gi_marshalling_tests_ghashtable_utf8_none_return: * * Returns: (element-type utf8 utf8) (transfer none): */ GHashTable * gi_marshalling_tests_ghashtable_utf8_none_return (void) { static GHashTable *hash_table = NULL; if (hash_table == NULL) { hash_table = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (hash_table, (gpointer) "-1", (gpointer) "1"); g_hash_table_insert (hash_table, (gpointer) "0", (gpointer) "0"); g_hash_table_insert (hash_table, (gpointer) "1", (gpointer) "-1"); g_hash_table_insert (hash_table, (gpointer) "2", (gpointer) "-2"); } return hash_table; } /** * gi_marshalling_tests_ghashtable_utf8_container_return: * * Returns: (element-type utf8 utf8) (transfer container): */ GHashTable * gi_marshalling_tests_ghashtable_utf8_container_return (void) { GHashTable *hash_table = NULL; hash_table = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (hash_table, (gpointer) "-1", (gpointer) "1"); g_hash_table_insert (hash_table, (gpointer) "0", (gpointer) "0"); g_hash_table_insert (hash_table, (gpointer) "1", (gpointer) "-1"); g_hash_table_insert (hash_table, (gpointer) "2", (gpointer) "-2"); return hash_table; } /** * gi_marshalling_tests_ghashtable_utf8_full_return: * * Returns: (element-type utf8 utf8) (transfer full): */ GHashTable * gi_marshalling_tests_ghashtable_utf8_full_return (void) { GHashTable *hash_table = NULL; hash_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert (hash_table, g_strdup ("-1"), g_strdup ("1")); g_hash_table_insert (hash_table, g_strdup ("0"), g_strdup ("0")); g_hash_table_insert (hash_table, g_strdup ("1"), g_strdup ("-1")); g_hash_table_insert (hash_table, g_strdup ("2"), g_strdup ("-2")); return hash_table; } /** * gi_marshalling_tests_ghashtable_int_none_in: * @hash_table: (element-type gint gint) (transfer none): */ void gi_marshalling_tests_ghashtable_int_none_in (GHashTable *hash_table) { g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (hash_table, GINT_TO_POINTER (-1))), ==, 1); g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (hash_table, GINT_TO_POINTER (0))), ==, 0); g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (hash_table, GINT_TO_POINTER (1))), ==, -1); g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (hash_table, GINT_TO_POINTER (2))), ==, -2); } /** * gi_marshalling_tests_ghashtable_utf8_none_in: * @hash_table: (element-type utf8 utf8) (transfer none): */ void gi_marshalling_tests_ghashtable_utf8_none_in (GHashTable *hash_table) { g_assert_cmpstr (g_hash_table_lookup (hash_table, "-1"), ==, "1"); g_assert_cmpstr (g_hash_table_lookup (hash_table, "0"), ==, "0"); g_assert_cmpstr (g_hash_table_lookup (hash_table, "1"), ==, "-1"); g_assert_cmpstr (g_hash_table_lookup (hash_table, "2"), ==, "-2"); } /** * gi_marshalling_tests_ghashtable_utf8_container_in: * @hash_table: (element-type utf8 utf8) (transfer container): */ void gi_marshalling_tests_ghashtable_utf8_container_in (GHashTable *hash_table) { gi_marshalling_tests_ghashtable_utf8_none_in (hash_table); g_hash_table_steal_all (hash_table); g_hash_table_unref (hash_table); } static gboolean hash_table_free_helper (gpointer key, gpointer value, gpointer data G_GNUC_UNUSED) { g_free (key); g_free (value); return TRUE; } /** * gi_marshalling_tests_ghashtable_utf8_full_in: * @hash_table: (element-type utf8 utf8) (transfer full): */ void gi_marshalling_tests_ghashtable_utf8_full_in (GHashTable *hash_table) { gi_marshalling_tests_ghashtable_utf8_none_in (hash_table); /* Free the keys and values manually. Do not rely on the binding passing in a * GHashTable with the destroy functions set. */ g_hash_table_foreach_steal (hash_table, hash_table_free_helper, NULL); g_hash_table_unref (hash_table); } /** * gi_marshalling_tests_ghashtable_double_in: * @hash_table: (element-type utf8 double) (transfer none): * * Meant to test a value type that doesn't fit inside a pointer. */ void gi_marshalling_tests_ghashtable_double_in (GHashTable *hash_table) { double *value; value = g_hash_table_lookup (hash_table, "-1"); g_assert_cmpfloat_with_epsilon (*value, -0.1, 0.01); value = g_hash_table_lookup (hash_table, "0"); g_assert_cmpfloat (*value, ==, 0.0); value = g_hash_table_lookup (hash_table, "1"); g_assert_cmpfloat_with_epsilon (*value, 0.1, 0.01); value = g_hash_table_lookup (hash_table, "2"); g_assert_cmpfloat_with_epsilon (*value, 0.2, 0.01); } /** * gi_marshalling_tests_ghashtable_float_in: * @hash_table: (element-type utf8 float) (transfer none): * * Meant to test a value type that doesn't fit inside a pointer. */ void gi_marshalling_tests_ghashtable_float_in (GHashTable *hash_table) { float *value; value = g_hash_table_lookup (hash_table, "-1"); g_assert_cmpfloat_with_epsilon (*value, -0.1f, 0.01f); value = g_hash_table_lookup (hash_table, "0"); g_assert_cmpfloat (*value, ==, 0.0f); value = g_hash_table_lookup (hash_table, "1"); g_assert_cmpfloat_with_epsilon (*value, 0.1f, 0.01f); value = g_hash_table_lookup (hash_table, "2"); g_assert_cmpfloat_with_epsilon (*value, 0.2f, 0.01f); } /** * gi_marshalling_tests_ghashtable_int64_in: * @hash_table: (element-type utf8 gint64) (transfer none): * * Meant to test a value type that doesn't fit inside a pointer. */ void gi_marshalling_tests_ghashtable_int64_in (GHashTable *hash_table) { gint64 *value; value = g_hash_table_lookup (hash_table, "-1"); g_assert_cmpint (*value, ==, -1); value = g_hash_table_lookup (hash_table, "0"); g_assert_cmpint (*value, ==, 0); value = g_hash_table_lookup (hash_table, "1"); g_assert_cmpint (*value, ==, 1); value = g_hash_table_lookup (hash_table, "2"); g_assert_cmpint (*value, ==, (gint64) G_MAXUINT32 + 1); } /** * gi_marshalling_tests_ghashtable_uint64_in: * @hash_table: (element-type utf8 guint64) (transfer none): * * Meant to test a value type that doesn't fit inside a pointer. */ void gi_marshalling_tests_ghashtable_uint64_in (GHashTable *hash_table) { guint64 *value; value = g_hash_table_lookup (hash_table, "-1"); g_assert_cmpuint (*value, ==, (guint64) G_MAXUINT32 + 1); value = g_hash_table_lookup (hash_table, "0"); g_assert_cmpuint (*value, ==, 0); value = g_hash_table_lookup (hash_table, "1"); g_assert_cmpuint (*value, ==, 1); value = g_hash_table_lookup (hash_table, "2"); g_assert_cmpuint (*value, ==, 2); } /** * gi_marshalling_tests_ghashtable_utf8_none_out: * @hash_table: (out) (element-type utf8 utf8) (transfer none): */ void gi_marshalling_tests_ghashtable_utf8_none_out (GHashTable **hash_table) { static GHashTable *new_hash_table = NULL; if (new_hash_table == NULL) { new_hash_table = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (new_hash_table, (gpointer) "-1", (gpointer) "1"); g_hash_table_insert (new_hash_table, (gpointer) "0", (gpointer) "0"); g_hash_table_insert (new_hash_table, (gpointer) "1", (gpointer) "-1"); g_hash_table_insert (new_hash_table, (gpointer) "2", (gpointer) "-2"); } *hash_table = new_hash_table; } /** * gi_marshalling_tests_ghashtable_utf8_none_out_uninitialized: * @v: (out) (element-type utf8 utf8) (transfer none): */ gboolean gi_marshalling_tests_ghashtable_utf8_none_out_uninitialized (GHashTable **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_ghashtable_utf8_container_out: * @hash_table: (out) (element-type utf8 utf8) (transfer container): */ void gi_marshalling_tests_ghashtable_utf8_container_out (GHashTable **hash_table) { *hash_table = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (*hash_table, (gpointer) "-1", (gpointer) "1"); g_hash_table_insert (*hash_table, (gpointer) "0", (gpointer) "0"); g_hash_table_insert (*hash_table, (gpointer) "1", (gpointer) "-1"); g_hash_table_insert (*hash_table, (gpointer) "2", (gpointer) "-2"); } /** * gi_marshalling_tests_ghashtable_utf8_container_out_uninitialized: * @v: (out) (element-type utf8 utf8) (transfer container): */ gboolean gi_marshalling_tests_ghashtable_utf8_container_out_uninitialized (GHashTable **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_ghashtable_utf8_full_out: * @hash_table: (out) (element-type utf8 utf8) (transfer full): */ void gi_marshalling_tests_ghashtable_utf8_full_out (GHashTable **hash_table) { *hash_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert (*hash_table, g_strdup ("-1"), g_strdup ("1")); g_hash_table_insert (*hash_table, g_strdup ("0"), g_strdup ("0")); g_hash_table_insert (*hash_table, g_strdup ("1"), g_strdup ("-1")); g_hash_table_insert (*hash_table, g_strdup ("2"), g_strdup ("-2")); } /** * gi_marshalling_tests_ghashtable_utf8_full_out_uninitialized: * @v: (out) (element-type utf8 utf8) (transfer full): */ gboolean gi_marshalling_tests_ghashtable_utf8_full_out_uninitialized (GHashTable **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_ghashtable_utf8_none_inout: * @hash_table: (inout) (element-type utf8 utf8) (transfer none): */ void gi_marshalling_tests_ghashtable_utf8_none_inout (GHashTable **hash_table) { static GHashTable *new_hash_table = NULL; g_assert_cmpstr (g_hash_table_lookup (*hash_table, "-1"), ==, "1"); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "0"), ==, "0"); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "1"), ==, "-1"); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "2"), ==, "-2"); if (new_hash_table == NULL) { new_hash_table = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (new_hash_table, (gpointer) "-1", (gpointer) "1"); g_hash_table_insert (new_hash_table, (gpointer) "0", (gpointer) "0"); g_hash_table_insert (new_hash_table, (gpointer) "1", (gpointer) "1"); } *hash_table = new_hash_table; } /** * gi_marshalling_tests_ghashtable_utf8_container_inout: * @hash_table: (inout) (element-type utf8 utf8) (transfer container): */ void gi_marshalling_tests_ghashtable_utf8_container_inout (GHashTable **hash_table) { GHashTable *result = g_hash_table_new (g_str_hash, g_str_equal); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "-1"), ==, "1"); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "0"), ==, "0"); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "1"), ==, "-1"); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "2"), ==, "-2"); g_hash_table_insert (result, (gpointer) "-1", (gpointer) "1"); g_hash_table_insert (result, (gpointer) "0", (gpointer) "0"); g_hash_table_insert (result, (gpointer) "1", (gpointer) "1"); g_hash_table_unref (*hash_table); *hash_table = result; } /** * gi_marshalling_tests_ghashtable_utf8_full_inout: * @hash_table: (inout) (element-type utf8 utf8) (transfer full): */ void gi_marshalling_tests_ghashtable_utf8_full_inout (GHashTable **hash_table) { GHashTable *result = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "-1"), ==, "1"); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "0"), ==, "0"); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "1"), ==, "-1"); g_assert_cmpstr (g_hash_table_lookup (*hash_table, "2"), ==, "-2"); g_hash_table_insert (result, g_strdup ("-1"), g_strdup ("1")); g_hash_table_insert (result, g_strdup ("0"), g_strdup ("0")); g_hash_table_insert (result, g_strdup ("1"), g_strdup ("1")); g_hash_table_unref (*hash_table); *hash_table = result; } /** * gi_marshalling_tests_gvalue_return: * * Returns: (transfer none): */ GValue * gi_marshalling_tests_gvalue_return (void) { static GValue *value = NULL; if (value == NULL) { value = g_new0 (GValue, 1); g_value_init (value, G_TYPE_INT); g_value_set_int (value, 42); } return value; } /** * gi_marshalling_tests_gvalue_noncanonical_nan_float: * * Returns: (transfer none): */ GValue * gi_marshalling_tests_gvalue_noncanonical_nan_float (void) { static GValue *value = NULL; if (value == NULL) { value = g_new0 (GValue, 1); g_value_init (value, G_TYPE_FLOAT); g_value_set_float (value, noncanonical_nan_float ()); } return value; } /** * gi_marshalling_tests_gvalue_noncanonical_nan_double: * * Returns: (transfer none): */ GValue * gi_marshalling_tests_gvalue_noncanonical_nan_double (void) { static GValue *value = NULL; if (value == NULL) { value = g_new0 (GValue, 1); g_value_init (value, G_TYPE_DOUBLE); g_value_set_double (value, noncanonical_nan_double ()); } return value; } /** * gi_marshalling_tests_gvalue_in: * @value: (transfer none): */ void gi_marshalling_tests_gvalue_in (GValue *value) { g_assert_cmpint (g_value_get_int (value), ==, 42); } /** * gi_marshalling_tests_gvalue_int64_in: * @value: (transfer none): */ void gi_marshalling_tests_gvalue_int64_in (GValue *value) { g_assert_cmpint (g_value_get_int64 (value), ==, G_MAXINT64); } /** * gi_marshalling_tests_gvalue_in_with_type: * @value: (transfer none): * @type: */ void gi_marshalling_tests_gvalue_in_with_type (GValue *value, GType type) { g_assert (g_type_is_a (G_VALUE_TYPE (value), type)); } /** * gi_marshalling_tests_gvalue_in_with_modification: * @value: (transfer none): * * Expects a GValue passed by reference which is then modified by * this function. */ void gi_marshalling_tests_gvalue_in_with_modification (GValue *value) { g_assert_cmpint (g_value_get_int (value), ==, 42); g_value_set_int (value, 24); } /** * gi_marshalling_tests_gvalue_in_enum: * @value: (transfer none): */ void gi_marshalling_tests_gvalue_in_enum (GValue *value) { if (!G_VALUE_HOLDS_ENUM (value)) g_critical ("Expected enum, got %s", G_VALUE_TYPE_NAME (value)); g_assert (g_value_get_enum (value) == GI_MARSHALLING_TESTS_ENUM_VALUE3); } /** * gi_marshalling_tests_gvalue_in_flags: * @value: (transfer none): */ void gi_marshalling_tests_gvalue_in_flags (GValue *value) { if (!G_VALUE_HOLDS_FLAGS (value)) g_critical ("Expected flags, got %s", G_VALUE_TYPE_NAME (value)); g_assert_cmpint (g_value_get_flags (value), ==, GI_MARSHALLING_TESTS_FLAGS_VALUE3); } /** * gi_marshalling_tests_gvalue_out: * @value: (out) (transfer none): */ void gi_marshalling_tests_gvalue_out (GValue **value) { static GValue *new_value = NULL; if (new_value == NULL) { new_value = g_new0 (GValue, 1); g_value_init (new_value, G_TYPE_INT); g_value_set_int (new_value, 42); } *value = new_value; } /** * gi_marshalling_tests_gvalue_out_uninitialized: * @v: (out) (transfer none): */ gboolean gi_marshalling_tests_gvalue_out_uninitialized (GValue **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gvalue_int64_out: * @value: (out) (transfer none): */ void gi_marshalling_tests_gvalue_int64_out (GValue **value) { static GValue *new_value = NULL; if (new_value == NULL) { new_value = g_new0 (GValue, 1); g_value_init (new_value, G_TYPE_INT64); g_value_set_int64 (new_value, G_MAXINT64); } *value = new_value; } /** * gi_marshalling_tests_gvalue_out_caller_allocates: * @value: (out) (transfer none): */ void gi_marshalling_tests_gvalue_out_caller_allocates (GValue *value) { g_value_init (value, G_TYPE_INT); g_value_set_int (value, 42); } /** * gi_marshalling_tests_gvalue_inout: * @value: (inout) (transfer none): */ void gi_marshalling_tests_gvalue_inout (GValue **value) { g_assert_cmpint (g_value_get_int (*value), ==, 42); g_value_unset (*value); g_value_init (*value, G_TYPE_STRING); g_value_set_string (*value, "42"); } /** * gi_marshalling_tests_gvalue_flat_array: * @n_values: number of values * @values: (array length=n_values): an array containing values */ void gi_marshalling_tests_gvalue_flat_array (guint n_values, const GValue *values) { g_assert (n_values == 3); g_assert_cmpint (g_value_get_int (&values[0]), ==, 42); g_assert_cmpstr (g_value_get_string (&values[1]), ==, "42"); g_assert_cmpint (g_value_get_boolean (&values[2]), ==, TRUE); } /** * gi_marshalling_tests_return_gvalue_flat_array: * * Returns: (array fixed-size=3) (transfer full): a flat GValue array */ GValue * gi_marshalling_tests_return_gvalue_flat_array (void) { GValue *array = g_new0 (GValue, 3); g_value_init (&array[0], G_TYPE_INT); g_value_set_int (&array[0], 42); g_value_init (&array[1], G_TYPE_STRING); g_value_set_static_string (&array[1], "42"); g_value_init (&array[2], G_TYPE_BOOLEAN); g_value_set_boolean (&array[2], TRUE); return array; } /** * gi_marshalling_tests_return_gvalue_zero_terminated_array: * * Returns: (array zero-terminated) (transfer full): a flat GValue array */ GValue * gi_marshalling_tests_return_gvalue_zero_terminated_array (void) { GValue *array = g_new0 (GValue, 4); g_value_init (&array[0], G_TYPE_INT); g_value_set_int (&array[0], 42); g_value_init (&array[1], G_TYPE_STRING); g_value_set_static_string (&array[1], "42"); g_value_init (&array[2], G_TYPE_BOOLEAN); g_value_set_boolean (&array[2], TRUE); return array; } /** * gi_marshalling_tests_gvalue_round_trip: * @value: The first GValue * * Returns: (transfer none): */ GValue * gi_marshalling_tests_gvalue_round_trip (GValue *value) { return value; } /** * gi_marshalling_tests_gvalue_copy: * @value: The first GValue * * Returns: (transfer full): */ GValue * gi_marshalling_tests_gvalue_copy (GValue *value) { GValue *return_value = g_new0 (GValue, 1); g_value_init (return_value, G_VALUE_TYPE (value)); g_value_copy (value, return_value); return return_value; } /** * gi_marshalling_tests_gvalue_flat_array_round_trip: * @one: The first GValue * @two: The second GValue * @three: The third GValue * * Returns: (array fixed-size=3) (transfer full): a flat array of [@one, @two, @three] */ GValue * gi_marshalling_tests_gvalue_flat_array_round_trip (const GValue one, const GValue two, const GValue three) { GValue *array = g_new (GValue, 3); array[0] = one; array[1] = two; array[2] = three; return array; } /** * gi_marshalling_tests_gvalue_float: * @float_value: A G_TYPE_FLOAT GValue * @double_value: A G_TYPE_DOUBLE GValue */ void gi_marshalling_tests_gvalue_float (const GValue *float_value, const GValue *double_value) { g_assert_cmpfloat_with_epsilon (g_value_get_float (float_value), 3.14, 0.001); g_assert_cmpfloat_with_epsilon (g_value_get_double (double_value), 3.14, 0.001); } /** * gi_marshalling_tests_gclosure_in: * @closure: (transfer none): */ void gi_marshalling_tests_gclosure_in (GClosure *closure) { GValue return_value = { 0, }; g_value_init (&return_value, G_TYPE_INT); g_closure_invoke (closure, &return_value, 0, NULL, NULL); g_assert_cmpint (g_value_get_int (&return_value), ==, 42); g_value_unset (&return_value); } static gint _closure_return_42 (void) { return 42; } static void _marshal_INT__VOID (GClosure *closure, GValue *return_value, guint n_param_values G_GNUC_UNUSED, const GValue *param_values G_GNUC_UNUSED, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data G_GNUC_UNUSED) { typedef gint (*GMarshalFunc_INT__VOID) (void); register GMarshalFunc_INT__VOID callback; register GCClosure *cc = (GCClosure *) closure; callback = (GMarshalFunc_INT__VOID) cc->callback; g_value_set_int (return_value, callback ()); } /** * gi_marshalling_tests_gclosure_return: * * Return: a #GClosure */ GClosure * gi_marshalling_tests_gclosure_return (void) { GClosure *closure = g_cclosure_new ((GCallback) _closure_return_42, NULL, NULL); g_closure_set_marshal (closure, _marshal_INT__VOID); return closure; } /** * gi_marshalling_tests_callback_return_value_only: * @callback: (scope call): */ glong gi_marshalling_tests_callback_return_value_only (GIMarshallingTestsCallbackReturnValueOnly callback) { return callback (); } /** * gi_marshalling_tests_callback_one_out_parameter: * @callback: (scope call): * @a: (out): */ void gi_marshalling_tests_callback_one_out_parameter (GIMarshallingTestsCallbackOneOutParameter callback, gfloat *a) { callback (a); } /** * gi_marshalling_tests_callback_multiple_out_parameters: * @callback: (scope call): * @a: (out): * @b: (out): */ void gi_marshalling_tests_callback_multiple_out_parameters (GIMarshallingTestsCallbackMultipleOutParameters callback, gfloat *a, gfloat *b) { callback (a, b); } /** * gi_marshalling_tests_callback_return_value_and_one_out_parameter: * @callback: (scope call): * @a: (out): */ glong gi_marshalling_tests_callback_return_value_and_one_out_parameter (GIMarshallingTestsCallbackReturnValueAndOneOutParameter callback, glong *a) { return callback (a); } /** * gi_marshalling_tests_callback_return_value_and_multiple_out_parameters: * @callback: (scope call): * @a: (out): * @b: (out): */ glong gi_marshalling_tests_callback_return_value_and_multiple_out_parameters (GIMarshallingTestsCallbackReturnValueAndMultipleOutParameters callback, glong *a, glong *b) { return callback (a, b); } /** * gi_marshalling_tests_pointer_in_return: * * Returns: The same pointer */ gpointer gi_marshalling_tests_pointer_in_return (gpointer pointer) { return pointer; } GType gi_marshalling_tests_genum_get_type (void) { static GType type = 0; if (G_UNLIKELY (type == 0)) { static const GEnumValue values[] = { { GI_MARSHALLING_TESTS_GENUM_VALUE1, "GI_MARSHALLING_TESTS_GENUM_VALUE1", "value1" }, { GI_MARSHALLING_TESTS_GENUM_VALUE2, "GI_MARSHALLING_TESTS_GENUM_VALUE2", "value2" }, { GI_MARSHALLING_TESTS_GENUM_VALUE3, "GI_MARSHALLING_TESTS_GENUM_VALUE3", "value3" }, { 0, NULL, NULL } }; type = g_enum_register_static (g_intern_static_string ("GIMarshallingTestsGEnum"), values); } return type; } GIMarshallingTestsGEnum gi_marshalling_tests_genum_returnv (void) { return GI_MARSHALLING_TESTS_GENUM_VALUE3; } void gi_marshalling_tests_genum_in (GIMarshallingTestsGEnum v) { g_assert_cmpint (v, ==, GI_MARSHALLING_TESTS_GENUM_VALUE3); } /** * gi_marshalling_tests_genum_out: * @v: (out): */ void gi_marshalling_tests_genum_out (GIMarshallingTestsGEnum *v) { *v = GI_MARSHALLING_TESTS_GENUM_VALUE3; } /** * gi_marshalling_tests_genum_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_genum_out_uninitialized (GIMarshallingTestsGEnum *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_genum_inout: * @v: (inout): */ void gi_marshalling_tests_genum_inout (GIMarshallingTestsGEnum *v) { g_assert_cmpint (*v, ==, GI_MARSHALLING_TESTS_GENUM_VALUE3); *v = GI_MARSHALLING_TESTS_GENUM_VALUE1; } GIMarshallingTestsEnum gi_marshalling_tests_enum_returnv (void) { return GI_MARSHALLING_TESTS_ENUM_VALUE3; } void gi_marshalling_tests_enum_in (GIMarshallingTestsEnum v) { g_assert_cmpint (v, ==, GI_MARSHALLING_TESTS_ENUM_VALUE3); } /** * gi_marshalling_tests_enum_out: * @v: (out): */ void gi_marshalling_tests_enum_out (GIMarshallingTestsEnum *v) { *v = GI_MARSHALLING_TESTS_ENUM_VALUE3; } /** * gi_marshalling_tests_enum_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_enum_out_uninitialized (GIMarshallingTestsEnum **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_enum_inout: * @v: (inout): */ void gi_marshalling_tests_enum_inout (GIMarshallingTestsEnum *v) { g_assert_cmpint (*v, ==, GI_MARSHALLING_TESTS_ENUM_VALUE3); *v = GI_MARSHALLING_TESTS_ENUM_VALUE1; } GType gi_marshalling_tests_flags_get_type (void) { static GType type = 0; if (G_UNLIKELY (type == 0)) { static const GFlagsValue values[] = { { GI_MARSHALLING_TESTS_FLAGS_VALUE1, "GI_MARSHALLING_TESTS_FLAGS_VALUE1", "value1" }, { GI_MARSHALLING_TESTS_FLAGS_VALUE2, "GI_MARSHALLING_TESTS_FLAGS_VALUE2", "value2" }, { GI_MARSHALLING_TESTS_FLAGS_VALUE3, "GI_MARSHALLING_TESTS_FLAGS_VALUE3", "value3" }, { GI_MARSHALLING_TESTS_FLAGS_MASK, "GI_MARSHALLING_TESTS_FLAGS_MASK", "mask" }, { GI_MARSHALLING_TESTS_FLAGS_MASK2, "GI_MARSHALLING_TESTS_FLAGS_MASK2", "mask2" }, { 0, NULL, NULL } }; type = g_flags_register_static (g_intern_static_string ("GIMarshallingTestsFlags"), values); } return type; } GIMarshallingTestsFlags gi_marshalling_tests_flags_returnv (void) { return GI_MARSHALLING_TESTS_FLAGS_VALUE2; } void gi_marshalling_tests_flags_in (GIMarshallingTestsFlags v) { g_assert (v == GI_MARSHALLING_TESTS_FLAGS_VALUE2); } void gi_marshalling_tests_flags_in_zero (GIMarshallingTestsFlags v) { g_assert (v == 0); } /** * gi_marshalling_tests_flags_out: * @v: (out): */ void gi_marshalling_tests_flags_out (GIMarshallingTestsFlags *v) { *v = GI_MARSHALLING_TESTS_FLAGS_VALUE2; } /** * gi_marshalling_tests_flags_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_flags_out_uninitialized (GIMarshallingTestsFlags *v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_flags_inout: * @v: (inout): */ void gi_marshalling_tests_flags_inout (GIMarshallingTestsFlags *v) { g_assert (*v == GI_MARSHALLING_TESTS_FLAGS_VALUE2); *v = GI_MARSHALLING_TESTS_FLAGS_VALUE1; } GIMarshallingTestsNoTypeFlags gi_marshalling_tests_no_type_flags_returnv (void) { return GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_VALUE2; } void gi_marshalling_tests_no_type_flags_in (GIMarshallingTestsNoTypeFlags v) { g_assert (v == GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_VALUE2); } void gi_marshalling_tests_no_type_flags_in_zero (GIMarshallingTestsNoTypeFlags v) { g_assert (v == 0); } /** * gi_marshalling_tests_no_type_flags_out: * @v: (out): */ void gi_marshalling_tests_no_type_flags_out (GIMarshallingTestsNoTypeFlags *v) { *v = GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_VALUE2; } /** * gi_marshalling_tests_no_type_flags_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_no_type_flags_out_uninitialized (GIMarshallingTestsNoTypeFlags **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_no_type_flags_inout: * @v: (inout): */ void gi_marshalling_tests_no_type_flags_inout (GIMarshallingTestsNoTypeFlags *v) { g_assert (*v == GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_VALUE2); *v = GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_VALUE1; } /** * gi_marshalling_tests_simple_struct_returnv: * * Returns: (transfer none): */ GIMarshallingTestsSimpleStruct * gi_marshalling_tests_simple_struct_returnv (void) { static GIMarshallingTestsSimpleStruct *struct_ = NULL; if (struct_ == NULL) { struct_ = g_new (GIMarshallingTestsSimpleStruct, 1); struct_->long_ = 6; struct_->int8 = 7; } return struct_; } /** * gi_marshalling_tests_simple_struct_inv: * @struct_: (transfer none): */ void gi_marshalling_tests_simple_struct_inv (GIMarshallingTestsSimpleStruct *struct_) { g_assert_cmpint (struct_->long_, ==, 6); g_assert_cmpint (struct_->int8, ==, 7); } void gi_marshalling_tests_simple_struct_method (GIMarshallingTestsSimpleStruct *struct_) { g_assert_cmpint (struct_->long_, ==, 6); g_assert_cmpint (struct_->int8, ==, 7); } GType gi_marshalling_tests_pointer_struct_get_type (void) { static GType type = 0; if (type == 0) { type = g_pointer_type_register_static ("GIMarshallingTestsPointerStruct"); } return type; } /** * gi_marshalling_tests_pointer_struct_returnv: * * Returns: (transfer none): */ GIMarshallingTestsPointerStruct * gi_marshalling_tests_pointer_struct_returnv (void) { static GIMarshallingTestsPointerStruct *struct_ = NULL; if (struct_ == NULL) { struct_ = g_new (GIMarshallingTestsPointerStruct, 1); struct_->long_ = 42; } return struct_; } /** * gi_marshalling_tests_pointer_struct_inv: * @struct_: (transfer none): */ void gi_marshalling_tests_pointer_struct_inv (GIMarshallingTestsPointerStruct *struct_) { g_assert_cmpint (struct_->long_, ==, 42); } static GIMarshallingTestsBoxedStruct * gi_marshalling_tests_boxed_struct_copy (GIMarshallingTestsBoxedStruct *struct_) { GIMarshallingTestsBoxedStruct *new_struct; if (struct_ == NULL) return NULL; new_struct = g_slice_new (GIMarshallingTestsBoxedStruct); *new_struct = *struct_; new_struct->string_ = g_strdup (struct_->string_); new_struct->g_strv = g_strdupv (struct_->g_strv); return new_struct; } static void gi_marshalling_tests_boxed_struct_free (GIMarshallingTestsBoxedStruct *struct_) { if (struct_ != NULL) { g_free (struct_->string_); g_clear_pointer (&struct_->g_strv, g_strfreev); g_slice_free (GIMarshallingTestsBoxedStruct, struct_); } } GType gi_marshalling_tests_boxed_struct_get_type (void) { static GType type = 0; if (type == 0) { type = g_boxed_type_register_static ("GIMarshallingTestsBoxedStruct", (GBoxedCopyFunc) gi_marshalling_tests_boxed_struct_copy, (GBoxedFreeFunc) gi_marshalling_tests_boxed_struct_free); } return type; } static GType gi_marshalling_tests_boxed_glist_get_type (void) { static GType type = 0; if (type == 0) { type = g_boxed_type_register_static ("GIMarshallingTestsBoxedGList", (GBoxedCopyFunc) g_list_copy, (GBoxedFreeFunc) g_list_free); } return type; } GIMarshallingTestsBoxedStruct * gi_marshalling_tests_boxed_struct_new (void) { return g_slice_new0 (GIMarshallingTestsBoxedStruct); } /** * gi_marshalling_tests_boxed_struct_returnv: * * Returns: (transfer none): */ GIMarshallingTestsBoxedStruct * gi_marshalling_tests_boxed_struct_returnv (void) { static GIMarshallingTestsBoxedStruct *struct_ = NULL; if (struct_ == NULL) { struct_ = g_new (GIMarshallingTestsBoxedStruct, 1); struct_->long_ = 42; struct_->string_ = g_strdup ("hello"); struct_->g_strv = g_new0 (gchar *, 4); struct_->g_strv[0] = g_strdup ("0"); struct_->g_strv[1] = g_strdup ("1"); struct_->g_strv[2] = g_strdup ("2"); struct_->g_strv[3] = NULL; } return struct_; } /** * gi_marshalling_tests_boxed_struct_inv: * @struct_: (transfer none): */ void gi_marshalling_tests_boxed_struct_inv (GIMarshallingTestsBoxedStruct *struct_) { g_assert_cmpint (struct_->long_, ==, 42); } /** * gi_marshalling_tests_boxed_struct_out: * @struct_: (out) (transfer none): */ void gi_marshalling_tests_boxed_struct_out (GIMarshallingTestsBoxedStruct **struct_) { static GIMarshallingTestsBoxedStruct *new_struct = NULL; if (new_struct == NULL) { new_struct = g_new0 (GIMarshallingTestsBoxedStruct, 1); new_struct->long_ = 42; } *struct_ = new_struct; } /** * gi_marshalling_tests_boxed_struct_out_uninitialized: * @v: (out) (transfer none): */ gboolean gi_marshalling_tests_boxed_struct_out_uninitialized (GIMarshallingTestsBoxedStruct **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_boxed_struct_inout: * @struct_: (inout) (transfer full): */ void gi_marshalling_tests_boxed_struct_inout (GIMarshallingTestsBoxedStruct **struct_) { g_assert_cmpint ((*struct_)->long_, ==, 42); g_boxed_free (gi_marshalling_tests_boxed_struct_get_type (), *struct_); (*struct_) = g_slice_new0 (GIMarshallingTestsBoxedStruct); (*struct_)->long_ = 0; } static GIMarshallingTestsUnion * gi_marshalling_tests_union_copy (GIMarshallingTestsUnion *union_) { GIMarshallingTestsUnion *new_union; new_union = g_slice_new (GIMarshallingTestsUnion); *new_union = *union_; return new_union; } static void gi_marshalling_tests_union_free (GIMarshallingTestsUnion *union_) { g_slice_free (GIMarshallingTestsUnion, union_); } GType gi_marshalling_tests_union_get_type (void) { static GType type = 0; if (type == 0) { type = g_boxed_type_register_static ("GIMarshallingTestsUnion", (GBoxedCopyFunc) gi_marshalling_tests_union_copy, (GBoxedFreeFunc) gi_marshalling_tests_union_free); } return type; } /** * gi_marshalling_tests_union_returnv: * * Returns: (transfer none): */ GIMarshallingTestsUnion * gi_marshalling_tests_union_returnv (void) { static GIMarshallingTestsUnion *union_ = NULL; if (union_ == NULL) { union_ = g_new (GIMarshallingTestsUnion, 1); union_->long_ = 42; } return union_; } /** * gi_marshalling_tests_union_inv: * @union_: (transfer none): */ void gi_marshalling_tests_union_inv (GIMarshallingTestsUnion *union_) { g_assert_cmpint (union_->long_, ==, 42); } void gi_marshalling_tests_union_method (GIMarshallingTestsUnion *union_) { g_assert_cmpint (union_->long_, ==, 42); } /** * gi_marshalling_tests_structured_union_new: * @type: Type of #GIMarshallingTestsStructuredUnion to create */ GIMarshallingTestsStructuredUnion * gi_marshalling_tests_structured_union_new (GIMarshallingTestsStructuredUnionType type) { GIMarshallingTestsStructuredUnion *new_union; new_union = g_new0 (GIMarshallingTestsStructuredUnion, 1); new_union->type = type; switch (type) { case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_NONE: break; case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_SIMPLE_STRUCT: new_union->simple_struct.parent.long_ = 6; new_union->simple_struct.parent.int8 = 7; break; case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_NESTED_STRUCT: new_union->nested_struct.parent.simple_struct.long_ = 6; new_union->nested_struct.parent.simple_struct.int8 = 7; break; case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_BOXED_STRUCT: new_union->boxed_struct.parent.long_ = 42; new_union->boxed_struct.parent.string_ = g_strdup ("hello"); new_union->boxed_struct.parent.g_strv = g_new0 (gchar *, 4); new_union->boxed_struct.parent.g_strv[0] = g_strdup ("0"); new_union->boxed_struct.parent.g_strv[1] = g_strdup ("1"); new_union->boxed_struct.parent.g_strv[2] = g_strdup ("2"); new_union->boxed_struct.parent.g_strv[3] = NULL; break; case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_BOXED_STRUCT_PTR: new_union->boxed_struct_ptr.parent = g_boxed_copy ( gi_marshalling_tests_boxed_struct_get_type (), gi_marshalling_tests_boxed_struct_returnv ()); break; case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_POINTER_STRUCT: new_union->pointer_struct.parent.long_ = 42; break; case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_SINGLE_UNION: new_union->single_union.parent.union_.long_ = 42; break; default: g_free (new_union); g_return_val_if_reached (NULL); } return new_union; } static GIMarshallingTestsStructuredUnion * gi_marshalling_tests_structured_union_copy (GIMarshallingTestsStructuredUnion *union_) { GIMarshallingTestsStructuredUnion *new_union; new_union = g_new (GIMarshallingTestsStructuredUnion, 1); *new_union = *union_; switch (union_->type) { case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_BOXED_STRUCT: new_union->boxed_struct.parent.string_ = g_strdup (union_->boxed_struct.parent.string_); if (union_->boxed_struct.parent.g_strv) { guint length = g_strv_length (union_->boxed_struct.parent.g_strv); guint i; new_union->boxed_struct.parent.g_strv = g_new0 (gchar *, length + 1); for (i = 0; i < length; i++) new_union->boxed_struct.parent.g_strv[i] = g_strdup (union_->boxed_struct.parent.g_strv[i]); new_union->boxed_struct.parent.g_strv[i] = NULL; } break; case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_BOXED_STRUCT_PTR: new_union->boxed_struct_ptr.parent = g_boxed_copy ( gi_marshalling_tests_boxed_struct_get_type (), union_->boxed_struct_ptr.parent); break; case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_NONE: case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_SINGLE_UNION: case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_POINTER_STRUCT: case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_SIMPLE_STRUCT: case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_NESTED_STRUCT: break; default: g_return_val_if_reached (new_union); } return new_union; } static void gi_marshalling_tests_structured_union_free (GIMarshallingTestsStructuredUnion *union_) { switch (union_->type) { case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_BOXED_STRUCT: g_free (union_->boxed_struct.parent.string_); g_strfreev (union_->boxed_struct.parent.g_strv); break; case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_BOXED_STRUCT_PTR: g_boxed_free (gi_marshalling_tests_boxed_struct_get_type (), union_->boxed_struct_ptr.parent); break; case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_NONE: case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_SINGLE_UNION: case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_POINTER_STRUCT: case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_SIMPLE_STRUCT: case GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_NESTED_STRUCT: break; default: g_assert_not_reached (); } g_free (union_); } GType gi_marshalling_tests_structured_union_get_type (void) { static GType type = 0; if (type == 0) { type = g_boxed_type_register_static ("GIMarshallingTestsStructuredUnion", (GBoxedCopyFunc) gi_marshalling_tests_structured_union_copy, (GBoxedFreeFunc) gi_marshalling_tests_structured_union_free); } return type; } GIMarshallingTestsStructuredUnionType gi_marshalling_tests_structured_union_type (GIMarshallingTestsStructuredUnion *structured_union) { return structured_union->type; } enum { PROP_0, PROP_INT_ }; static void gi_marshalling_tests_object_real_method_with_default_implementation (GIMarshallingTestsObject *self, gint8 in); G_DEFINE_TYPE (GIMarshallingTestsObject, gi_marshalling_tests_object, G_TYPE_OBJECT); static void gi_marshalling_tests_object_init (GIMarshallingTestsObject *self G_GNUC_UNUSED) { } static void gi_marshalling_tests_object_finalize (GObject *object) { G_OBJECT_CLASS (gi_marshalling_tests_object_parent_class)->finalize (object); } static void gi_marshalling_tests_object_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { g_return_if_fail (GI_MARSHALLING_TESTS_IS_OBJECT (object)); switch (prop_id) { case PROP_INT_: GI_MARSHALLING_TESTS_OBJECT (object)->int_ = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gi_marshalling_tests_object_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { g_return_if_fail (GI_MARSHALLING_TESTS_IS_OBJECT (object)); switch (prop_id) { case PROP_INT_: g_value_set_int (value, GI_MARSHALLING_TESTS_OBJECT (object)->int_); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gi_marshalling_tests_object_class_init (GIMarshallingTestsObjectClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); #if 0 GObjectClass *parent_class = G_OBJECT_CLASS (klass); #endif object_class->finalize = gi_marshalling_tests_object_finalize; object_class->set_property = gi_marshalling_tests_object_set_property; object_class->get_property = gi_marshalling_tests_object_get_property; g_object_class_install_property (object_class, PROP_INT_, g_param_spec_int ("int", "Integer", "An integer", G_MININT, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); klass->method_with_default_implementation = gi_marshalling_tests_object_real_method_with_default_implementation; } void gi_marshalling_tests_object_static_method (void) { } void gi_marshalling_tests_object_method (GIMarshallingTestsObject *object) { g_return_if_fail (GI_MARSHALLING_TESTS_IS_OBJECT (object)); g_assert_cmpint (object->int_, ==, 42); } void gi_marshalling_tests_object_overridden_method (GIMarshallingTestsObject *object) { g_return_if_fail (GI_MARSHALLING_TESTS_IS_OBJECT (object)); g_assert_cmpint (object->int_, ==, 0); } GIMarshallingTestsObject * gi_marshalling_tests_object_new (gint int_) { return g_object_new (GI_MARSHALLING_TESTS_TYPE_OBJECT, "int", int_, NULL); } GIMarshallingTestsObject * gi_marshalling_tests_object_new_fail (gint int_ G_GNUC_UNUSED, GError **error) { g_return_val_if_fail (error == NULL || *error == NULL, NULL); g_set_error_literal (error, g_quark_from_static_string (GI_MARSHALLING_TESTS_CONSTANT_GERROR_DOMAIN), GI_MARSHALLING_TESTS_CONSTANT_GERROR_CODE, GI_MARSHALLING_TESTS_CONSTANT_GERROR_MESSAGE); return NULL; } /** * gi_marshalling_tests_object_method_array_in: * @ints: (array length=length): */ void gi_marshalling_tests_object_method_array_in (GIMarshallingTestsObject *self G_GNUC_UNUSED, const gint *ints, gint length) { g_assert_cmpint (length, ==, 4); g_assert_cmpint (ints[0], ==, -1); g_assert_cmpint (ints[1], ==, 0); g_assert_cmpint (ints[2], ==, 1); g_assert_cmpint (ints[3], ==, 2); } /** * gi_marshalling_tests_object_method_array_out: * @ints: (out) (array length=length) (transfer none): */ void gi_marshalling_tests_object_method_array_out (GIMarshallingTestsObject *self G_GNUC_UNUSED, gint **ints, gint *length) { static gint values[] = { -1, 0, 1, 2 }; *length = 4; *ints = values; } /** * gi_marshalling_tests_object_method_array_inout: * @ints: (inout) (array length=length) (transfer none): * @length: (inout): */ void gi_marshalling_tests_object_method_array_inout (GIMarshallingTestsObject *self G_GNUC_UNUSED, gint **ints, gint *length) { static gint values[] = { -2, -1, 0, 1, 2 }; g_assert_cmpint (*length, ==, 4); g_assert_cmpint ((*ints)[0], ==, -1); g_assert_cmpint ((*ints)[1], ==, 0); g_assert_cmpint ((*ints)[2], ==, 1); g_assert_cmpint ((*ints)[3], ==, 2); *length = 5; *ints = values; } /** * gi_marshalling_tests_object_method_array_return: * * Returns: (array length=length): */ const gint * gi_marshalling_tests_object_method_array_return (GIMarshallingTestsObject *self G_GNUC_UNUSED, gint *length) { static gint ints[] = { -1, 0, 1, 2 }; *length = 4; return ints; } /** * gi_marshalling_tests_object_method_int8_in: * @in: (in): */ void gi_marshalling_tests_object_method_int8_in (GIMarshallingTestsObject *self, gint8 in) { GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->method_int8_in (self, in); } /** * gi_marshalling_tests_object_method_int8_out: * @out: (out): */ void gi_marshalling_tests_object_method_int8_out (GIMarshallingTestsObject *self, gint8 *out) { GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->method_int8_out (self, out); } /** * gi_marshalling_tests_object_method_int8_arg_and_out_caller: * @out: (out): */ void gi_marshalling_tests_object_method_int8_arg_and_out_caller (GIMarshallingTestsObject *self, gint8 arg, gint8 *out) { GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->method_int8_arg_and_out_caller (self, arg, out); } /** * gi_marshalling_tests_object_method_int8_arg_and_out_callee: * @out: (out): */ void gi_marshalling_tests_object_method_int8_arg_and_out_callee (GIMarshallingTestsObject *self, gint8 arg, gint8 **out) { GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->method_int8_arg_and_out_callee (self, arg, out); } /** * gi_marshalling_tests_object_method_str_arg_out_ret: * @out: (out): * * Returns: (transfer none) */ const gchar * gi_marshalling_tests_object_method_str_arg_out_ret (GIMarshallingTestsObject *self, const gchar *arg, guint *out) { return GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->method_str_arg_out_ret (self, arg, out); } /** * gi_marshalling_tests_object_method_with_default_implementation: * @in: (in): */ void gi_marshalling_tests_object_method_with_default_implementation (GIMarshallingTestsObject *self, gint8 in) { GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->method_with_default_implementation (self, in); } static void gi_marshalling_tests_object_real_method_with_default_implementation (GIMarshallingTestsObject *self, gint8 in) { GValue val = { 0, }; g_value_init (&val, G_TYPE_INT); g_value_set_int (&val, in); g_object_set_property (G_OBJECT (self), "int", &val); } /** * gi_marshalling_tests_object_vfunc_with_callback: (virtual vfunc_with_callback) * @callback: (scope call) (closure callback_data): * @callback_data: (allow-none): */ void gi_marshalling_tests_object_vfunc_with_callback (GIMarshallingTestsObject *self G_GNUC_UNUSED, GIMarshallingTestsCallbackIntInt callback G_GNUC_UNUSED, void *callback_data G_GNUC_UNUSED) { } static int _callback (int val, void *user_data) { g_assert (user_data == (gpointer) 0xdeadbeef); return val; } void gi_marshalling_tests_object_call_vfunc_with_callback (GIMarshallingTestsObject *object) { GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (object)->vfunc_with_callback (object, _callback, (void *) 0xdeadbeef); } /** * gi_marshalling_tests_object_none_return: * * Returns: (transfer none): */ GIMarshallingTestsObject * gi_marshalling_tests_object_none_return (void) { static GIMarshallingTestsObject *object = NULL; if (object == NULL) { object = g_object_new (GI_MARSHALLING_TESTS_TYPE_OBJECT, NULL); } return object; } /** * gi_marshalling_tests_object_full_return: * * Returns: (transfer full): */ GIMarshallingTestsObject * gi_marshalling_tests_object_full_return (void) { return g_object_new (GI_MARSHALLING_TESTS_TYPE_OBJECT, NULL); } /** * gi_marshalling_tests_object_none_in: * @object: (transfer none): */ void gi_marshalling_tests_object_none_in (GIMarshallingTestsObject *object) { g_assert_cmpint (object->int_, ==, 42); } /** * gi_marshalling_tests_object_none_out: * @object: (out) (transfer none): */ void gi_marshalling_tests_object_none_out (GIMarshallingTestsObject **object) { static GIMarshallingTestsObject *new_object = NULL; if (new_object == NULL) { new_object = g_object_new (GI_MARSHALLING_TESTS_TYPE_OBJECT, NULL); } *object = new_object; } /** * gi_marshalling_tests_object_none_out_uninitialized: * @v: (out) (transfer none): */ gboolean gi_marshalling_tests_object_none_out_uninitialized (GIMarshallingTestsObject **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_object_full_out: * @object: (out) (transfer full): */ void gi_marshalling_tests_object_full_out (GIMarshallingTestsObject **object) { *object = g_object_new (GI_MARSHALLING_TESTS_TYPE_OBJECT, NULL); } /** * gi_marshalling_tests_object_full_out_uninitialized: * @v: (out) (transfer full): */ gboolean gi_marshalling_tests_object_full_out_uninitialized (GIMarshallingTestsObject **v G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_object_none_inout: * @object: (inout) (transfer none): */ void gi_marshalling_tests_object_none_inout (GIMarshallingTestsObject **object) { static GIMarshallingTestsObject *new_object = NULL; g_assert_cmpint ((*object)->int_, ==, 42); if (new_object == NULL) { new_object = g_object_new (GI_MARSHALLING_TESTS_TYPE_OBJECT, NULL); new_object->int_ = 0; } *object = new_object; } /** * gi_marshalling_tests_object_full_inout: * @object: (inout) (transfer full): */ void gi_marshalling_tests_object_full_inout (GIMarshallingTestsObject **object) { g_assert_cmpint ((*object)->int_, ==, 42); g_object_unref (*object); *object = g_object_new (GI_MARSHALLING_TESTS_TYPE_OBJECT, NULL); } /** * gi_marshalling_tests_object_int8_in: * @in: (in): */ void gi_marshalling_tests_object_int8_in (GIMarshallingTestsObject *object, gint8 in) { gi_marshalling_tests_object_method_int8_in (object, in); } /** * gi_marshalling_tests_object_int8_out: * @out: (out): */ void gi_marshalling_tests_object_int8_out (GIMarshallingTestsObject *object, gint8 *out) { gi_marshalling_tests_object_method_int8_out (object, out); } /** * gi_marshalling_tests_object_vfunc_return_value_only: */ glong gi_marshalling_tests_object_vfunc_return_value_only (GIMarshallingTestsObject *self) { /* make sure that local variables don't get smashed */ glong return_value; gulong local = 0x12345678; return_value = GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_return_value_only (self); g_assert_cmpint (local, ==, 0x12345678); return return_value; } /** * gi_marshalling_tests_object_vfunc_one_out_parameter: * @a: (out): */ void gi_marshalling_tests_object_vfunc_one_out_parameter (GIMarshallingTestsObject *self, gfloat *a) { /* make sure that local variables don't get smashed */ gulong local = 0x12345678; GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_one_out_parameter (self, a); g_assert_cmpint (local, ==, 0x12345678); } /** * gi_marshalling_tests_object_vfunc_one_inout_parameter: * @a: (inout): */ void gi_marshalling_tests_object_vfunc_one_inout_parameter (GIMarshallingTestsObject *self, gfloat *a) { /* make sure that local variables don't get smashed */ gulong local = 0x12345678; GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_one_inout_parameter (self, a); g_assert_cmpint (local, ==, 0x12345678); } /** * gi_marshalling_tests_object_vfunc_multiple_inout_parameters: * @a: (inout): * @b: (inout): */ void gi_marshalling_tests_object_vfunc_multiple_inout_parameters (GIMarshallingTestsObject *self, gfloat *a, gfloat *b) { /* make sure that local variables don't get smashed */ gulong local = 0x12345678; GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_multiple_inout_parameters (self, a, b); g_assert_cmpint (local, ==, 0x12345678); } /** * gi_marshalling_tests_object_vfunc_multiple_out_parameters: * @a: (out): * @b: (out): */ void gi_marshalling_tests_object_vfunc_multiple_out_parameters (GIMarshallingTestsObject *self, gfloat *a, gfloat *b) { /* make sure that local variables don't get smashed */ gulong local = 0x12345678; GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_multiple_out_parameters (self, a, b); g_assert_cmpint (local, ==, 0x12345678); } /** * gi_marshalling_tests_object_vfunc_caller_allocated_out_parameter: * @a: (out): */ void gi_marshalling_tests_object_vfunc_caller_allocated_out_parameter (GIMarshallingTestsObject *self, GValue *a) { /* make sure that local variables don't get smashed */ gulong local = 0x12345678; GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_caller_allocated_out_parameter (self, a); g_assert_cmpint (local, ==, 0x12345678); } /** * gi_marshalling_tests_object_vfunc_array_out_parameter: * @a: (out) (array zero-terminated): */ void gi_marshalling_tests_object_vfunc_array_out_parameter (GIMarshallingTestsObject *self, gfloat **a) { /* make sure that local variables don't get smashed */ gulong local = 0x12345678; GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_array_out_parameter (self, a); g_assert_cmpint (local, ==, 0x12345678); } /** * gi_marshalling_tests_object_vfunc_return_value_and_one_out_parameter: * @a: (out): */ glong gi_marshalling_tests_object_vfunc_return_value_and_one_out_parameter (GIMarshallingTestsObject *self, glong *a) { /* make sure that local variables don't get smashed */ gulong return_value; gulong local = 0x12345678; return_value = GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_return_value_and_one_out_parameter (self, a); g_assert_cmpint (local, ==, 0x12345678); return return_value; } /** * gi_marshalling_tests_object_vfunc_return_value_and_multiple_out_parameters: * @a: (out): * @b: (out): */ glong gi_marshalling_tests_object_vfunc_return_value_and_multiple_out_parameters (GIMarshallingTestsObject *self, glong *a, glong *b) { gulong return_value; gulong local = 0x12345678; return_value = GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_return_value_and_multiple_out_parameters (self, a, b); g_assert_cmpint (local, ==, 0x12345678); return return_value; } /** * gi_marshalling_tests_object_vfunc_return_value_and_one_inout_parameter: * @a: (inout): */ glong gi_marshalling_tests_object_vfunc_return_value_and_one_inout_parameter (GIMarshallingTestsObject *self, glong *a) { /* make sure that local variables don't get smashed */ gulong return_value; gulong local = 0x12345678; return_value = GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_return_value_and_one_inout_parameter (self, a); g_assert_cmpint (local, ==, 0x12345678); return return_value; } /** * gi_marshalling_tests_object_vfunc_return_value_and_multiple_inout_parameters: * @a: (inout): * @b: (inout): */ glong gi_marshalling_tests_object_vfunc_return_value_and_multiple_inout_parameters (GIMarshallingTestsObject *self, glong *a, glong *b) { gulong return_value; gulong local = 0x12345678; return_value = GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_return_value_and_multiple_inout_parameters (self, a, b); g_assert_cmpint (local, ==, 0x12345678); return return_value; } /** * gi_marshalling_tests_callback_owned_boxed: * @callback: (scope call) (closure callback_data): * @callback_data: (allow-none): */ glong gi_marshalling_tests_callback_owned_boxed (GIMarshallingTestsCallbackOwnedBoxed callback, void *callback_data) { static GIMarshallingTestsBoxedStruct *box = NULL; glong ret; if (!box) box = gi_marshalling_tests_boxed_struct_new (); box->long_++; callback (box, callback_data); ret = box->long_; return ret; } gboolean gi_marshalling_tests_object_vfunc_meth_with_error (GIMarshallingTestsObject *self, gint x, GError **error) { gulong local = 0x12345678; gboolean ret = GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_meth_with_err (self, x, error); g_assert_cmpint (local, ==, 0x12345678); return ret; } /** * gi_marshalling_tests_object_vfunc_return_enum: */ GIMarshallingTestsEnum gi_marshalling_tests_object_vfunc_return_enum (GIMarshallingTestsObject *self) { /* make sure that local variables don't get smashed */ GIMarshallingTestsEnum return_value; glong local = 0x12345678; return_value = GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_return_enum (self); g_assert_cmpint (local, ==, 0x12345678); return return_value; } /** * gi_marshalling_tests_object_vfunc_out_enum: * @_enum: (out): */ void gi_marshalling_tests_object_vfunc_out_enum (GIMarshallingTestsObject *self, GIMarshallingTestsEnum *_enum) { /* make sure that local variables don't get smashed */ gulong local = 0x12345678; GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_out_enum (self, _enum); g_assert_cmpint (local, ==, 0x12345678); } /** * gi_marshalling_tests_object_vfunc_return_flags: */ GIMarshallingTestsFlags gi_marshalling_tests_object_vfunc_return_flags (GIMarshallingTestsObject *self) { /* make sure that local variables don't get smashed */ GIMarshallingTestsFlags return_value; glong local = 0x12345678; return_value = GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_return_flags (self); g_assert_cmpint (local, ==, 0x12345678); return return_value; } /** * gi_marshalling_tests_object_vfunc_static_name: */ gchar * gi_marshalling_tests_object_vfunc_static_name (void) { GIMarshallingTestsObjectClass *klass; klass = g_type_class_peek_static (GI_MARSHALLING_TESTS_TYPE_OBJECT); if (klass->vfunc_static_name) return klass->vfunc_static_name (); return g_strdup (g_type_name (GI_MARSHALLING_TESTS_TYPE_OBJECT)); } /** * gi_marshalling_tests_object_vfunc_static_typed_name: * @gtype: */ gchar * gi_marshalling_tests_object_vfunc_static_typed_name (GType gtype) { GIMarshallingTestsObjectClass *klass; g_return_val_if_fail (g_type_is_a (gtype, GI_MARSHALLING_TESTS_TYPE_OBJECT), NULL); klass = g_type_class_peek_static (gtype); if (klass->vfunc_static_name) return klass->vfunc_static_name (); return g_strdup (g_type_name (GI_MARSHALLING_TESTS_TYPE_OBJECT)); } /** * gi_marshalling_tests_object_vfunc_static_create_new: * @gtype: * @int_: */ GIMarshallingTestsObject * gi_marshalling_tests_object_vfunc_static_create_new (GType gtype, gint int_) { GIMarshallingTestsObjectClass *klass; g_return_val_if_fail (g_type_is_a (gtype, GI_MARSHALLING_TESTS_TYPE_OBJECT), NULL); klass = g_type_class_peek (gtype); if (klass->vfunc_static_create_new) return klass->vfunc_static_create_new (int_); return gi_marshalling_tests_object_new (int_); } /** * gi_marshalling_tests_object_vfunc_static_create_new_out: * @out: (out): We keep this as first parameter to ensure it's parsed properly * @gtype: * @int_: */ void gi_marshalling_tests_object_vfunc_static_create_new_out (GIMarshallingTestsObject **out, GType gtype, gint int_) { GIMarshallingTestsObjectClass *klass; g_return_if_fail (g_type_is_a (gtype, GI_MARSHALLING_TESTS_TYPE_OBJECT)); klass = g_type_class_peek (gtype); if (klass->vfunc_static_create_new_out) return klass->vfunc_static_create_new_out (out, int_); *out = gi_marshalling_tests_object_new (int_); } /** * gi_marshalling_tests_object_vfunc_out_flags: * @flags: (out): */ void gi_marshalling_tests_object_vfunc_out_flags (GIMarshallingTestsObject *self, GIMarshallingTestsFlags *flags) { /* make sure that local variables don't get smashed */ gulong local = 0x12345678; GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_out_flags (self, flags); g_assert_cmpuint (local, ==, 0x12345678); } /* NOTE: * * The following (get_ref_info_for_*) methods are designed to call vfuncs related * to object argument marshaling. They do not pass the resulting objects through them * as regular vfunc wrapper method do, but rather return reference count and floating * information back to the callers. This is useful because callers can do testing of * expected reference counts in isolation and from the perspective of C. This is important * because if there are bugs in the reverse marshaling, they can obfuscate or compound * bugs in marshaling from the vfuncs. */ /** * gi_marshalling_tests_object_get_ref_info_for_vfunc_return_object_transfer_none: * @ref_count: (out): Ref count of the object returned from the vfunc directly after vfunc call. * @is_floating: (out): Floating state object returned from the vfunc directly after vfunc call. */ void gi_marshalling_tests_object_get_ref_info_for_vfunc_return_object_transfer_none (GIMarshallingTestsObject *self, guint *ref_count, gboolean *is_floating) { GObject *object = GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_return_object_transfer_none (self); *ref_count = object->ref_count; *is_floating = g_object_is_floating (object); /* Attempt to sink and unref the returned object and avoid any potential leaks */ g_object_ref_sink (object); g_object_unref (object); } /** * gi_marshalling_tests_object_get_ref_info_for_vfunc_return_object_transfer_full: * @ref_count: (out): Ref count of the object returned from the vfunc directly after vfunc call. * @is_floating: (out): Floating state object returned from the vfunc directly after vfunc call. */ void gi_marshalling_tests_object_get_ref_info_for_vfunc_return_object_transfer_full (GIMarshallingTestsObject *self, guint *ref_count, gboolean *is_floating) { GObject *object = GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_return_object_transfer_full (self); *ref_count = object->ref_count; *is_floating = g_object_is_floating (object); g_object_unref (object); } /** * gi_marshalling_tests_object_get_ref_info_for_vfunc_out_object_transfer_none: * @ref_count: (out): Ref count of the object returned from the vfunc directly after vfunc call. * @is_floating: (out): Floating state object returned from the vfunc directly after vfunc call. */ void gi_marshalling_tests_object_get_ref_info_for_vfunc_out_object_transfer_none (GIMarshallingTestsObject *self, guint *ref_count, gboolean *is_floating) { GObject *object = NULL; GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_out_object_transfer_none (self, &object); *ref_count = object->ref_count; *is_floating = g_object_is_floating (object); /* Attempt to sink and unref the returned object and avoid any potential leaks */ g_object_ref_sink (object); g_object_unref (object); } /** * gi_marshalling_tests_object_get_ref_info_for_vfunc_out_object_transfer_full: * @ref_count: (out): Ref count of the object returned from the vfunc directly after vfunc call. * @is_floating: (out): Floating state object returned from the vfunc directly after vfunc call. */ void gi_marshalling_tests_object_get_ref_info_for_vfunc_out_object_transfer_full (GIMarshallingTestsObject *self, guint *ref_count, gboolean *is_floating) { GObject *object = NULL; GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_out_object_transfer_full (self, &object); *ref_count = object->ref_count; *is_floating = g_object_is_floating (object); g_object_unref (object); } static void _vfunc_in_object_destroy_callback (gboolean *destroy_called, GObject *where_the_object_was G_GNUC_UNUSED) { *destroy_called = TRUE; } /** * gi_marshalling_tests_object_get_ref_info_for_vfunc_in_object_transfer_none: * @type: GType of object to create and pass as in argument to the vfunc * @ref_count: (out): Ref count of the in object directly after vfunc call. * @is_floating: (out): Floating state of in object directly after vfunc call. * * Calls vfunc_in_object_transfer_none with a new object of the given type. */ void gi_marshalling_tests_object_get_ref_info_for_vfunc_in_object_transfer_none (GIMarshallingTestsObject *self, GType type, guint *ref_count, gboolean *is_floating) { static gboolean destroy_called; GObject *object; destroy_called = FALSE; object = g_object_new (type, NULL); g_object_weak_ref (object, (GWeakNotify) _vfunc_in_object_destroy_callback, &destroy_called); GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_in_object_transfer_none (self, object); if (destroy_called) { *ref_count = 0; *is_floating = FALSE; } else { *ref_count = object->ref_count; *is_floating = g_object_is_floating (object); g_object_unref (object); } } /** * gi_marshalling_tests_object_get_ref_info_for_vfunc_in_object_transfer_full: * @type: GType of object to create and pass as in argument to the vfunc * @ref_count: (out): Ref count of the in object directly after vfunc call. * @is_floating: (out): Floating state of in object directly after vfunc call. */ void gi_marshalling_tests_object_get_ref_info_for_vfunc_in_object_transfer_full (GIMarshallingTestsObject *self, GType type, guint *ref_count, gboolean *is_floating) { static gboolean destroy_called; GObject *object; destroy_called = FALSE; object = g_object_new (type, NULL); g_object_weak_ref (object, (GWeakNotify) _vfunc_in_object_destroy_callback, &destroy_called); /* Calling the vfunc takes ownership of the object, so we use a weak_ref to determine * if the object gets destroyed after the call and appropriately return 0 as the ref count. */ GI_MARSHALLING_TESTS_OBJECT_GET_CLASS (self)->vfunc_in_object_transfer_full (self, object); if (destroy_called) { *ref_count = 0; *is_floating = FALSE; } else { *ref_count = object->ref_count; *is_floating = g_object_is_floating (object); } } G_DEFINE_TYPE (GIMarshallingTestsSubObject, gi_marshalling_tests_sub_object, GI_MARSHALLING_TESTS_TYPE_OBJECT); static void gi_marshalling_tests_sub_object_init (GIMarshallingTestsSubObject *self G_GNUC_UNUSED) { } static void gi_marshalling_tests_sub_object_finalize (GObject *object) { G_OBJECT_CLASS (gi_marshalling_tests_sub_object_parent_class)->finalize (object); } static void method_deep_hierarchy (GIMarshallingTestsObject *self, gint8 in) { GValue val = { 0, }; g_value_init (&val, G_TYPE_INT); g_value_set_int (&val, in); g_object_set_property (G_OBJECT (self), "int", &val); } static void gi_marshalling_tests_sub_object_class_init (GIMarshallingTestsSubObjectClass *klass) { G_OBJECT_CLASS (klass)->finalize = gi_marshalling_tests_sub_object_finalize; GI_MARSHALLING_TESTS_OBJECT_CLASS (klass)->method_deep_hierarchy = method_deep_hierarchy; } void gi_marshalling_tests_sub_object_sub_method (GIMarshallingTestsSubObject *object) { g_assert_cmpint (GI_MARSHALLING_TESTS_OBJECT (object)->int_, ==, 0); } void gi_marshalling_tests_sub_object_overwritten_method (GIMarshallingTestsSubObject *object) { g_assert_cmpint (GI_MARSHALLING_TESTS_OBJECT (object)->int_, ==, 0); } G_DEFINE_TYPE (GIMarshallingTestsSubSubObject, gi_marshalling_tests_sub_sub_object, GI_MARSHALLING_TESTS_TYPE_SUB_OBJECT); static void gi_marshalling_tests_sub_sub_object_init (GIMarshallingTestsSubSubObject *self G_GNUC_UNUSED) { } static void gi_marshalling_tests_sub_sub_object_class_init (GIMarshallingTestsSubSubObjectClass *klass G_GNUC_UNUSED) { } /* Interfaces */ static void gi_marshalling_tests_interface_class_init (void *g_iface G_GNUC_UNUSED, void *data G_GNUC_UNUSED) { } GType gi_marshalling_tests_interface_get_type (void) { static GType type = 0; if (type == 0) { /* Not adding prerequisite here for test purposes */ type = g_type_register_static_simple (G_TYPE_INTERFACE, "GIMarshallingTestsInterface", sizeof (GIMarshallingTestsInterfaceIface), (GClassInitFunc) gi_marshalling_tests_interface_class_init, 0, NULL, 0); } return type; } /** * gi_marshalling_tests_interface_test_int8_in: * @in: (in): */ void gi_marshalling_tests_interface_test_int8_in (GIMarshallingTestsInterface *self, gint8 in) { GI_MARSHALLING_TESTS_INTERFACE_GET_IFACE (self)->test_int8_in (self, in); } /** * gi_marshalling_tests_test_interface_test_int8_in: * @in: (in): */ void gi_marshalling_tests_test_interface_test_int8_in (GIMarshallingTestsInterface *test_iface, gint8 in) { gi_marshalling_tests_interface_test_int8_in (test_iface, in); } static void test_interface_init (GIMarshallingTestsInterfaceIface *iface); G_DEFINE_TYPE_WITH_CODE (GIMarshallingTestsInterfaceImpl, gi_marshalling_tests_interface_impl, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GI_MARSHALLING_TESTS_TYPE_INTERFACE, test_interface_init)) static void gi_marshalling_tests_interface_impl_test_int8_in (GIMarshallingTestsInterface *self G_GNUC_UNUSED, gint8 in G_GNUC_UNUSED) { } static void test_interface_init (GIMarshallingTestsInterfaceIface *iface) { iface->test_int8_in = gi_marshalling_tests_interface_impl_test_int8_in; } static void gi_marshalling_tests_interface_impl_init (GIMarshallingTestsInterfaceImpl *self G_GNUC_UNUSED) { } static void gi_marshalling_tests_interface_impl_class_init (GIMarshallingTestsInterfaceImplClass *klass G_GNUC_UNUSED) { } /** * gi_marshalling_tests_interface_impl_get_as_interface: * * Returns: (transfer none): */ GIMarshallingTestsInterface * gi_marshalling_tests_interface_impl_get_as_interface (GIMarshallingTestsInterfaceImpl *self) { return (GIMarshallingTestsInterface *) self; } static void gi_marshalling_tests_interface2_class_init (void *g_iface G_GNUC_UNUSED, void *data G_GNUC_UNUSED) { } GType gi_marshalling_tests_interface2_get_type (void) { static GType type = 0; if (type == 0) { type = g_type_register_static_simple (G_TYPE_INTERFACE, "GIMarshallingTestsInterface2", sizeof (GIMarshallingTestsInterface2Iface), (GClassInitFunc) gi_marshalling_tests_interface2_class_init, 0, NULL, 0); } return type; } static void gi_marshalling_tests_interface3_class_init (void *g_iface G_GNUC_UNUSED, void *data G_GNUC_UNUSED) { } GType gi_marshalling_tests_interface3_get_type (void) { static GType type = 0; if (type == 0) { type = g_type_register_static_simple (G_TYPE_INTERFACE, "GIMarshallingTestsInterface3", sizeof (GIMarshallingTestsInterface3Iface), (GClassInitFunc) gi_marshalling_tests_interface3_class_init, 0, NULL, 0); } return type; } /** * gi_marshalling_tests_interface3_test_variant_array_in: * @in: (array length=n_in): * @n_in: */ void gi_marshalling_tests_interface3_test_variant_array_in (GIMarshallingTestsInterface3 *self, GVariant **in, gsize n_in) { GI_MARSHALLING_TESTS_INTERFACE3_GET_IFACE (self)->test_variant_array_in (self, in, n_in); } /** * gi_marshalling_tests_int_out_out: * @int0: (out): * @int1: (out): */ void gi_marshalling_tests_int_out_out (gint *int0, gint *int1) { *int0 = 6; *int1 = 7; } /** * gi_marshalling_tests_int_three_in_three_out: * @a: (in): * @b: (in): * @c: (in): * @out0: (out): * @out1: (out): * @out2: (out): */ void gi_marshalling_tests_int_three_in_three_out (gint a, gint b, gint c, gint *out0, gint *out1, gint *out2) { *out0 = a; *out1 = b; *out2 = c; } /** * gi_marshalling_tests_int_return_out: * @int_: (out): */ gint gi_marshalling_tests_int_return_out (gint *int_) { *int_ = 7; return 6; } /** * gi_marshalling_tests_int_two_in_utf8_two_in_with_allow_none: * @a: (in): Must be 1 * @b: (in): Must be 2 * @c: (in) (allow-none): Must be "3" or NULL * @d: (in) (allow-none): Must be "4" or NULL */ void gi_marshalling_tests_int_two_in_utf8_two_in_with_allow_none (gint a, gint b, const gchar *c, const gchar *d) { g_assert_cmpint (a, ==, 1); g_assert_cmpint (b, ==, 2); if (c != NULL) g_assert_cmpstr (c, ==, "3"); if (d != NULL) g_assert_cmpstr (d, ==, "4"); } /** * gi_marshalling_tests_int_one_in_utf8_two_in_one_allows_none: * @a: (in): Must be 1 * @b: (in) (allow-none): Must be "2" or NULL * @c: (in): Must be "3" */ void gi_marshalling_tests_int_one_in_utf8_two_in_one_allows_none (gint a, const gchar *b, const gchar *c) { g_assert_cmpint (a, ==, 1); if (b != NULL) g_assert_cmpstr (b, ==, "2"); g_assert_cmpstr (c, ==, "3"); } /** * gi_marshalling_tests_array_in_utf8_two_in: * @ints: (array length=length): * @length: * @a: (in) (allow-none): Must be "1" or NULL * @b: (in) (allow-none): Must be "2" or NULL */ void gi_marshalling_tests_array_in_utf8_two_in (const gint *ints, gint length, const gchar *a, const gchar *b) { g_assert_cmpint (length, ==, 4); g_assert_cmpint (ints[0], ==, -1); g_assert_cmpint (ints[1], ==, 0); g_assert_cmpint (ints[2], ==, 1); g_assert_cmpint (ints[3], ==, 2); if (a != NULL) g_assert_cmpstr (a, ==, "1"); if (b != NULL) g_assert_cmpstr (b, ==, "2"); } /** * gi_marshalling_tests_array_in_utf8_two_in_out_of_order: * @length: * @a: (in) (allow-none): Must be "1" or NULL * @ints: (array length=length): * @b: (in) (allow-none): Must be "2" or NULL */ void gi_marshalling_tests_array_in_utf8_two_in_out_of_order (gint length, const gchar *a, const gint *ints, const gchar *b) { g_assert_cmpint (length, ==, 4); g_assert_cmpint (ints[0], ==, -1); g_assert_cmpint (ints[1], ==, 0); g_assert_cmpint (ints[2], ==, 1); g_assert_cmpint (ints[3], ==, 2); if (a != NULL) g_assert_cmpstr (a, ==, "1"); if (b != NULL) g_assert_cmpstr (b, ==, "2"); } /* GError */ void gi_marshalling_tests_gerror (GError **error) { GQuark quark = g_quark_from_static_string (GI_MARSHALLING_TESTS_CONSTANT_GERROR_DOMAIN); g_set_error_literal (error, quark, GI_MARSHALLING_TESTS_CONSTANT_GERROR_CODE, GI_MARSHALLING_TESTS_CONSTANT_GERROR_MESSAGE); } /** * gi_marshalling_tests_gerror_array_in: * @in_ints: (array zero-terminated): */ void gi_marshalling_tests_gerror_array_in (gint *in_ints G_GNUC_UNUSED, GError **error) { GQuark quark = g_quark_from_static_string (GI_MARSHALLING_TESTS_CONSTANT_GERROR_DOMAIN); g_set_error_literal (error, quark, GI_MARSHALLING_TESTS_CONSTANT_GERROR_CODE, GI_MARSHALLING_TESTS_CONSTANT_GERROR_MESSAGE); } /** * gi_marshalling_tests_gerror_out: * @error: (out) (allow-none) (transfer full): location for the GError. * @debug: (out) (allow-none) (transfer full): location for the debug message * * Inspired by gst_message_parse_error. */ void gi_marshalling_tests_gerror_out (GError **error, gchar **debug) { GQuark quark = g_quark_from_static_string (GI_MARSHALLING_TESTS_CONSTANT_GERROR_DOMAIN); g_set_error_literal (error, quark, GI_MARSHALLING_TESTS_CONSTANT_GERROR_CODE, GI_MARSHALLING_TESTS_CONSTANT_GERROR_MESSAGE); if (debug != NULL) { *debug = g_strdup (GI_MARSHALLING_TESTS_CONSTANT_GERROR_DEBUG_MESSAGE); } } /** * gi_marshalling_tests_gerror_out_uninitialized: * @v: (out) (allow-none) (transfer full): * @v2: (out) (allow-none) (transfer full): */ gboolean gi_marshalling_tests_gerror_out_uninitialized (GError **v G_GNUC_UNUSED, gchar **v2 G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gerror_out_transfer_none: * @err: (out) (allow-none) (transfer none): location for the GError. * @debug: (out) (allow-none) (transfer none): location for the debug message * * A variant of gi_marshalling_tests_gerror_out() which returns data the caller * must not free. */ void gi_marshalling_tests_gerror_out_transfer_none (GError **err, const gchar **debug) { static GError error = { 0, GI_MARSHALLING_TESTS_CONSTANT_GERROR_CODE, (gchar *) GI_MARSHALLING_TESTS_CONSTANT_GERROR_MESSAGE }; error.domain = g_quark_from_static_string (GI_MARSHALLING_TESTS_CONSTANT_GERROR_DOMAIN); *err = &error; *debug = GI_MARSHALLING_TESTS_CONSTANT_GERROR_DEBUG_MESSAGE; } /** * gi_marshalling_tests_gerror_out_transfer_none_uninitialized: * @v: (out) (allow-none) (transfer none): * @v2: (out) (allow-none) (transfer none): */ gboolean gi_marshalling_tests_gerror_out_transfer_none_uninitialized (GError **v G_GNUC_UNUSED, const gchar **v2 G_GNUC_UNUSED) { return FALSE; } /** * gi_marshalling_tests_gerror_return: * * Yet another variant of gi_marshalling_tests_gerror_out(). * * Returns: (transfer full): a GError */ GError * gi_marshalling_tests_gerror_return (void) { GQuark quark = g_quark_from_static_string (GI_MARSHALLING_TESTS_CONSTANT_GERROR_DOMAIN); return g_error_new_literal (quark, GI_MARSHALLING_TESTS_CONSTANT_GERROR_CODE, GI_MARSHALLING_TESTS_CONSTANT_GERROR_MESSAGE); } static GIMarshallingTestsOverridesStruct * gi_marshalling_tests_overrides_struct_copy (GIMarshallingTestsOverridesStruct *struct_) { GIMarshallingTestsOverridesStruct *new_struct; new_struct = g_slice_new (GIMarshallingTestsOverridesStruct); *new_struct = *struct_; return new_struct; } static void gi_marshalling_tests_overrides_struct_free (GIMarshallingTestsOverridesStruct *struct_) { g_slice_free (GIMarshallingTestsOverridesStruct, struct_); } GType gi_marshalling_tests_overrides_struct_get_type (void) { static GType type = 0; if (type == 0) { type = g_boxed_type_register_static ("GIMarshallingTestsOverridesStruct", (GBoxedCopyFunc) gi_marshalling_tests_overrides_struct_copy, (GBoxedFreeFunc) gi_marshalling_tests_overrides_struct_free); } return type; } GIMarshallingTestsOverridesStruct * gi_marshalling_tests_overrides_struct_new (void) { return g_slice_new (GIMarshallingTestsOverridesStruct); } glong gi_marshalling_tests_overrides_struct_method (GIMarshallingTestsOverridesStruct *self G_GNUC_UNUSED) { return 42; } /** * gi_marshalling_tests_overrides_struct_returnv: * * Returns: (transfer full): */ GIMarshallingTestsOverridesStruct * gi_marshalling_tests_overrides_struct_returnv (void) { return gi_marshalling_tests_overrides_struct_new (); } G_DEFINE_TYPE (GIMarshallingTestsOverridesObject, gi_marshalling_tests_overrides_object, G_TYPE_OBJECT); static void gi_marshalling_tests_overrides_object_init (GIMarshallingTestsOverridesObject *self G_GNUC_UNUSED) { } static void gi_marshalling_tests_overrides_object_finalize (GObject *object) { G_OBJECT_CLASS (gi_marshalling_tests_overrides_object_parent_class)->finalize (object); } static void gi_marshalling_tests_overrides_object_class_init (GIMarshallingTestsOverridesObjectClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); #if 0 GObjectClass *parent_class = G_OBJECT_CLASS (klass); #endif object_class->finalize = gi_marshalling_tests_overrides_object_finalize; } GIMarshallingTestsOverridesObject * gi_marshalling_tests_overrides_object_new (void) { return g_object_new (GI_MARSHALLING_TESTS_TYPE_OVERRIDES_OBJECT, NULL); } glong gi_marshalling_tests_overrides_object_method (GIMarshallingTestsOverridesObject *self G_GNUC_UNUSED) { return 42; } /** * gi_marshalling_tests_overrides_object_returnv: * * Returns: (transfer full): */ GIMarshallingTestsOverridesObject * gi_marshalling_tests_overrides_object_returnv (void) { return g_object_new (GI_MARSHALLING_TESTS_TYPE_OVERRIDES_OBJECT, NULL); } /** * gi_marshalling_tests_filename_list_return: * * Returns: (transfer none) (element-type filename): List of filenames */ GSList * gi_marshalling_tests_filename_list_return (void) { return NULL; } /** * gi_marshalling_tests_param_spec_in_bool: */ void gi_marshalling_tests_param_spec_in_bool (const GParamSpec *param) { g_assert (G_IS_PARAM_SPEC (param)); g_assert_cmpint (G_PARAM_SPEC_VALUE_TYPE (param), ==, G_TYPE_BOOLEAN); g_assert_cmpstr (g_param_spec_get_name ((GParamSpec *) param), ==, "mybool"); } /** * gi_marshalling_tests_param_spec_return: * * Returns: (transfer full): a #GParamSpec */ GParamSpec * gi_marshalling_tests_param_spec_return (void) { return g_param_spec_string ("test-param", "test", "This is a test", "42", G_PARAM_READABLE); } /** * gi_marshalling_tests_param_spec_out: * @param: (out): */ void gi_marshalling_tests_param_spec_out (GParamSpec **param) { *param = g_param_spec_string ("test-param", "test", "This is a test", "42", G_PARAM_READABLE); } /** * gi_marshalling_tests_param_spec_out_uninitialized: * @v: (out): */ gboolean gi_marshalling_tests_param_spec_out_uninitialized (GParamSpec **v G_GNUC_UNUSED) { return FALSE; } enum { DUMMY_PROPERTY, SOME_BOOLEAN_PROPERTY, SOME_CHAR_PROPERTY, SOME_UCHAR_PROPERTY, SOME_INT_PROPERTY, SOME_UINT_PROPERTY, SOME_LONG_PROPERTY, SOME_ULONG_PROPERTY, SOME_INT64_PROPERTY, SOME_UINT64_PROPERTY, SOME_FLOAT_PROPERTY, SOME_STRING_PROPERTY, SOME_DOUBLE_PROPERTY, SOME_STRV_PROPERTY, SOME_BOXED_STRUCT_PROPERTY, SOME_VARIANT_PROPERTY, SOME_BOXED_GLIST_PROPERTY, SOME_GVALUE_PROPERTY, SOME_OBJECT_PROPERTY, SOME_FLAGS_PROPERTY, SOME_ENUM_PROPERTY, SOME_BYTE_ARRAY_PROPERTY, SOME_READONLY_PROPERTY, SOME_DEPRECATED_INT_PROPERTY, N_PROPERTIES }; G_DEFINE_TYPE (GIMarshallingTestsPropertiesObject, gi_marshalling_tests_properties_object, G_TYPE_OBJECT); static void gi_marshalling_tests_properties_object_init (GIMarshallingTestsPropertiesObject *self G_GNUC_UNUSED) { } static void gi_marshalling_tests_properties_object_finalize (GObject *obj) { GIMarshallingTestsPropertiesObject *self; self = GI_MARSHALLING_TESTS_PROPERTIES_OBJECT (obj); if (self->some_gvalue) { g_boxed_free (G_TYPE_VALUE, self->some_gvalue); self->some_gvalue = NULL; } g_clear_pointer (&self->some_string, g_free); g_clear_pointer (&self->some_strv, g_strfreev); g_clear_pointer (&self->some_boxed_struct, gi_marshalling_tests_boxed_struct_free); g_clear_pointer (&self->some_byte_array, g_byte_array_unref); g_clear_pointer (&self->some_variant, g_variant_unref); g_clear_pointer (&self->some_boxed_glist, g_list_free); g_clear_object (&self->some_object); G_OBJECT_CLASS (gi_marshalling_tests_properties_object_parent_class)->finalize (obj); } static void gi_marshalling_tests_properties_object_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GIMarshallingTestsPropertiesObject *self; self = GI_MARSHALLING_TESTS_PROPERTIES_OBJECT (object); switch (property_id) { case SOME_BOOLEAN_PROPERTY: g_value_set_boolean (value, self->some_boolean); break; case SOME_CHAR_PROPERTY: g_value_set_schar (value, self->some_char); break; case SOME_UCHAR_PROPERTY: g_value_set_uchar (value, self->some_uchar); break; case SOME_INT_PROPERTY: g_value_set_int (value, self->some_int); break; case SOME_UINT_PROPERTY: g_value_set_uint (value, self->some_uint); break; case SOME_LONG_PROPERTY: g_value_set_long (value, self->some_long); break; case SOME_ULONG_PROPERTY: g_value_set_ulong (value, self->some_ulong); break; case SOME_INT64_PROPERTY: g_value_set_int64 (value, self->some_int64); break; case SOME_UINT64_PROPERTY: g_value_set_uint64 (value, self->some_uint64); break; case SOME_FLOAT_PROPERTY: g_value_set_float (value, self->some_float); break; case SOME_DOUBLE_PROPERTY: g_value_set_double (value, self->some_double); break; case SOME_STRING_PROPERTY: g_value_set_string (value, self->some_string); break; case SOME_STRV_PROPERTY: g_value_set_boxed (value, self->some_strv); break; case SOME_BOXED_STRUCT_PROPERTY: g_value_set_boxed (value, self->some_boxed_struct); break; case SOME_BOXED_GLIST_PROPERTY: g_value_set_boxed (value, self->some_boxed_glist); break; case SOME_GVALUE_PROPERTY: g_value_set_boxed (value, self->some_gvalue); break; case SOME_VARIANT_PROPERTY: g_value_set_variant (value, self->some_variant); break; case SOME_OBJECT_PROPERTY: g_value_set_object (value, self->some_object); break; case SOME_FLAGS_PROPERTY: g_value_set_flags (value, self->some_flags); break; case SOME_ENUM_PROPERTY: g_value_set_enum (value, self->some_enum); break; case SOME_BYTE_ARRAY_PROPERTY: g_value_set_boxed (value, self->some_byte_array); break; case SOME_READONLY_PROPERTY: g_value_set_int (value, 42); break; case SOME_DEPRECATED_INT_PROPERTY: g_value_set_int (value, self->some_deprecated_int); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gi_marshalling_tests_properties_object_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GIMarshallingTestsPropertiesObject *self; self = GI_MARSHALLING_TESTS_PROPERTIES_OBJECT (object); switch (property_id) { case SOME_BOOLEAN_PROPERTY: self->some_boolean = g_value_get_boolean (value); break; case SOME_CHAR_PROPERTY: self->some_char = g_value_get_schar (value); break; case SOME_UCHAR_PROPERTY: self->some_uchar = g_value_get_uchar (value); break; case SOME_INT_PROPERTY: self->some_int = g_value_get_int (value); break; case SOME_UINT_PROPERTY: self->some_uint = g_value_get_uint (value); break; case SOME_LONG_PROPERTY: self->some_long = g_value_get_long (value); break; case SOME_ULONG_PROPERTY: self->some_ulong = g_value_get_ulong (value); break; case SOME_INT64_PROPERTY: self->some_int64 = g_value_get_int64 (value); break; case SOME_UINT64_PROPERTY: self->some_uint64 = g_value_get_uint64 (value); break; case SOME_FLOAT_PROPERTY: self->some_float = g_value_get_float (value); break; case SOME_DOUBLE_PROPERTY: self->some_double = g_value_get_double (value); break; case SOME_STRING_PROPERTY: g_clear_pointer (&self->some_string, g_free); self->some_string = g_value_dup_string (value); break; case SOME_STRV_PROPERTY: g_strfreev (self->some_strv); self->some_strv = g_strdupv (g_value_get_boxed (value)); break; case SOME_BOXED_STRUCT_PROPERTY: gi_marshalling_tests_boxed_struct_free (self->some_boxed_struct); self->some_boxed_struct = gi_marshalling_tests_boxed_struct_copy (g_value_get_boxed (value)); break; case SOME_BOXED_GLIST_PROPERTY: g_list_free (self->some_boxed_glist); self->some_boxed_glist = g_list_copy (g_value_get_boxed (value)); break; case SOME_GVALUE_PROPERTY: if (self->some_gvalue) g_boxed_free (G_TYPE_VALUE, self->some_gvalue); self->some_gvalue = g_value_dup_boxed (value); break; case SOME_VARIANT_PROPERTY: if (self->some_variant != NULL) g_variant_unref (self->some_variant); self->some_variant = g_value_get_variant (value); if (self->some_variant != NULL) g_variant_ref (self->some_variant); break; case SOME_OBJECT_PROPERTY: if (self->some_object != NULL) g_object_unref (self->some_object); self->some_object = g_value_dup_object (value); break; case SOME_FLAGS_PROPERTY: self->some_flags = g_value_get_flags (value); break; case SOME_ENUM_PROPERTY: self->some_enum = g_value_get_enum (value); break; case SOME_BYTE_ARRAY_PROPERTY: if (self->some_byte_array != NULL) g_byte_array_unref (self->some_byte_array); self->some_byte_array = g_value_dup_boxed (value); break; case SOME_DEPRECATED_INT_PROPERTY: self->some_deprecated_int = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static GParamSpec *properties_object_properties[N_PROPERTIES] = { NULL, }; static void gi_marshalling_tests_properties_object_class_init (GIMarshallingTestsPropertiesObjectClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gi_marshalling_tests_properties_object_finalize; object_class->get_property = gi_marshalling_tests_properties_object_get_property; object_class->set_property = gi_marshalling_tests_properties_object_set_property; properties_object_properties[SOME_BOOLEAN_PROPERTY] = g_param_spec_boolean ("some-boolean", "some-boolean", "some-boolean", FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_CHAR_PROPERTY] = g_param_spec_char ("some-char", "some-char", "some-char", G_MININT8, G_MAXINT8, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_UCHAR_PROPERTY] = g_param_spec_uchar ("some-uchar", "some-uchar", "some-uchar", 0, G_MAXUINT8, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_INT_PROPERTY] = g_param_spec_int ("some-int", "some-int", "some-int", G_MININT, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_UINT_PROPERTY] = g_param_spec_uint ("some-uint", "some-uint", "some-uint", 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_LONG_PROPERTY] = g_param_spec_long ("some-long", "some-long", "some-long", G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_ULONG_PROPERTY] = g_param_spec_ulong ("some-ulong", "some-ulong", "some-ulong", 0, G_MAXULONG, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_INT64_PROPERTY] = g_param_spec_int64 ("some-int64", "some-int64", "some-int64", G_MININT64, G_MAXINT64, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_UINT64_PROPERTY] = g_param_spec_uint64 ("some-uint64", "some-uint64", "some-uint64", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_FLOAT_PROPERTY] = g_param_spec_float ("some-float", "some-float", "some-float", -1 * G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_DOUBLE_PROPERTY] = g_param_spec_double ("some-double", "some-double", "some-double", -1 * G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_STRING_PROPERTY] = g_param_spec_string ("some-string", "some-string", "some-string", NULL, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_STRV_PROPERTY] = g_param_spec_boxed ("some-strv", "some-strv", "some-strv", G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_BOXED_STRUCT_PROPERTY] = g_param_spec_boxed ("some-boxed-struct", "some-boxed-struct", "some-boxed-struct", gi_marshalling_tests_boxed_struct_get_type (), G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesObject:some-boxed-glist: (type GLib.List(gint)) (transfer none): */ properties_object_properties[SOME_BOXED_GLIST_PROPERTY] = g_param_spec_boxed ("some-boxed-glist", "some-boxed-glist", "some-boxed-glist", gi_marshalling_tests_boxed_glist_get_type (), G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_GVALUE_PROPERTY] = g_param_spec_boxed ("some-gvalue", "some-gvalue", "some-gvalue", G_TYPE_VALUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_VARIANT_PROPERTY] = g_param_spec_variant ("some-variant", "some-variant", "some-variant", G_VARIANT_TYPE_ANY, NULL, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_OBJECT_PROPERTY] = g_param_spec_object ("some-object", "some-object", "some-object", G_TYPE_OBJECT, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_FLAGS_PROPERTY] = g_param_spec_flags ("some-flags", "some-flags", "some-flags", GI_MARSHALLING_TESTS_TYPE_FLAGS, GI_MARSHALLING_TESTS_FLAGS_VALUE1, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_ENUM_PROPERTY] = g_param_spec_enum ("some-enum", "some-enum", "some-enum", GI_MARSHALLING_TESTS_TYPE_GENUM, GI_MARSHALLING_TESTS_GENUM_VALUE1, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_BYTE_ARRAY_PROPERTY] = g_param_spec_boxed ("some-byte-array", "some-byte-array", "some-byte-array", G_TYPE_BYTE_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); properties_object_properties[SOME_READONLY_PROPERTY] = g_param_spec_int ("some-readonly", "some-readonly", "some-readonly", G_MININT, G_MAXINT, 0, G_PARAM_READABLE); properties_object_properties[SOME_DEPRECATED_INT_PROPERTY] = g_param_spec_int ("some-deprecated-int", "some-deprecated-int", "some-deprecated-int", G_MININT, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT | G_PARAM_DEPRECATED); g_object_class_install_properties (object_class, N_PROPERTIES, properties_object_properties); } GIMarshallingTestsPropertiesObject * gi_marshalling_tests_properties_object_new (void) { return g_object_new (GI_MARSHALLING_TESTS_TYPE_PROPERTIES_OBJECT, NULL); } G_DEFINE_FINAL_TYPE (GIMarshallingTestsPropertiesAccessorsObject, gi_marshalling_tests_properties_accessors_object, G_TYPE_OBJECT) GIMarshallingTestsPropertiesAccessorsObject * gi_marshalling_tests_properties_accessors_object_new (void) { return g_object_new (GI_MARSHALLING_TESTS_TYPE_ACCESSORS_TESTS_PROPERTIES_OBJECT, NULL); } static void gi_marshalling_tests_properties_accessors_object_init (GIMarshallingTestsPropertiesAccessorsObject *self G_GNUC_UNUSED) { } static void gi_marshalling_tests_properties_accessors_object_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GIMarshallingTestsPropertiesAccessorsObject *self; self = GI_MARSHALLING_TESTS_PROPERTIES_ACCESSORS_OBJECT (object); switch (property_id) { case SOME_BOOLEAN_PROPERTY: g_value_set_boolean (value, self->some_boolean); break; case SOME_CHAR_PROPERTY: g_value_set_schar (value, self->some_char); break; case SOME_UCHAR_PROPERTY: g_value_set_uchar (value, self->some_uchar); break; case SOME_INT_PROPERTY: g_value_set_int (value, self->some_int); break; case SOME_UINT_PROPERTY: g_value_set_uint (value, self->some_uint); break; case SOME_LONG_PROPERTY: g_value_set_long (value, self->some_long); break; case SOME_ULONG_PROPERTY: g_value_set_ulong (value, self->some_ulong); break; case SOME_INT64_PROPERTY: g_value_set_int64 (value, self->some_int64); break; case SOME_UINT64_PROPERTY: g_value_set_uint64 (value, self->some_uint64); break; case SOME_FLOAT_PROPERTY: g_value_set_float (value, self->some_float); break; case SOME_DOUBLE_PROPERTY: g_value_set_double (value, self->some_double); break; case SOME_STRING_PROPERTY: g_value_set_string (value, self->some_string); break; case SOME_STRV_PROPERTY: g_value_set_boxed (value, self->some_strv); break; case SOME_BOXED_STRUCT_PROPERTY: g_value_set_boxed (value, self->some_boxed_struct); break; case SOME_BOXED_GLIST_PROPERTY: g_value_set_boxed (value, self->some_boxed_glist); break; case SOME_GVALUE_PROPERTY: g_value_set_boxed (value, self->some_gvalue); break; case SOME_VARIANT_PROPERTY: g_value_set_variant (value, self->some_variant); break; case SOME_OBJECT_PROPERTY: g_value_set_object (value, self->some_object); break; case SOME_FLAGS_PROPERTY: g_value_set_flags (value, self->some_flags); break; case SOME_ENUM_PROPERTY: g_value_set_enum (value, self->some_enum); break; case SOME_BYTE_ARRAY_PROPERTY: g_value_set_boxed (value, self->some_byte_array); break; case SOME_READONLY_PROPERTY: g_value_set_int (value, 42); break; case SOME_DEPRECATED_INT_PROPERTY: g_value_set_int (value, self->some_deprecated_int); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gi_marshalling_tests_properties_accessors_object_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GIMarshallingTestsPropertiesAccessorsObject *self; self = GI_MARSHALLING_TESTS_PROPERTIES_ACCESSORS_OBJECT (object); switch (property_id) { case SOME_BOOLEAN_PROPERTY: self->some_boolean = g_value_get_boolean (value); break; case SOME_CHAR_PROPERTY: self->some_char = g_value_get_schar (value); break; case SOME_UCHAR_PROPERTY: self->some_uchar = g_value_get_uchar (value); break; case SOME_INT_PROPERTY: self->some_int = g_value_get_int (value); break; case SOME_UINT_PROPERTY: self->some_uint = g_value_get_uint (value); break; case SOME_LONG_PROPERTY: self->some_long = g_value_get_long (value); break; case SOME_ULONG_PROPERTY: self->some_ulong = g_value_get_ulong (value); break; case SOME_INT64_PROPERTY: self->some_int64 = g_value_get_int64 (value); break; case SOME_UINT64_PROPERTY: self->some_uint64 = g_value_get_uint64 (value); break; case SOME_FLOAT_PROPERTY: self->some_float = g_value_get_float (value); break; case SOME_DOUBLE_PROPERTY: self->some_double = g_value_get_double (value); break; case SOME_STRING_PROPERTY: g_clear_pointer (&self->some_string, g_free); self->some_string = g_value_dup_string (value); break; case SOME_STRV_PROPERTY: g_strfreev (self->some_strv); self->some_strv = g_strdupv (g_value_get_boxed (value)); break; case SOME_BOXED_STRUCT_PROPERTY: gi_marshalling_tests_boxed_struct_free (self->some_boxed_struct); self->some_boxed_struct = gi_marshalling_tests_boxed_struct_copy (g_value_get_boxed (value)); break; case SOME_BOXED_GLIST_PROPERTY: g_list_free (self->some_boxed_glist); self->some_boxed_glist = g_list_copy (g_value_get_boxed (value)); break; case SOME_GVALUE_PROPERTY: if (self->some_gvalue) g_boxed_free (G_TYPE_VALUE, self->some_gvalue); self->some_gvalue = g_value_dup_boxed (value); break; case SOME_VARIANT_PROPERTY: if (self->some_variant != NULL) g_variant_unref (self->some_variant); self->some_variant = g_value_get_variant (value); if (self->some_variant != NULL) g_variant_ref (self->some_variant); break; case SOME_OBJECT_PROPERTY: if (self->some_object != NULL) g_object_unref (self->some_object); self->some_object = g_value_dup_object (value); break; case SOME_FLAGS_PROPERTY: self->some_flags = g_value_get_flags (value); break; case SOME_ENUM_PROPERTY: self->some_enum = g_value_get_enum (value); break; case SOME_BYTE_ARRAY_PROPERTY: if (self->some_byte_array != NULL) g_byte_array_unref (self->some_byte_array); self->some_byte_array = g_value_dup_boxed (value); break; case SOME_DEPRECATED_INT_PROPERTY: self->some_deprecated_int = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gi_marshalling_tests_properties_accessors_object_dispose (GObject *obj) { GIMarshallingTestsPropertiesAccessorsObject *self; self = GI_MARSHALLING_TESTS_PROPERTIES_ACCESSORS_OBJECT (obj); if (self->some_gvalue) { g_boxed_free (G_TYPE_VALUE, self->some_gvalue); self->some_gvalue = NULL; } g_clear_pointer (&self->some_string, g_free); g_clear_pointer (&self->some_strv, g_strfreev); g_clear_pointer (&self->some_boxed_struct, gi_marshalling_tests_boxed_struct_free); g_clear_pointer (&self->some_byte_array, g_byte_array_unref); g_clear_pointer (&self->some_variant, g_variant_unref); g_clear_pointer (&self->some_boxed_glist, g_list_free); g_clear_object (&self->some_object); G_OBJECT_CLASS (gi_marshalling_tests_properties_accessors_object_parent_class)->dispose (obj); } static GParamSpec *accessors_object_properties[N_PROPERTIES] = { NULL, }; static void gi_marshalling_tests_properties_accessors_object_class_init (GIMarshallingTestsPropertiesAccessorsObjectClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = gi_marshalling_tests_properties_accessors_object_dispose; object_class->get_property = gi_marshalling_tests_properties_accessors_object_get_property; object_class->set_property = gi_marshalling_tests_properties_accessors_object_set_property; /** * GIMarshallingTestsPropertiesAccessorsObject:some-boolean: (setter set_boolean) (getter get_boolean): */ accessors_object_properties[SOME_BOOLEAN_PROPERTY] = g_param_spec_boolean ("some-boolean", "some-boolean", "some-boolean", FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-char: (setter set_char) (getter get_char): */ accessors_object_properties[SOME_CHAR_PROPERTY] = g_param_spec_char ("some-char", "some-char", "some-char", G_MININT8, G_MAXINT8, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-uchar: (setter set_uchar) (getter get_uchar): */ accessors_object_properties[SOME_UCHAR_PROPERTY] = g_param_spec_uchar ("some-uchar", "some-uchar", "some-uchar", 0, G_MAXUINT8, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-int: (setter set_int) (getter get_int): */ accessors_object_properties[SOME_INT_PROPERTY] = g_param_spec_int ("some-int", "some-int", "some-int", G_MININT, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-uint: (setter set_uint) (getter get_uint): */ accessors_object_properties[SOME_UINT_PROPERTY] = g_param_spec_uint ("some-uint", "some-uint", "some-uint", 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-long: (setter set_long) (getter get_long): */ accessors_object_properties[SOME_LONG_PROPERTY] = g_param_spec_long ("some-long", "some-long", "some-long", G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-ulong: (setter set_ulong) (getter get_ulong): */ accessors_object_properties[SOME_ULONG_PROPERTY] = g_param_spec_ulong ("some-ulong", "some-ulong", "some-ulong", 0, G_MAXULONG, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-int64: (setter set_int64) (getter get_int64): */ accessors_object_properties[SOME_INT64_PROPERTY] = g_param_spec_int64 ("some-int64", "some-int64", "some-int64", G_MININT64, G_MAXINT64, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-uint64: (setter set_uint64) (getter get_uint64): */ accessors_object_properties[SOME_UINT64_PROPERTY] = g_param_spec_uint64 ("some-uint64", "some-uint64", "some-uint64", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-float: (setter set_float) (getter get_float): */ accessors_object_properties[SOME_FLOAT_PROPERTY] = g_param_spec_float ("some-float", "some-float", "some-float", -1 * G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-double: (setter set_double) (getter get_double): */ accessors_object_properties[SOME_DOUBLE_PROPERTY] = g_param_spec_double ("some-double", "some-double", "some-double", -1 * G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-string: (setter set_string) (getter get_string): */ accessors_object_properties[SOME_STRING_PROPERTY] = g_param_spec_string ("some-string", "some-string", "some-string", NULL, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-strv: (setter set_strv) (getter get_strv): */ accessors_object_properties[SOME_STRV_PROPERTY] = g_param_spec_boxed ("some-strv", "some-strv", "some-strv", G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-boxed-struct: (setter set_boxed_struct) (getter get_boxed_struct): */ accessors_object_properties[SOME_BOXED_STRUCT_PROPERTY] = g_param_spec_boxed ("some-boxed-struct", "some-boxed-struct", "some-boxed-struct", gi_marshalling_tests_boxed_struct_get_type (), G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-boxed-glist: (type GLib.List(gint)) (transfer none) (setter set_boxed_glist) (getter get_boxed_glist): */ accessors_object_properties[SOME_BOXED_GLIST_PROPERTY] = g_param_spec_boxed ("some-boxed-glist", "some-boxed-glist", "some-boxed-glist", gi_marshalling_tests_boxed_glist_get_type (), G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-gvalue: (setter set_gvalue) (getter get_gvalue): */ accessors_object_properties[SOME_GVALUE_PROPERTY] = g_param_spec_boxed ("some-gvalue", "some-gvalue", "some-gvalue", G_TYPE_VALUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-variant: (setter set_variant) (getter get_variant): */ accessors_object_properties[SOME_VARIANT_PROPERTY] = g_param_spec_variant ("some-variant", "some-variant", "some-variant", G_VARIANT_TYPE_ANY, NULL, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-object: (setter set_object) (getter get_object): */ accessors_object_properties[SOME_OBJECT_PROPERTY] = g_param_spec_object ("some-object", "some-object", "some-object", G_TYPE_OBJECT, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-flags: (setter set_flags) (getter get_flags): */ accessors_object_properties[SOME_FLAGS_PROPERTY] = g_param_spec_flags ("some-flags", "some-flags", "some-flags", GI_MARSHALLING_TESTS_TYPE_FLAGS, GI_MARSHALLING_TESTS_FLAGS_VALUE1, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-enum: (setter set_enum) (getter get_enum): */ accessors_object_properties[SOME_ENUM_PROPERTY] = g_param_spec_enum ("some-enum", "some-enum", "some-enum", GI_MARSHALLING_TESTS_TYPE_GENUM, GI_MARSHALLING_TESTS_GENUM_VALUE1, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-byte_array: (setter set_byte_array) (getter get_byte_array): */ accessors_object_properties[SOME_BYTE_ARRAY_PROPERTY] = g_param_spec_boxed ("some-byte-array", "some-byte-array", "some-byte-array", G_TYPE_BYTE_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); /** * GIMarshallingTestsPropertiesAccessorsObject:some-readonly: (getter get_readonly): */ accessors_object_properties[SOME_READONLY_PROPERTY] = g_param_spec_int ("some-readonly", "some-readonly", "some-readonly", G_MININT, G_MAXINT, 0, G_PARAM_READABLE); /** * GIMarshallingTestsPropertiesAccessorsObject:some-deprecated-int: (setter set_deprecated_int) (getter get_deprecated_int): * Deprecated: 0.1 */ accessors_object_properties[SOME_DEPRECATED_INT_PROPERTY] = g_param_spec_int ("some-deprecated-int", "some-deprecated-int", "some-deprecated-int", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_DEPRECATED); g_object_class_install_properties (object_class, N_PROPERTIES, accessors_object_properties); } /** * gi_marshalling_tests_properties_accessors_object_set_boolean: (set-property some-boolean) * @self: * @some_boolean: */ void gi_marshalling_tests_properties_accessors_object_set_boolean (GIMarshallingTestsPropertiesAccessorsObject *self, gboolean some_boolean) { if (self->some_boolean == some_boolean) return; self->some_boolean = some_boolean; g_object_notify (G_OBJECT (self), "some-boolean"); } /** * gi_marshalling_tests_properties_accessors_object_set_char: (set-property some-char) * @self: * @some_char: */ void gi_marshalling_tests_properties_accessors_object_set_char (GIMarshallingTestsPropertiesAccessorsObject *self, gchar some_char) { if (self->some_char == some_char) return; self->some_char = some_char; g_object_notify (G_OBJECT (self), "some-char"); } /** * gi_marshalling_tests_properties_accessors_object_set_uchar: (set-property some-uchar) * @self: * @some_uchar: */ void gi_marshalling_tests_properties_accessors_object_set_uchar (GIMarshallingTestsPropertiesAccessorsObject *self, guchar some_uchar) { if (self->some_uchar == some_uchar) return; self->some_uchar = some_uchar; g_object_notify (G_OBJECT (self), "some-uchar"); } /** * gi_marshalling_tests_properties_accessors_object_set_int: (set-property some-int) * @self: * @some_int: */ void gi_marshalling_tests_properties_accessors_object_set_int (GIMarshallingTestsPropertiesAccessorsObject *self, gint some_int) { if (self->some_int == some_int) return; self->some_int = some_int; g_object_notify (G_OBJECT (self), "some-int"); } /** * gi_marshalling_tests_properties_accessors_object_set_uint: (set-property some-uint) * @self: * @some_uint: */ void gi_marshalling_tests_properties_accessors_object_set_uint (GIMarshallingTestsPropertiesAccessorsObject *self, guint some_uint) { if (self->some_uint == some_uint) return; self->some_uint = some_uint; g_object_notify (G_OBJECT (self), "some-uint"); } /** * gi_marshalling_tests_properties_accessors_object_set_long: (set-property some-long) * @self: * @some_long: */ void gi_marshalling_tests_properties_accessors_object_set_long (GIMarshallingTestsPropertiesAccessorsObject *self, glong some_long) { if (self->some_long == some_long) return; self->some_long = some_long; g_object_notify (G_OBJECT (self), "some-long"); } /** * gi_marshalling_tests_properties_accessors_object_set_ulong: (set-property some-ulong) * @self: * @some_ulong: */ void gi_marshalling_tests_properties_accessors_object_set_ulong (GIMarshallingTestsPropertiesAccessorsObject *self, gulong some_ulong) { if (self->some_ulong == some_ulong) return; self->some_ulong = some_ulong; g_object_notify (G_OBJECT (self), "some-ulong"); } /** * gi_marshalling_tests_properties_accessors_object_set_int64: (set-property some-int64) * @self: * @some_int64: */ void gi_marshalling_tests_properties_accessors_object_set_int64 (GIMarshallingTestsPropertiesAccessorsObject *self, gint64 some_int64) { if (self->some_int64 == some_int64) return; self->some_int64 = some_int64; g_object_notify (G_OBJECT (self), "some-int64"); } /** * gi_marshalling_tests_properties_accessors_object_set_uint64: (set-property some-uint64) * @self: * @some_uint64: */ void gi_marshalling_tests_properties_accessors_object_set_uint64 (GIMarshallingTestsPropertiesAccessorsObject *self, guint64 some_uint64) { if (self->some_uint64 == some_uint64) return; self->some_uint64 = some_uint64; g_object_notify (G_OBJECT (self), "some-uint64"); } /** * gi_marshalling_tests_properties_accessors_object_set_float: (set-property some-float) * @self: * @some_float: */ void gi_marshalling_tests_properties_accessors_object_set_float (GIMarshallingTestsPropertiesAccessorsObject *self, gfloat some_float) { if (self->some_float == some_float) return; self->some_float = some_float; g_object_notify (G_OBJECT (self), "some-float"); } /** * gi_marshalling_tests_properties_accessors_object_set_double: (set-property some-double) * @self: * @some_double: */ void gi_marshalling_tests_properties_accessors_object_set_double (GIMarshallingTestsPropertiesAccessorsObject *self, gdouble some_double) { if (self->some_double == some_double) return; self->some_double = some_double; g_object_notify (G_OBJECT (self), "some-double"); } /** * gi_marshalling_tests_properties_accessors_object_set_string: (set-property some-string) * @self: * @some_string: */ void gi_marshalling_tests_properties_accessors_object_set_string (GIMarshallingTestsPropertiesAccessorsObject *self, gchar *some_string) { if (g_strcmp0 (self->some_string, some_string) == 0) return; g_set_str (&self->some_string, some_string); g_object_notify (G_OBJECT (self), "some-string"); } /** * gi_marshalling_tests_properties_accessors_object_set_strv: (set-property some-strv) * @self: * @some_strv: */ void gi_marshalling_tests_properties_accessors_object_set_strv (GIMarshallingTestsPropertiesAccessorsObject *self, GStrv some_strv) { if (self->some_strv == some_strv) return; if (self->some_strv && some_strv && g_strv_equal ((const char **) self->some_strv, (const char **) some_strv)) return; g_clear_pointer (&self->some_strv, g_strfreev); self->some_strv = g_strdupv (some_strv); g_object_notify (G_OBJECT (self), "some-strv"); } /** * gi_marshalling_tests_properties_accessors_object_set_boxed_struct: (set-property some-boxed-struct) * @self: * @some_boxed_struct: */ void gi_marshalling_tests_properties_accessors_object_set_boxed_struct (GIMarshallingTestsPropertiesAccessorsObject *self, GIMarshallingTestsBoxedStruct *some_boxed_struct) { if (self->some_boxed_struct == some_boxed_struct) return; g_clear_pointer (&self->some_boxed_struct, gi_marshalling_tests_boxed_struct_free); self->some_boxed_struct = gi_marshalling_tests_boxed_struct_copy (some_boxed_struct); g_object_notify (G_OBJECT (self), "some-boxed-struct"); } /** * gi_marshalling_tests_properties_accessors_object_set_boxed_glist: (set-property some-boxed-glist) * @self: * @some_boxed_glist: (element-type int): */ void gi_marshalling_tests_properties_accessors_object_set_boxed_glist (GIMarshallingTestsPropertiesAccessorsObject *self, GList *some_boxed_glist) { if (self->some_boxed_glist == some_boxed_glist) return; g_clear_pointer (&self->some_boxed_glist, g_list_free); self->some_boxed_glist = g_list_copy (some_boxed_glist); g_object_notify (G_OBJECT (self), "some-boxed-glist"); } /** * gi_marshalling_tests_properties_accessors_object_set_gvalue: (set-property some-gvalue) * @self: * @some_gvalue: */ void gi_marshalling_tests_properties_accessors_object_set_gvalue (GIMarshallingTestsPropertiesAccessorsObject *self, GValue *some_gvalue) { if (self->some_gvalue == some_gvalue) return; if (self->some_gvalue) g_boxed_free (G_TYPE_VALUE, self->some_gvalue); self->some_gvalue = g_boxed_copy (G_TYPE_VALUE, some_gvalue); g_object_notify (G_OBJECT (self), "some-gvalue"); } /** * gi_marshalling_tests_properties_accessors_object_set_variant: (set-property some-variant) * @self: * @some_variant: */ void gi_marshalling_tests_properties_accessors_object_set_variant (GIMarshallingTestsPropertiesAccessorsObject *self, GVariant *some_variant) { if (self->some_variant == some_variant) return; g_clear_pointer (&self->some_variant, g_variant_unref); self->some_variant = g_variant_ref_sink (some_variant); g_object_notify (G_OBJECT (self), "some-variant"); } /** * gi_marshalling_tests_properties_accessors_object_set_object: (set-property some-object) * @self: * @some_object: */ void gi_marshalling_tests_properties_accessors_object_set_object (GIMarshallingTestsPropertiesAccessorsObject *self, GObject *some_object) { if (self->some_object == some_object) return; g_set_object (&self->some_object, some_object); g_object_notify (G_OBJECT (self), "some-object"); } /** * gi_marshalling_tests_properties_accessors_object_set_flags: (set-property some-flags) * @self: * @some_flags: */ void gi_marshalling_tests_properties_accessors_object_set_flags (GIMarshallingTestsPropertiesAccessorsObject *self, GIMarshallingTestsFlags some_flags) { if (self->some_flags == some_flags) return; self->some_flags = some_flags; g_object_notify (G_OBJECT (self), "some-flags"); } /** * gi_marshalling_tests_properties_accessors_object_set_enum: (set-property some-enum) * @self: * @some_enum: */ void gi_marshalling_tests_properties_accessors_object_set_enum (GIMarshallingTestsPropertiesAccessorsObject *self, GIMarshallingTestsGEnum some_enum) { if (self->some_enum == some_enum) return; self->some_enum = some_enum; g_object_notify (G_OBJECT (self), "some-enum"); } /** * gi_marshalling_tests_properties_accessors_object_set_byte_array: (set-property some-byte-array) * @self: * @some_byte_array: */ void gi_marshalling_tests_properties_accessors_object_set_byte_array (GIMarshallingTestsPropertiesAccessorsObject *self, GByteArray *some_byte_array) { if (self->some_byte_array == some_byte_array) return; g_clear_pointer (&self->some_byte_array, g_byte_array_unref); self->some_byte_array = g_byte_array_ref (some_byte_array); g_object_notify (G_OBJECT (self), "some-byte-array"); } /** * gi_marshalling_tests_properties_accessors_object_set_deprecated_int: (set-property some-deprecated-int) * @self: * @some_deprecated_int: */ void gi_marshalling_tests_properties_accessors_object_set_deprecated_int (GIMarshallingTestsPropertiesAccessorsObject *self, gint some_deprecated_int) { if (self->some_deprecated_int == some_deprecated_int) return; self->some_deprecated_int = some_deprecated_int; g_object_notify (G_OBJECT (self), "some-deprecated-int"); } /** * gi_marshalling_tests_properties_accessors_object_get_boolean: (get-property some-boolean) * @self: */ gboolean gi_marshalling_tests_properties_accessors_object_get_boolean (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_boolean; } /** * gi_marshalling_tests_properties_accessors_object_get_char: (get-property some-char) * @self: */ gchar gi_marshalling_tests_properties_accessors_object_get_char (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_char; } /** * gi_marshalling_tests_properties_accessors_object_get_uchar: (get-property some-uchar) * @self: */ guchar gi_marshalling_tests_properties_accessors_object_get_uchar (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_uchar; } /** * gi_marshalling_tests_properties_accessors_object_get_int: (get-property some-int) * @self: */ gint gi_marshalling_tests_properties_accessors_object_get_int (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_int; } /** * gi_marshalling_tests_properties_accessors_object_get_uint: (get-property some-uint) * @self: */ guint gi_marshalling_tests_properties_accessors_object_get_uint (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_uint; } /** * gi_marshalling_tests_properties_accessors_object_get_long: (get-property some-long) * @self: */ glong gi_marshalling_tests_properties_accessors_object_get_long (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_long; } /** * gi_marshalling_tests_properties_accessors_object_get_ulong: (get-property some-ulong) * @self: */ gulong gi_marshalling_tests_properties_accessors_object_get_ulong (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_ulong; } /** * gi_marshalling_tests_properties_accessors_object_get_int64: (get-property some-int64) * @self: */ gint64 gi_marshalling_tests_properties_accessors_object_get_int64 (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_int64; } /** * gi_marshalling_tests_properties_accessors_object_get_uint64: (get-property some-uint64) * @self: */ guint64 gi_marshalling_tests_properties_accessors_object_get_uint64 (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_uint64; } /** * gi_marshalling_tests_properties_accessors_object_get_float: (get-property some-float) * @self: */ gfloat gi_marshalling_tests_properties_accessors_object_get_float (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_float; } /** * gi_marshalling_tests_properties_accessors_object_get_double: (get-property some-double) * @self: */ gdouble gi_marshalling_tests_properties_accessors_object_get_double (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_double; } /** * gi_marshalling_tests_properties_accessors_object_get_string: (get-property some-string) * @self: */ const gchar * gi_marshalling_tests_properties_accessors_object_get_string (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_string; } /** * gi_marshalling_tests_properties_accessors_object_get_strv: (get-property some-strv) * @self: * * Returns: (transfer none): */ gchar ** gi_marshalling_tests_properties_accessors_object_get_strv (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_strv; } /** * gi_marshalling_tests_properties_accessors_object_get_boxed_struct: (get-property some-boxed-struct) * @self: * * Returns: (transfer none): */ GIMarshallingTestsBoxedStruct * gi_marshalling_tests_properties_accessors_object_get_boxed_struct (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_boxed_struct; } /** * gi_marshalling_tests_properties_accessors_object_get_boxed_glist: (get-property some-boxed-glist) * @self: * * Returns: (element-type int) (transfer none): */ GList * gi_marshalling_tests_properties_accessors_object_get_boxed_glist (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_boxed_glist; } /** * gi_marshalling_tests_properties_accessors_object_get_gvalue: (get-property some-gvalue) * @self: * * Returns: (transfer none): */ GValue * gi_marshalling_tests_properties_accessors_object_get_gvalue (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_gvalue; } /** * gi_marshalling_tests_properties_accessors_object_get_variant: (get-property some-variant) * @self: * * Returns: (transfer none): */ GVariant * gi_marshalling_tests_properties_accessors_object_get_variant (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_variant; } /** * gi_marshalling_tests_properties_accessors_object_get_object: (get-property some-object) * @self: * * Returns: (transfer none): */ GObject * gi_marshalling_tests_properties_accessors_object_get_object (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_object; } /** * gi_marshalling_tests_properties_accessors_object_get_flags: (get-property some-flags) * @self: */ GIMarshallingTestsFlags gi_marshalling_tests_properties_accessors_object_get_flags (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_flags; } /** * gi_marshalling_tests_properties_accessors_object_get_enum: (get-property some-enum) * @self: */ GIMarshallingTestsGEnum gi_marshalling_tests_properties_accessors_object_get_enum (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_enum; } /** * gi_marshalling_tests_properties_accessors_object_get_byte_array: (get-property some-byte-array) * @self: * * Returns: (transfer none): */ GByteArray * gi_marshalling_tests_properties_accessors_object_get_byte_array (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_byte_array; } /** * gi_marshalling_tests_properties_accessors_object_get_readonly: (get-property some-readonly) * @self: */ gint gi_marshalling_tests_properties_accessors_object_get_readonly (GIMarshallingTestsPropertiesAccessorsObject *self G_GNUC_UNUSED) { return 42; } /** * gi_marshalling_tests_properties_accessors_object_get_deprecated_int: (get-property some-deprecated-int) * @self: */ gint gi_marshalling_tests_properties_accessors_object_get_deprecated_int (GIMarshallingTestsPropertiesAccessorsObject *self) { return self->some_deprecated_int; } G_DEFINE_TYPE (GIMarshallingTestsSignalsObject, gi_marshalling_tests_signals_object, G_TYPE_OBJECT); static void gi_marshalling_tests_signals_object_init (GIMarshallingTestsSignalsObject *object G_GNUC_UNUSED) { } static void gi_marshalling_tests_signals_object_finalize (GObject *object) { G_OBJECT_CLASS (gi_marshalling_tests_signals_object_parent_class)->finalize (object); } static void gi_marshalling_tests_signals_object_class_init (GIMarshallingTestsSignalsObjectClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gi_marshalling_tests_signals_object_finalize; /** * GIMarshallingTestsSignalsObject::some-boxed-gptrarray-utf8: * @self: * @arg: (element-type utf8): */ g_signal_new ("some-boxed-gptrarray-utf8", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_PTR_ARRAY); /** * GIMarshallingTestsSignalsObject::some-boxed-gptrarray-utf8-container: * @self: * @arg: (element-type utf8) (transfer container): */ g_signal_new ("some-boxed-gptrarray-utf8-container", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_PTR_ARRAY); /** * GIMarshallingTestsSignalsObject::some-boxed-gptrarray-utf8-full: * @self: * @arg: (element-type utf8) (transfer full): */ g_signal_new ("some-boxed-gptrarray-utf8-full", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_PTR_ARRAY); /** * GIMarshallingTestsSignalsObject::some-boxed-gptrarray-boxed-struct: * @self: * @arg: (element-type GIMarshallingTestsBoxedStruct): */ g_signal_new ("some-boxed-gptrarray-boxed-struct", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_PTR_ARRAY); /** * GIMarshallingTestsSignalsObject::some-boxed-gptrarray-boxed-struct-container: * @self: * @arg: (element-type GIMarshallingTestsBoxedStruct) (transfer container): */ g_signal_new ("some-boxed-gptrarray-boxed-struct-container", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_PTR_ARRAY); /** * GIMarshallingTestsSignalsObject::some-boxed-gptrarray-boxed-struct-full: * @self: * @arg: (element-type GIMarshallingTestsBoxedStruct) (transfer full): */ g_signal_new ("some-boxed-gptrarray-boxed-struct-full", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_PTR_ARRAY); /** * GIMarshallingTestsSignalsObject::some-hash-table-utf8-int: * @self: * @arg: (type GHashTable) (element-type utf8 int): */ g_signal_new ("some-hash-table-utf8-int", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_HASH_TABLE); /** * GIMarshallingTestsSignalsObject::some-hash-table-utf8-int-container: * @self: * @arg: (type GHashTable) (element-type utf8 int) (transfer container): */ g_signal_new ("some-hash-table-utf8-int-container", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_HASH_TABLE); /** * GIMarshallingTestsSignalsObject::some-hash-table-utf8-int-full: * @self: * @arg: (type GHashTable) (element-type utf8 int) (transfer full): */ g_signal_new ("some-hash-table-utf8-int-full", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_HASH_TABLE); /** * GIMarshallingTestsSignalsObject::some-boxed-struct: * @self: * @arg: */ g_signal_new ("some-boxed-struct", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, gi_marshalling_tests_boxed_struct_get_type ()); /** * GIMarshallingTestsSignalsObject::some-boxed-struct-full: * @self: * @arg: (transfer full): */ g_signal_new ("some-boxed-struct-full", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, gi_marshalling_tests_boxed_struct_get_type ()); } GIMarshallingTestsSignalsObject * gi_marshalling_tests_signals_object_new (void) { return g_object_new (GI_MARSHALLING_TESTS_TYPE_SIGNALS_OBJECT, NULL); } void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_utf8 (GIMarshallingTestsSignalsObject *object) { GPtrArray *ptrarray; ptrarray = gi_marshalling_tests_gptrarray_utf8_container_return (); g_signal_emit_by_name (object, "some-boxed-gptrarray-utf8", ptrarray); g_ptr_array_unref (ptrarray); } void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_utf8_container (GIMarshallingTestsSignalsObject *object) { g_signal_emit_by_name (object, "some-boxed-gptrarray-utf8-container", gi_marshalling_tests_gptrarray_utf8_container_return ()); } void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_utf8_full (GIMarshallingTestsSignalsObject *object) { g_signal_emit_by_name (object, "some-boxed-gptrarray-utf8-full", gi_marshalling_tests_gptrarray_utf8_full_return ()); } void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_boxed_struct (GIMarshallingTestsSignalsObject *object) { GPtrArray *ptrarray; ptrarray = gi_marshalling_tests_gptrarray_boxed_struct_full_return (); g_signal_emit_by_name (object, "some-boxed-gptrarray-boxed-struct", ptrarray); g_ptr_array_set_free_func (ptrarray, (GDestroyNotify) gi_marshalling_tests_boxed_struct_free); g_ptr_array_unref (ptrarray); } void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_boxed_struct_container (GIMarshallingTestsSignalsObject *object) { GPtrArray *ptrarray; ptrarray = gi_marshalling_tests_gptrarray_boxed_struct_full_return (); g_ptr_array_set_free_func (ptrarray, (GDestroyNotify) gi_marshalling_tests_boxed_struct_free); g_signal_emit_by_name (object, "some-boxed-gptrarray-boxed-struct-container", g_steal_pointer (&ptrarray)); } void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_boxed_struct_full (GIMarshallingTestsSignalsObject *object) { g_signal_emit_by_name (object, "some-boxed-gptrarray-boxed-struct-full", gi_marshalling_tests_gptrarray_boxed_struct_full_return ()); } void gi_marshalling_tests_signals_object_emit_hash_table_utf8_int (GIMarshallingTestsSignalsObject *object) { GHashTable *hash_table; hash_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); g_hash_table_insert (hash_table, g_strdup ("-1"), GINT_TO_POINTER (1)); g_hash_table_insert (hash_table, g_strdup ("0"), GINT_TO_POINTER (0)); g_hash_table_insert (hash_table, g_strdup ("1"), GINT_TO_POINTER (-1)); g_hash_table_insert (hash_table, g_strdup ("2"), GINT_TO_POINTER (-2)); g_signal_emit_by_name (object, "some-hash-table-utf8-int", hash_table); g_hash_table_unref (hash_table); } void gi_marshalling_tests_signals_object_emit_hash_table_utf8_int_container (GIMarshallingTestsSignalsObject *object) { GHashTable *hash_table; hash_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); g_hash_table_insert (hash_table, g_strdup ("-1"), GINT_TO_POINTER (1)); g_hash_table_insert (hash_table, g_strdup ("0"), GINT_TO_POINTER (0)); g_hash_table_insert (hash_table, g_strdup ("1"), GINT_TO_POINTER (-1)); g_hash_table_insert (hash_table, g_strdup ("2"), GINT_TO_POINTER (-2)); g_signal_emit_by_name (object, "some-hash-table-utf8-int-container", g_steal_pointer (&hash_table)); } void gi_marshalling_tests_signals_object_emit_hash_table_utf8_int_full (GIMarshallingTestsSignalsObject *object) { GHashTable *hash_table; hash_table = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (hash_table, g_strdup ("-1"), GINT_TO_POINTER (1)); g_hash_table_insert (hash_table, g_strdup ("0"), GINT_TO_POINTER (0)); g_hash_table_insert (hash_table, g_strdup ("1"), GINT_TO_POINTER (-1)); g_hash_table_insert (hash_table, g_strdup ("2"), GINT_TO_POINTER (-2)); g_signal_emit_by_name (object, "some-hash-table-utf8-int-full", g_steal_pointer (&hash_table)); } void gi_marshalling_tests_signals_object_emit_boxed_struct (GIMarshallingTestsSignalsObject *object) { GIMarshallingTestsBoxedStruct *boxed = gi_marshalling_tests_boxed_struct_new (); boxed->long_ = 99; boxed->string_ = g_strdup ("a string"); boxed->g_strv = g_strdupv ((GStrv) (const char *[]){ "foo", "bar", "baz", NULL }); g_signal_emit_by_name (object, "some-boxed-struct", boxed); g_clear_pointer (&boxed, gi_marshalling_tests_boxed_struct_free); } void gi_marshalling_tests_signals_object_emit_boxed_struct_full (GIMarshallingTestsSignalsObject *object) { GIMarshallingTestsBoxedStruct *boxed = gi_marshalling_tests_boxed_struct_new (); boxed->long_ = 99; boxed->string_ = g_strdup ("a string"); boxed->g_strv = g_strdupv ((GStrv) (const char *[]){ "foo", "bar", "baz", NULL }); g_signal_emit_by_name (object, "some-boxed-struct-full", g_steal_pointer (&boxed)); } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/gimarshallingtests.h0000664000000000000000000026567215056773103026462 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2010-2012 Collabora, Ltd. SPDX-FileCopyrightText: 2010 Johan Dahlin SPDX-FileCopyrightText: 2010 Sugar Labs SPDX-FileCopyrightText: 2010 Zach Goldberg SPDX-FileCopyrightText: 2011 Alex Eftimie SPDX-FileCopyrightText: 2011-2012 Canonical Ltd. SPDX-FileCopyrightText: 2011-2012 Colin Walters SPDX-FileCopyrightText: 2011 Dan Winship SPDX-FileCopyrightText: 2011-2012 Giovanni Campagna SPDX-FileCopyrightText: 2011 Ignacio Casal Quinteiro SPDX-FileCopyrightText: 2011-2012 Jasper St. Pierre SPDX-FileCopyrightText: 2011 Laszlo Pandy SPDX-FileCopyrightText: 2011, 2013 Red Hat, Inc. SPDX-FileCopyrightText: 2012 Bastian Winkler SPDX-FileCopyrightText: 2012 Epitech SPDX-FileCopyrightText: 2012 Gonzalo Odiard SPDX-FileCopyrightText: 2012-2013 Martin Pitt SPDX-FileCopyrightText: 2012-2013 Paolo Borelli SPDX-FileCopyrightText: 2012 Sebastian Pölsterl SPDX-FileCopyrightText: 2013 Simon Feltman SPDX-FileCopyrightText: 2014 Lionel Landwerlin SPDX-FileCopyrightText: 2014 RIFT.io, Inc. SPDX-FileCopyrightText: 2014 SuSE SPDX-FileCopyrightText: 2016 Endless Mobile, Inc. SPDX-FileCopyrightText: 2017 Christoph Reiter SPDX-FileCopyrightText: 2016-2017, 2023, 2025 Philip Chimento SPDX-FileCopyrightText: 2018 Tomasz MiÄ…sko SPDX-FileCopyrightText: 2019 Stéphane Seng SPDX-FileCopyrightText: 2020-2023 Marco Trevisan SPDX-FileCopyrightText: 2020, 2024 Simon McVittie SPDX-FileCopyrightText: 2021 Carlos Garnacho */ #pragma once #include /* size_t */ #include /* off_t, time_t */ #include #include #ifdef G_OS_UNIX #include #endif #include "gitestmacros.h" typedef struct _GIMarshallingTestsSimpleStruct GIMarshallingTestsSimpleStruct; typedef struct _GIMarshallingTestsBoxedStruct GIMarshallingTestsBoxedStruct; /* Constants */ #define GI_MARSHALLING_TESTS_CONSTANT_NUMBER 42 #define GI_MARSHALLING_TESTS_CONSTANT_UTF8 "const \xe2\x99\xa5 utf8" #define GI_MARSHALLING_TESTS_CONSTANT_UCS4 { 0x63, 0x6f, 0x6e, 0x73, 0x74, \ 0x20, 0x2665, 0x20, 0x75, 0x74, \ 0x66, 0x38 } GI_TEST_EXTERN void gi_marshalling_tests_cleanup_unaligned_buffer (void); /* Booleans */ GI_TEST_EXTERN gboolean gi_marshalling_tests_boolean_return_true (void); GI_TEST_EXTERN gboolean gi_marshalling_tests_boolean_return_false (void); GI_TEST_EXTERN void gi_marshalling_tests_boolean_in_true (gboolean v); GI_TEST_EXTERN void gi_marshalling_tests_boolean_in_false (gboolean v); GI_TEST_EXTERN void gi_marshalling_tests_boolean_out_true (gboolean *v); GI_TEST_EXTERN void gi_marshalling_tests_boolean_out_false (gboolean *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_boolean_out_uninitialized (gboolean *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_boolean_inout_true_false (gboolean *v); GI_TEST_EXTERN void gi_marshalling_tests_boolean_inout_false_true (gboolean *v); /* Integers */ GI_TEST_EXTERN gint8 gi_marshalling_tests_int8_return_max (void); GI_TEST_EXTERN gint8 gi_marshalling_tests_int8_return_min (void); GI_TEST_EXTERN void gi_marshalling_tests_int8_in_max (gint8 v); GI_TEST_EXTERN void gi_marshalling_tests_int8_in_min (gint8 v); GI_TEST_EXTERN void gi_marshalling_tests_int8_out_max (gint8 *v); GI_TEST_EXTERN void gi_marshalling_tests_int8_out_min (gint8 *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_int8_out_uninitialized (gint8 *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_int8_inout_max_min (gint8 *v); GI_TEST_EXTERN void gi_marshalling_tests_int8_inout_min_max (gint8 *v); GI_TEST_EXTERN guint8 gi_marshalling_tests_uint8_return (void); GI_TEST_EXTERN void gi_marshalling_tests_uint8_in (guint8 v); GI_TEST_EXTERN void gi_marshalling_tests_uint8_out (guint8 *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_uint8_out_uninitialized (guint8 *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_uint8_inout (guint8 *v); GI_TEST_EXTERN gint16 gi_marshalling_tests_int16_return_max (void); GI_TEST_EXTERN gint16 gi_marshalling_tests_int16_return_min (void); GI_TEST_EXTERN void gi_marshalling_tests_int16_in_max (gint16 v); GI_TEST_EXTERN void gi_marshalling_tests_int16_in_min (gint16 v); GI_TEST_EXTERN void gi_marshalling_tests_int16_out_max (gint16 *v); GI_TEST_EXTERN void gi_marshalling_tests_int16_out_min (gint16 *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_int16_out_uninitialized (gint16 *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_int16_inout_max_min (gint16 *v); GI_TEST_EXTERN void gi_marshalling_tests_int16_inout_min_max (gint16 *v); GI_TEST_EXTERN guint16 gi_marshalling_tests_uint16_return (void); GI_TEST_EXTERN void gi_marshalling_tests_uint16_in (guint16 v); GI_TEST_EXTERN void gi_marshalling_tests_uint16_out (guint16 *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_uint16_out_uninitialized (guint16 *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_uint16_inout (guint16 *v); GI_TEST_EXTERN gint32 gi_marshalling_tests_int32_return_max (void); GI_TEST_EXTERN gint32 gi_marshalling_tests_int32_return_min (void); GI_TEST_EXTERN void gi_marshalling_tests_int32_in_max (gint32 v); GI_TEST_EXTERN void gi_marshalling_tests_int32_in_min (gint32 v); GI_TEST_EXTERN void gi_marshalling_tests_int32_out_max (gint32 *v); GI_TEST_EXTERN void gi_marshalling_tests_int32_out_min (gint32 *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_int32_out_uninitialized (gint32 *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_int32_inout_max_min (gint32 *v); GI_TEST_EXTERN void gi_marshalling_tests_int32_inout_min_max (gint32 *v); GI_TEST_EXTERN guint32 gi_marshalling_tests_uint32_return (void); GI_TEST_EXTERN void gi_marshalling_tests_uint32_in (guint32 v); GI_TEST_EXTERN void gi_marshalling_tests_uint32_out (guint32 *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_uint32_out_uninitialized (guint32 *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_uint32_inout (guint32 *v); GI_TEST_EXTERN gint64 gi_marshalling_tests_int64_return_max (void); GI_TEST_EXTERN gint64 gi_marshalling_tests_int64_return_min (void); GI_TEST_EXTERN void gi_marshalling_tests_int64_in_max (gint64 v); GI_TEST_EXTERN void gi_marshalling_tests_int64_in_min (gint64 v); GI_TEST_EXTERN void gi_marshalling_tests_int64_out_max (gint64 *v); GI_TEST_EXTERN void gi_marshalling_tests_int64_out_min (gint64 *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_int64_out_uninitialized (gint64 *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_int64_inout_max_min (gint64 *v); GI_TEST_EXTERN void gi_marshalling_tests_int64_inout_min_max (gint64 *v); GI_TEST_EXTERN guint64 gi_marshalling_tests_uint64_return (void); GI_TEST_EXTERN void gi_marshalling_tests_uint64_in (guint64 v); GI_TEST_EXTERN void gi_marshalling_tests_uint64_out (guint64 *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_uint64_out_uninitialized (guint64 *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_uint64_inout (guint64 *v); GI_TEST_EXTERN gshort gi_marshalling_tests_short_return_max (void); GI_TEST_EXTERN gshort gi_marshalling_tests_short_return_min (void); GI_TEST_EXTERN void gi_marshalling_tests_short_in_max (gshort short_); GI_TEST_EXTERN void gi_marshalling_tests_short_in_min (gshort short_); GI_TEST_EXTERN void gi_marshalling_tests_short_out_max (gshort *short_); GI_TEST_EXTERN void gi_marshalling_tests_short_out_min (gshort *short_); GI_TEST_EXTERN gboolean gi_marshalling_tests_short_out_uninitialized (gshort *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_short_inout_max_min (gshort *short_); GI_TEST_EXTERN void gi_marshalling_tests_short_inout_min_max (gshort *short_); GI_TEST_EXTERN gushort gi_marshalling_tests_ushort_return (void); GI_TEST_EXTERN void gi_marshalling_tests_ushort_in (gushort ushort_); GI_TEST_EXTERN void gi_marshalling_tests_ushort_out (gushort *ushort_); GI_TEST_EXTERN gboolean gi_marshalling_tests_ushort_out_uninitialized (gushort *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_ushort_inout (gushort *ushort_); GI_TEST_EXTERN gint gi_marshalling_tests_int_return_max (void); GI_TEST_EXTERN gint gi_marshalling_tests_int_return_min (void); GI_TEST_EXTERN void gi_marshalling_tests_int_in_max (gint int_); GI_TEST_EXTERN void gi_marshalling_tests_int_in_min (gint int_); GI_TEST_EXTERN void gi_marshalling_tests_int_out_max (gint *int_); GI_TEST_EXTERN void gi_marshalling_tests_int_out_min (gint *int_); GI_TEST_EXTERN gboolean gi_marshalling_tests_int_out_uninitialized (gint *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_int_inout_max_min (gint *int_); GI_TEST_EXTERN void gi_marshalling_tests_int_inout_min_max (gint *int_); GI_TEST_EXTERN guint gi_marshalling_tests_uint_return (void); GI_TEST_EXTERN void gi_marshalling_tests_uint_in (guint uint_); GI_TEST_EXTERN void gi_marshalling_tests_uint_out (guint *uint_); GI_TEST_EXTERN gboolean gi_marshalling_tests_uint_out_uninitialized (guint *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_uint_inout (guint *uint_); GI_TEST_EXTERN glong gi_marshalling_tests_long_return_max (void); GI_TEST_EXTERN glong gi_marshalling_tests_long_return_min (void); GI_TEST_EXTERN void gi_marshalling_tests_long_in_max (glong long_); GI_TEST_EXTERN void gi_marshalling_tests_long_in_min (glong long_); GI_TEST_EXTERN void gi_marshalling_tests_long_out_max (glong *long_); GI_TEST_EXTERN void gi_marshalling_tests_long_out_min (glong *long_); GI_TEST_EXTERN gboolean gi_marshalling_tests_long_out_uninitialized (glong *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_long_inout_max_min (glong *long_); GI_TEST_EXTERN void gi_marshalling_tests_long_inout_min_max (glong *long_); GI_TEST_EXTERN gulong gi_marshalling_tests_ulong_return (void); GI_TEST_EXTERN void gi_marshalling_tests_ulong_in (gulong ulong_); GI_TEST_EXTERN void gi_marshalling_tests_ulong_out (gulong *ulong_); GI_TEST_EXTERN void gi_marshalling_tests_ulong_inout (gulong *ulong_); GI_TEST_EXTERN gboolean gi_marshalling_tests_ulong_out_uninitialized (gulong *v G_GNUC_UNUSED); GI_TEST_EXTERN gssize gi_marshalling_tests_ssize_return_max (void); GI_TEST_EXTERN gssize gi_marshalling_tests_ssize_return_min (void); GI_TEST_EXTERN void gi_marshalling_tests_ssize_in_max (gssize ssize); GI_TEST_EXTERN void gi_marshalling_tests_ssize_in_min (gssize ssize); GI_TEST_EXTERN void gi_marshalling_tests_ssize_out_max (gssize *ssize); GI_TEST_EXTERN void gi_marshalling_tests_ssize_out_min (gssize *ssize); GI_TEST_EXTERN gboolean gi_marshalling_tests_ssize_out_uninitialized (gssize *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_ssize_inout_max_min (gssize *ssize); GI_TEST_EXTERN void gi_marshalling_tests_ssize_inout_min_max (gssize *ssize); GI_TEST_EXTERN gsize gi_marshalling_tests_size_return (void); GI_TEST_EXTERN void gi_marshalling_tests_size_in (gsize size); GI_TEST_EXTERN void gi_marshalling_tests_size_out (gsize *size); GI_TEST_EXTERN gboolean gi_marshalling_tests_size_out_uninitialized (gsize *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_size_inout (gsize *size); /* Floating-point */ GI_TEST_EXTERN gfloat gi_marshalling_tests_float_return (void); GI_TEST_EXTERN void gi_marshalling_tests_float_in (gfloat v); GI_TEST_EXTERN void gi_marshalling_tests_float_out (gfloat *v); GI_TEST_EXTERN void gi_marshalling_tests_float_noncanonical_nan_out (gfloat *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_float_out_uninitialized (gfloat *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_float_inout (gfloat *v); GI_TEST_EXTERN gdouble gi_marshalling_tests_double_return (void); GI_TEST_EXTERN void gi_marshalling_tests_double_in (gdouble v); GI_TEST_EXTERN void gi_marshalling_tests_double_out (gdouble *v); GI_TEST_EXTERN void gi_marshalling_tests_double_noncanonical_nan_out (gdouble *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_double_out_uninitialized (gdouble *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_double_inout (gdouble *v); /* Timestamps */ GI_TEST_EXTERN time_t gi_marshalling_tests_time_t_return (void); GI_TEST_EXTERN void gi_marshalling_tests_time_t_in (time_t v); GI_TEST_EXTERN void gi_marshalling_tests_time_t_out (time_t *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_time_t_out_uninitialized (time_t *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_time_t_inout (time_t *v); /* Platform file offset (avoid this, use goffset instead) */ GI_TEST_EXTERN off_t gi_marshalling_tests_off_t_return (void); GI_TEST_EXTERN void gi_marshalling_tests_off_t_in (off_t v); GI_TEST_EXTERN void gi_marshalling_tests_off_t_out (off_t *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_off_t_out_uninitialized (off_t *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_off_t_inout (off_t *v); #ifdef G_OS_UNIX /* Unix device number */ GI_TEST_EXTERN dev_t gi_marshalling_tests_dev_t_return (void); GI_TEST_EXTERN void gi_marshalling_tests_dev_t_in (dev_t v); GI_TEST_EXTERN void gi_marshalling_tests_dev_t_out (dev_t *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_dev_t_out_uninitialized (dev_t *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_dev_t_inout (dev_t *v); /* Unix group */ GI_TEST_EXTERN gid_t gi_marshalling_tests_gid_t_return (void); GI_TEST_EXTERN void gi_marshalling_tests_gid_t_in (gid_t v); GI_TEST_EXTERN void gi_marshalling_tests_gid_t_out (gid_t *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_gid_t_out_uninitialized (gid_t *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gid_t_inout (gid_t *v); /* Unix process */ GI_TEST_EXTERN pid_t gi_marshalling_tests_pid_t_return (void); GI_TEST_EXTERN void gi_marshalling_tests_pid_t_in (pid_t v); GI_TEST_EXTERN void gi_marshalling_tests_pid_t_out (pid_t *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_pid_t_out_uninitialized (pid_t *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_pid_t_inout (pid_t *v); /* Unix socket address length */ GI_TEST_EXTERN socklen_t gi_marshalling_tests_socklen_t_return (void); GI_TEST_EXTERN void gi_marshalling_tests_socklen_t_in (socklen_t v); GI_TEST_EXTERN void gi_marshalling_tests_socklen_t_out (socklen_t *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_socklen_t_out_uninitialized (socklen_t *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_socklen_t_inout (socklen_t *v); /* Unix user */ GI_TEST_EXTERN uid_t gi_marshalling_tests_uid_t_return (void); GI_TEST_EXTERN void gi_marshalling_tests_uid_t_in (uid_t v); GI_TEST_EXTERN void gi_marshalling_tests_uid_t_out (uid_t *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_uid_t_out_uninitialized (uid_t *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_uid_t_inout (uid_t *v); #endif /* G_OS_UNIX */ /* GType */ GI_TEST_EXTERN GType gi_marshalling_tests_gtype_return (void); GI_TEST_EXTERN GType gi_marshalling_tests_gtype_string_return (void); GI_TEST_EXTERN void gi_marshalling_tests_gtype_in (GType gtype); GI_TEST_EXTERN void gi_marshalling_tests_gtype_string_in (GType gtype); GI_TEST_EXTERN void gi_marshalling_tests_gtype_out (GType *gtype); GI_TEST_EXTERN gboolean gi_marshalling_tests_gtype_out_uninitialized (GType *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gtype_string_out (GType *gtype); GI_TEST_EXTERN void gi_marshalling_tests_gtype_inout (GType *gtype); /* UTF-8 */ GI_TEST_EXTERN const gchar *gi_marshalling_tests_utf8_none_return (void); GI_TEST_EXTERN gchar *gi_marshalling_tests_utf8_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_utf8_none_in (const gchar *utf8); GI_TEST_EXTERN void gi_marshalling_tests_utf8_full_in (gchar *utf8); GI_TEST_EXTERN void gi_marshalling_tests_utf8_none_out (const gchar **utf8); GI_TEST_EXTERN gboolean gi_marshalling_tests_utf8_none_out_uninitialized (const gchar **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_utf8_full_out (gchar **utf8); GI_TEST_EXTERN void gi_marshalling_tests_utf8_dangling_out (gchar **utf8); GI_TEST_EXTERN void gi_marshalling_tests_utf8_none_inout (const gchar **utf8); GI_TEST_EXTERN void gi_marshalling_tests_utf8_full_inout (gchar **utf8); GI_TEST_EXTERN GSList *gi_marshalling_tests_filename_list_return (void); GI_TEST_EXTERN void gi_marshalling_tests_utf8_as_uint8array_in (const guint8 *array, gsize len); /* Enum */ typedef enum { GI_MARSHALLING_TESTS_ENUM_VALUE1, GI_MARSHALLING_TESTS_ENUM_VALUE2, GI_MARSHALLING_TESTS_ENUM_VALUE3 = 42 } GIMarshallingTestsEnum; typedef enum { GI_MARSHALLING_TESTS_SECOND_ENUM_SECONDVALUE1, GI_MARSHALLING_TESTS_SECOND_ENUM_SECONDVALUE2, } GIMarshallingTestsSecondEnum; GI_TEST_EXTERN GIMarshallingTestsEnum gi_marshalling_tests_enum_returnv (void); GI_TEST_EXTERN void gi_marshalling_tests_enum_in (GIMarshallingTestsEnum v); GI_TEST_EXTERN void gi_marshalling_tests_enum_out (GIMarshallingTestsEnum *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_enum_out_uninitialized (GIMarshallingTestsEnum **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_enum_inout (GIMarshallingTestsEnum *v); /* GEnum */ typedef enum { GI_MARSHALLING_TESTS_GENUM_VALUE1, GI_MARSHALLING_TESTS_GENUM_VALUE2, GI_MARSHALLING_TESTS_GENUM_VALUE3 = 42 } GIMarshallingTestsGEnum; GI_TEST_EXTERN GType gi_marshalling_tests_genum_get_type (void) G_GNUC_CONST; #define GI_MARSHALLING_TESTS_TYPE_GENUM (gi_marshalling_tests_genum_get_type ()) GI_TEST_EXTERN GIMarshallingTestsGEnum gi_marshalling_tests_genum_returnv (void); GI_TEST_EXTERN void gi_marshalling_tests_genum_in (GIMarshallingTestsGEnum v); GI_TEST_EXTERN void gi_marshalling_tests_genum_out (GIMarshallingTestsGEnum *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_genum_out_uninitialized (GIMarshallingTestsGEnum *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_genum_inout (GIMarshallingTestsGEnum *v); /* GFlags */ typedef enum { GI_MARSHALLING_TESTS_FLAGS_VALUE1 = 1 << 0, GI_MARSHALLING_TESTS_FLAGS_VALUE2 = 1 << 1, GI_MARSHALLING_TESTS_FLAGS_VALUE3 = 1 << 2, GI_MARSHALLING_TESTS_FLAGS_MASK = GI_MARSHALLING_TESTS_FLAGS_VALUE1 | GI_MARSHALLING_TESTS_FLAGS_VALUE2, GI_MARSHALLING_TESTS_FLAGS_MASK2 = GI_MARSHALLING_TESTS_FLAGS_MASK } GIMarshallingTestsFlags; GI_TEST_EXTERN GType gi_marshalling_tests_flags_get_type (void) G_GNUC_CONST; #define GI_MARSHALLING_TESTS_TYPE_FLAGS (gi_marshalling_tests_flags_get_type ()) GI_TEST_EXTERN GIMarshallingTestsFlags gi_marshalling_tests_flags_returnv (void); GI_TEST_EXTERN void gi_marshalling_tests_flags_in (GIMarshallingTestsFlags v); GI_TEST_EXTERN void gi_marshalling_tests_flags_in_zero (GIMarshallingTestsFlags v); GI_TEST_EXTERN void gi_marshalling_tests_flags_out (GIMarshallingTestsFlags *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_flags_out_uninitialized (GIMarshallingTestsFlags *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_flags_inout (GIMarshallingTestsFlags *v); /* Flags with no GType */ typedef enum { GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_VALUE1 = 1 << 0, GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_VALUE2 = 1 << 1, GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_VALUE3 = 1 << 2, GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_MASK = GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_VALUE1 | GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_VALUE2, GI_MARSHALLING_TESTS_NO_TYPE_FLAGS_MASK2 = GI_MARSHALLING_TESTS_FLAGS_MASK } GIMarshallingTestsNoTypeFlags; GI_TEST_EXTERN GIMarshallingTestsNoTypeFlags gi_marshalling_tests_no_type_flags_returnv (void); GI_TEST_EXTERN void gi_marshalling_tests_no_type_flags_in (GIMarshallingTestsNoTypeFlags v); GI_TEST_EXTERN void gi_marshalling_tests_no_type_flags_in_zero (GIMarshallingTestsNoTypeFlags v); GI_TEST_EXTERN void gi_marshalling_tests_no_type_flags_out (GIMarshallingTestsNoTypeFlags *v); GI_TEST_EXTERN gboolean gi_marshalling_tests_no_type_flags_out_uninitialized (GIMarshallingTestsNoTypeFlags **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_no_type_flags_inout (GIMarshallingTestsNoTypeFlags *v); /* Arrays */ GI_TEST_EXTERN gboolean gi_marshalling_tests_init_function (gint *n_args, char ***argv); /* Fixed-size */ GI_TEST_EXTERN const gint *gi_marshalling_tests_array_fixed_int_return (void); GI_TEST_EXTERN const gshort *gi_marshalling_tests_array_fixed_short_return (void); GI_TEST_EXTERN const guint8 *gi_marshalling_tests_array_fixed_return_unaligned (void); GI_TEST_EXTERN void gi_marshalling_tests_array_fixed_int_in (const gint *ints); GI_TEST_EXTERN void gi_marshalling_tests_array_fixed_caller_allocated_out (gint *ints); GI_TEST_EXTERN void gi_marshalling_tests_array_fixed_short_in (const gshort *shorts); GI_TEST_EXTERN void gi_marshalling_tests_array_fixed_out (gint **ints); GI_TEST_EXTERN gboolean gi_marshalling_tests_array_fixed_out_uninitialized (gint **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_array_fixed_out_unaligned (const guint8 **v); GI_TEST_EXTERN void gi_marshalling_tests_array_fixed_out_struct (GIMarshallingTestsSimpleStruct **structs); GI_TEST_EXTERN gboolean gi_marshalling_tests_array_fixed_out_struct_uninitialized (GIMarshallingTestsSimpleStruct **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_array_fixed_caller_allocated_struct_out (GIMarshallingTestsSimpleStruct *structs); GI_TEST_EXTERN void gi_marshalling_tests_array_fixed_inout (gint **ints); /* Variable-size */ GI_TEST_EXTERN const gint *gi_marshalling_tests_array_return (gint *length); GI_TEST_EXTERN const gint *gi_marshalling_tests_array_return_etc (gint first, gint *length, gint last, gint *sum); GI_TEST_EXTERN const guint8 *gi_marshalling_tests_array_return_unaligned (gsize *len); GI_TEST_EXTERN void gi_marshalling_tests_array_in (const gint *ints, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_in_len_before (gint length, const gint *ints); GI_TEST_EXTERN void gi_marshalling_tests_array_in_len_zero_terminated (const gint *ints, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_string_in (const gchar **strings, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_uint8_in (const guint8 *chars, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_int64_in (const gint64 *ints, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_uint64_in (const guint64 *ints, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_unichar_in (const gunichar *chars, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_bool_in (const gboolean *bools, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_struct_in (GIMarshallingTestsBoxedStruct **structs, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_struct_value_in (GIMarshallingTestsBoxedStruct *structs, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_struct_take_in (GIMarshallingTestsBoxedStruct **structs, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_simple_struct_in (GIMarshallingTestsSimpleStruct *structs, gint length); GI_TEST_EXTERN void gi_marshalling_tests_multi_array_key_value_in (gint length, const gchar **keys, const GValue *values); GI_TEST_EXTERN void gi_marshalling_tests_array_enum_in (GIMarshallingTestsEnum *_enum, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_flags_in (GIMarshallingTestsFlags *flags, gint length); GI_TEST_EXTERN void gi_marshalling_tests_array_in_guint64_len (const gint *ints, guint64 length); GI_TEST_EXTERN void gi_marshalling_tests_array_in_guint8_len (const gint *ints, guint8 length); GI_TEST_EXTERN void gi_marshalling_tests_array_out (gint **ints, gint *length); GI_TEST_EXTERN gboolean gi_marshalling_tests_array_out_uninitialized (gint **v G_GNUC_UNUSED, gint *length G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_array_out_unaligned (const guint8 **v, gsize *len); GI_TEST_EXTERN void gi_marshalling_tests_array_out_etc (gint first, gint **ints, gint *length, gint last, gint *sum); GI_TEST_EXTERN void gi_marshalling_tests_array_bool_out (const gboolean **bools, gint *length); GI_TEST_EXTERN void gi_marshalling_tests_array_unichar_out (const gunichar **chars, gint *length); GI_TEST_EXTERN void gi_marshalling_tests_array_inout (gint **ints, gint *length); GI_TEST_EXTERN void gi_marshalling_tests_array_inout_etc (gint first, gint **ints, gint *length, gint last, gint *sum); GI_TEST_EXTERN void gi_marshalling_tests_array_in_nonzero_nonlen (gint first, const guint8 *chars); /* Zero-terminated */ GI_TEST_EXTERN const gchar **gi_marshalling_tests_array_zero_terminated_return (void); GI_TEST_EXTERN gchar **gi_marshalling_tests_array_zero_terminated_return_null (void); GI_TEST_EXTERN GIMarshallingTestsBoxedStruct **gi_marshalling_tests_array_zero_terminated_return_struct (void); GI_TEST_EXTERN GIMarshallingTestsBoxedStruct *gi_marshalling_tests_array_zero_terminated_return_sequential_struct (void); GI_TEST_EXTERN gunichar *gi_marshalling_tests_array_zero_terminated_return_unichar (void); GI_TEST_EXTERN const guint8 *gi_marshalling_tests_array_zero_terminated_return_unaligned (void); GI_TEST_EXTERN void gi_marshalling_tests_array_zero_terminated_in (gchar **utf8s); GI_TEST_EXTERN void gi_marshalling_tests_array_zero_terminated_out (const gchar ***utf8s); GI_TEST_EXTERN gboolean gi_marshalling_tests_array_zero_terminated_out_uninitialized (const gchar ***v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_array_zero_terminated_out_unaligned (const guint8 **v); GI_TEST_EXTERN void gi_marshalling_tests_array_zero_terminated_inout (const gchar ***utf8s); GI_TEST_EXTERN GVariant **gi_marshalling_tests_array_gvariant_none_in (GVariant **variants); GI_TEST_EXTERN GVariant **gi_marshalling_tests_array_gvariant_container_in (GVariant **variants); GI_TEST_EXTERN GVariant **gi_marshalling_tests_array_gvariant_full_in (GVariant **variants); /* Full complement of array-of-UTF8 in/out tests for fixed-length array, * explicit-length array, zero-terminated array. GArray, GPtrArray, GList, and * GSList are already covered below. */ GI_TEST_EXTERN const gchar *const *gi_marshalling_tests_length_array_utf8_none_return (size_t *out_length); GI_TEST_EXTERN const gchar **gi_marshalling_tests_length_array_utf8_container_return (size_t *out_length); GI_TEST_EXTERN gchar **gi_marshalling_tests_length_array_utf8_full_return (size_t *out_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_utf8_none_in (const gchar *const *array, size_t length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_utf8_container_in (const gchar **array, size_t length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_utf8_full_in (gchar **array, size_t length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_utf8_none_out (const gchar *const **array_out, size_t *out_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_utf8_container_out (const gchar ***array_out, size_t *out_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_utf8_full_out (gchar ***array_out, size_t *out_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_utf8_none_inout (const gchar *const **array_inout, size_t *inout_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_utf8_container_inout (const gchar ***array_inout, size_t *inout_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_utf8_full_inout (gchar ***array_inout, size_t *inout_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_utf8_optional_inout (int *inout_length, char **array_inout[]); GI_TEST_EXTERN const gchar *const *gi_marshalling_tests_zero_terminated_array_utf8_none_return (void); GI_TEST_EXTERN const gchar **gi_marshalling_tests_zero_terminated_array_utf8_container_return (void); GI_TEST_EXTERN gchar **gi_marshalling_tests_zero_terminated_array_utf8_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_utf8_none_in (const gchar *const *array); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_utf8_container_in (const gchar **array); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_utf8_full_in (gchar **array); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_utf8_none_out (const gchar *const **array_out); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_utf8_container_out (const gchar ***array_out); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_utf8_full_out (gchar ***array_out); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_utf8_none_inout (const gchar *const **array_inout); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_utf8_container_inout (const gchar ***array_inout); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_utf8_full_inout (gchar ***array_inout); GI_TEST_EXTERN const gchar *const *gi_marshalling_tests_fixed_array_utf8_none_return (void); GI_TEST_EXTERN const gchar **gi_marshalling_tests_fixed_array_utf8_container_return (void); GI_TEST_EXTERN gchar **gi_marshalling_tests_fixed_array_utf8_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_utf8_none_in (const gchar *const *array); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_utf8_container_in (const gchar **array); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_utf8_full_in (gchar **array); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_utf8_none_out (const gchar *const **array_out); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_utf8_container_out (const gchar ***array_out); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_utf8_full_out (gchar ***array_out); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_utf8_none_inout (const gchar *const **array_inout); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_utf8_container_inout (const gchar ***array_inout); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_utf8_full_inout (gchar ***array_inout); /* GArray */ GI_TEST_EXTERN GArray *gi_marshalling_tests_garray_int_none_return (void); GI_TEST_EXTERN GArray *gi_marshalling_tests_garray_uint64_none_return (void); GI_TEST_EXTERN GArray *gi_marshalling_tests_garray_utf8_none_return (void); GI_TEST_EXTERN GArray *gi_marshalling_tests_garray_utf8_container_return (void); GI_TEST_EXTERN GArray *gi_marshalling_tests_garray_utf8_full_return (void); GI_TEST_EXTERN GArray *gi_marshalling_tests_garray_boxed_struct_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_garray_int_none_in (GArray *array_); GI_TEST_EXTERN void gi_marshalling_tests_garray_uint64_none_in (GArray *array_); GI_TEST_EXTERN void gi_marshalling_tests_garray_utf8_none_in (GArray *array_); GI_TEST_EXTERN void gi_marshalling_tests_garray_utf8_container_in (GArray *array_); GI_TEST_EXTERN void gi_marshalling_tests_garray_utf8_full_in (GArray *array_); GI_TEST_EXTERN void gi_marshalling_tests_garray_utf8_none_out (GArray **array_); GI_TEST_EXTERN gboolean gi_marshalling_tests_garray_utf8_none_out_uninitialized (GArray **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_garray_utf8_container_out (GArray **array_); GI_TEST_EXTERN gboolean gi_marshalling_tests_garray_utf8_container_out_uninitialized (GArray **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_garray_utf8_full_out (GArray **array_); GI_TEST_EXTERN gboolean gi_marshalling_tests_garray_utf8_full_out_uninitialized (GArray **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_garray_utf8_full_out_caller_allocated (GArray *array_); GI_TEST_EXTERN void gi_marshalling_tests_garray_utf8_none_inout (GArray **array_); GI_TEST_EXTERN void gi_marshalling_tests_garray_utf8_container_inout (GArray **array_); GI_TEST_EXTERN void gi_marshalling_tests_garray_utf8_full_inout (GArray **array_); GI_TEST_EXTERN void gi_marshalling_tests_garray_bool_none_in (GArray *array_); GI_TEST_EXTERN void gi_marshalling_tests_garray_unichar_none_in (GArray *array_); /* GPtrArray */ GI_TEST_EXTERN GPtrArray *gi_marshalling_tests_gptrarray_utf8_none_return (void); GI_TEST_EXTERN GPtrArray *gi_marshalling_tests_gptrarray_utf8_container_return (void); GI_TEST_EXTERN GPtrArray *gi_marshalling_tests_gptrarray_utf8_full_return (void); GI_TEST_EXTERN GPtrArray *gi_marshalling_tests_gptrarray_boxed_struct_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_gptrarray_utf8_none_in (GPtrArray *parray_); GI_TEST_EXTERN void gi_marshalling_tests_gptrarray_utf8_container_in (GPtrArray *parray_); GI_TEST_EXTERN void gi_marshalling_tests_gptrarray_utf8_full_in (GPtrArray *parray_); GI_TEST_EXTERN void gi_marshalling_tests_gptrarray_utf8_none_out (GPtrArray **parray_); GI_TEST_EXTERN gboolean gi_marshalling_tests_gptrarray_utf8_none_out_uninitialized (GPtrArray **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gptrarray_utf8_container_out (GPtrArray **parray_); GI_TEST_EXTERN gboolean gi_marshalling_tests_gptrarray_utf8_container_out_uninitialized (GPtrArray **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gptrarray_utf8_full_out (GPtrArray **parray_); GI_TEST_EXTERN gboolean gi_marshalling_tests_gptrarray_utf8_full_out_uninitialized (GPtrArray **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gptrarray_utf8_none_inout (GPtrArray **parray_); GI_TEST_EXTERN void gi_marshalling_tests_gptrarray_utf8_container_inout (GPtrArray **parray_); GI_TEST_EXTERN void gi_marshalling_tests_gptrarray_utf8_full_inout (GPtrArray **parray_); /* GByteArray */ GI_TEST_EXTERN GByteArray *gi_marshalling_tests_bytearray_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_bytearray_none_in (GByteArray *v); GI_TEST_EXTERN void gi_marshalling_tests_bytearray_full_out (GByteArray **v); GI_TEST_EXTERN void gi_marshalling_tests_bytearray_full_inout (GByteArray **v); /* GBytes */ GI_TEST_EXTERN GBytes *gi_marshalling_tests_gbytes_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_gbytes_none_in (GBytes *v); /* GStrv */ GI_TEST_EXTERN GStrv gi_marshalling_tests_gstrv_return (void); GI_TEST_EXTERN void gi_marshalling_tests_gstrv_in (GStrv g_strv); GI_TEST_EXTERN void gi_marshalling_tests_gstrv_out (GStrv *g_strv); GI_TEST_EXTERN gboolean gi_marshalling_tests_gstrv_out_uninitialized (GStrv *v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gstrv_inout (GStrv *g_strv); /* Array of GStrv's */ GI_TEST_EXTERN GStrv *gi_marshalling_tests_length_array_of_gstrv_transfer_full_return (size_t *out_length); GI_TEST_EXTERN GStrv *gi_marshalling_tests_length_array_of_gstrv_transfer_container_return (size_t *out_length); GI_TEST_EXTERN GStrv *gi_marshalling_tests_length_array_of_gstrv_transfer_none_return (size_t *out_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_of_gstrv_transfer_none_in (GStrv *array, size_t length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_of_gstrv_transfer_container_in (GStrv *array, size_t length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_of_gstrv_transfer_full_in (GStrv *array, size_t length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_of_gstrv_transfer_none_out (GStrv **array_out, size_t *out_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_of_gstrv_transfer_container_out (GStrv **array_out, size_t *out_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_of_gstrv_transfer_full_out (GStrv **array_out, size_t *out_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_of_gstrv_transfer_none_inout (GStrv **array_inout, size_t *inout_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_of_gstrv_transfer_container_inout (GStrv **array_inout, size_t *inout_length); GI_TEST_EXTERN void gi_marshalling_tests_length_array_of_gstrv_transfer_full_inout (GStrv **array_inout, size_t *inout_length); GI_TEST_EXTERN GStrv *gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_return (void); GI_TEST_EXTERN GStrv *gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_return (void); GI_TEST_EXTERN GStrv *gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_return (void); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_in (GStrv *array); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_in (GStrv *array); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_in (GStrv *array); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_out (GStrv **array_out); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_out (GStrv **array_out); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_out (GStrv **array_out); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_none_inout (GStrv **array_inout); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_container_inout (GStrv **array_inout); GI_TEST_EXTERN void gi_marshalling_tests_zero_terminated_array_of_gstrv_transfer_full_inout (GStrv **array_inout); GI_TEST_EXTERN GStrv *gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_return (void); GI_TEST_EXTERN GStrv *gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_return (void); GI_TEST_EXTERN GStrv *gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_return (void); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_in (GStrv *array); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_in (GStrv *array); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_in (GStrv *array); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_out (GStrv **array_out); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_out (GStrv **array_out); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_out (GStrv **array_out); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_of_gstrv_transfer_none_inout (GStrv **array_inout); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_of_gstrv_transfer_container_inout (GStrv **array_inout); GI_TEST_EXTERN void gi_marshalling_tests_fixed_array_of_gstrv_transfer_full_inout (GStrv **array_inout); /* GList */ GI_TEST_EXTERN GList *gi_marshalling_tests_glist_int_none_return (void); GI_TEST_EXTERN GList *gi_marshalling_tests_glist_uint32_none_return (void); GI_TEST_EXTERN GList *gi_marshalling_tests_glist_utf8_none_return (void); GI_TEST_EXTERN GList *gi_marshalling_tests_glist_utf8_container_return (void); GI_TEST_EXTERN GList *gi_marshalling_tests_glist_utf8_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_glist_int_none_in (GList *list); GI_TEST_EXTERN void gi_marshalling_tests_glist_uint32_none_in (GList *list); GI_TEST_EXTERN void gi_marshalling_tests_glist_utf8_none_in (GList *list); GI_TEST_EXTERN void gi_marshalling_tests_glist_utf8_container_in (GList *list); GI_TEST_EXTERN void gi_marshalling_tests_glist_utf8_full_in (GList *list); GI_TEST_EXTERN void gi_marshalling_tests_glist_utf8_none_out (GList **list); GI_TEST_EXTERN gboolean gi_marshalling_tests_glist_utf8_none_out_uninitialized (GList **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_glist_utf8_container_out (GList **list); GI_TEST_EXTERN gboolean gi_marshalling_tests_glist_utf8_container_out_uninitialized (GList **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_glist_utf8_full_out (GList **list); GI_TEST_EXTERN gboolean gi_marshalling_tests_glist_utf8_full_out_uninitialized (GList **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_glist_utf8_none_inout (GList **list); GI_TEST_EXTERN void gi_marshalling_tests_glist_utf8_container_inout (GList **list); GI_TEST_EXTERN void gi_marshalling_tests_glist_utf8_full_inout (GList **list); /* GSList */ GI_TEST_EXTERN GSList *gi_marshalling_tests_gslist_int_none_return (void); GI_TEST_EXTERN GSList *gi_marshalling_tests_gslist_utf8_none_return (void); GI_TEST_EXTERN GSList *gi_marshalling_tests_gslist_utf8_container_return (void); GI_TEST_EXTERN GSList *gi_marshalling_tests_gslist_utf8_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_gslist_int_none_in (GSList *list); GI_TEST_EXTERN void gi_marshalling_tests_gslist_utf8_none_in (GSList *list); GI_TEST_EXTERN void gi_marshalling_tests_gslist_utf8_container_in (GSList *list); GI_TEST_EXTERN void gi_marshalling_tests_gslist_utf8_full_in (GSList *list); GI_TEST_EXTERN void gi_marshalling_tests_gslist_utf8_none_out (GSList **list); GI_TEST_EXTERN gboolean gi_marshalling_tests_gslist_utf8_none_out_uninitialized (GSList **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gslist_utf8_container_out (GSList **list); GI_TEST_EXTERN gboolean gi_marshalling_tests_gslist_utf8_container_out_uninitialized (GSList **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gslist_utf8_full_out (GSList **list); GI_TEST_EXTERN gboolean gi_marshalling_tests_gslist_utf8_full_out_uninitialized (GSList **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gslist_utf8_none_inout (GSList **list); GI_TEST_EXTERN void gi_marshalling_tests_gslist_utf8_container_inout (GSList **list); GI_TEST_EXTERN void gi_marshalling_tests_gslist_utf8_full_inout (GSList **list); /* GHashTable */ GI_TEST_EXTERN GHashTable *gi_marshalling_tests_ghashtable_int_none_return (void); GI_TEST_EXTERN GHashTable *gi_marshalling_tests_ghashtable_utf8_none_return (void); GI_TEST_EXTERN GHashTable *gi_marshalling_tests_ghashtable_utf8_container_return (void); GI_TEST_EXTERN GHashTable *gi_marshalling_tests_ghashtable_utf8_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_int_none_in (GHashTable *hash_table); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_utf8_none_in (GHashTable *hash_table); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_double_in (GHashTable *hash_table); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_float_in (GHashTable *hash_table); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_int64_in (GHashTable *hash_table); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_uint64_in (GHashTable *hash_table); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_utf8_container_in (GHashTable *hash_table); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_utf8_full_in (GHashTable *hash_table); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_utf8_none_out (GHashTable **hash_table); GI_TEST_EXTERN gboolean gi_marshalling_tests_ghashtable_utf8_none_out_uninitialized (GHashTable **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_utf8_container_out (GHashTable **hash_table); GI_TEST_EXTERN gboolean gi_marshalling_tests_ghashtable_utf8_container_out_uninitialized (GHashTable **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_utf8_full_out (GHashTable **hash_table); GI_TEST_EXTERN gboolean gi_marshalling_tests_ghashtable_utf8_full_out_uninitialized (GHashTable **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_utf8_none_inout (GHashTable **hash_table); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_utf8_container_inout (GHashTable **hash_table); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_utf8_full_inout (GHashTable **hash_table); /* GValue */ GI_TEST_EXTERN GValue *gi_marshalling_tests_gvalue_return (void); GI_TEST_EXTERN GValue *gi_marshalling_tests_gvalue_noncanonical_nan_float (void); GI_TEST_EXTERN GValue *gi_marshalling_tests_gvalue_noncanonical_nan_double (void); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_in (GValue *value); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_int64_in (GValue *value); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_in_with_type (GValue *value, GType type); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_in_with_modification (GValue *value); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_in_enum (GValue *value); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_in_flags (GValue *value); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_out (GValue **value); GI_TEST_EXTERN gboolean gi_marshalling_tests_gvalue_out_uninitialized (GValue **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_int64_out (GValue **value); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_out_caller_allocates (GValue *value); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_inout (GValue **value); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_flat_array (guint n_values, const GValue *values); GI_TEST_EXTERN GValue *gi_marshalling_tests_return_gvalue_flat_array (void); GI_TEST_EXTERN GValue *gi_marshalling_tests_return_gvalue_zero_terminated_array (void); GI_TEST_EXTERN GValue *gi_marshalling_tests_gvalue_round_trip (GValue *value); GI_TEST_EXTERN GValue *gi_marshalling_tests_gvalue_copy (GValue *value); GI_TEST_EXTERN GValue *gi_marshalling_tests_gvalue_flat_array_round_trip (const GValue one, const GValue two, const GValue three); GI_TEST_EXTERN void gi_marshalling_tests_gvalue_float (const GValue *float_value, const GValue *double_value); /* GClosure */ GI_TEST_EXTERN void gi_marshalling_tests_gclosure_in (GClosure *closure); GI_TEST_EXTERN GClosure *gi_marshalling_tests_gclosure_return (void); /* Callback return values */ /** * GIMarshallingTestsCallbackReturnValueOnly: */ typedef glong (*GIMarshallingTestsCallbackReturnValueOnly) (void); GI_TEST_EXTERN glong gi_marshalling_tests_callback_return_value_only (GIMarshallingTestsCallbackReturnValueOnly callback); /** * GIMarshallingTestsCallbackOneOutParameter: * @a: (out): */ typedef void (*GIMarshallingTestsCallbackOneOutParameter) (gfloat *a); GI_TEST_EXTERN void gi_marshalling_tests_callback_one_out_parameter (GIMarshallingTestsCallbackOneOutParameter callback, gfloat *a); /** * GIMarshallingTestsCallbackMultipleOutParameters: * @a: (out): * @b: (out): */ typedef void (*GIMarshallingTestsCallbackMultipleOutParameters) (gfloat *a, gfloat *b); GI_TEST_EXTERN void gi_marshalling_tests_callback_multiple_out_parameters (GIMarshallingTestsCallbackMultipleOutParameters callback, gfloat *a, gfloat *b); /** * GIMarshallingTestsCallbackReturnValueAndOneOutParameter: * @a: (out): */ typedef glong (*GIMarshallingTestsCallbackReturnValueAndOneOutParameter) (glong *a); GI_TEST_EXTERN glong gi_marshalling_tests_callback_return_value_and_one_out_parameter (GIMarshallingTestsCallbackReturnValueAndOneOutParameter callback, glong *a); /** * GIMarshallingTestsCallbackReturnValueAndMultipleOutParameters: * @a: (out): * @b: (out): */ typedef glong (*GIMarshallingTestsCallbackReturnValueAndMultipleOutParameters) (glong *a, glong *b); GI_TEST_EXTERN glong gi_marshalling_tests_callback_return_value_and_multiple_out_parameters (GIMarshallingTestsCallbackReturnValueAndMultipleOutParameters callback, glong *a, glong *b); /** * GIMarshallingTestsCallbackOwnedBoxed * @box: (transfer none): the boxed structure. */ typedef void (*GIMarshallingTestsCallbackOwnedBoxed) (GIMarshallingTestsBoxedStruct *box, void *user_data); GI_TEST_EXTERN glong gi_marshalling_tests_callback_owned_boxed (GIMarshallingTestsCallbackOwnedBoxed callback, void *callback_data); /* Pointer */ GI_TEST_EXTERN gpointer gi_marshalling_tests_pointer_in_return (gpointer pointer); /* Structure */ struct _GIMarshallingTestsSimpleStruct { glong long_; gint8 int8; }; typedef struct { GIMarshallingTestsSimpleStruct simple_struct; } GIMarshallingTestsNestedStruct; typedef struct { GIMarshallingTestsNestedStruct *pointer; } GIMarshallingTestsNotSimpleStruct; GI_TEST_EXTERN GIMarshallingTestsSimpleStruct *gi_marshalling_tests_simple_struct_returnv (void); GI_TEST_EXTERN void gi_marshalling_tests_simple_struct_inv (GIMarshallingTestsSimpleStruct *struct_); GI_TEST_EXTERN void gi_marshalling_tests_simple_struct_method (GIMarshallingTestsSimpleStruct *struct_); typedef struct { glong long_; } GIMarshallingTestsPointerStruct; GI_TEST_EXTERN GType gi_marshalling_tests_pointer_struct_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN GIMarshallingTestsPointerStruct *gi_marshalling_tests_pointer_struct_returnv (void); GI_TEST_EXTERN void gi_marshalling_tests_pointer_struct_inv (GIMarshallingTestsPointerStruct *struct_); struct _GIMarshallingTestsBoxedStruct { glong long_; gchar *string_; GStrv g_strv; }; GI_TEST_EXTERN GType gi_marshalling_tests_boxed_struct_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN GIMarshallingTestsBoxedStruct *gi_marshalling_tests_boxed_struct_new (void); GI_TEST_EXTERN GIMarshallingTestsBoxedStruct *gi_marshalling_tests_boxed_struct_returnv (void); GI_TEST_EXTERN void gi_marshalling_tests_boxed_struct_inv (GIMarshallingTestsBoxedStruct *struct_); GI_TEST_EXTERN void gi_marshalling_tests_boxed_struct_out (GIMarshallingTestsBoxedStruct **struct_); GI_TEST_EXTERN gboolean gi_marshalling_tests_boxed_struct_out_uninitialized (GIMarshallingTestsBoxedStruct **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_boxed_struct_inout (GIMarshallingTestsBoxedStruct **struct_); typedef union { glong long_; } GIMarshallingTestsUnion; typedef union { glong long_; gsize size; const gchar *str; } GIMarshallingTestsUnregisteredUnion; GI_TEST_EXTERN GType gi_marshalling_tests_union_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN GIMarshallingTestsUnion *gi_marshalling_tests_union_returnv (void); GI_TEST_EXTERN void gi_marshalling_tests_union_inv (GIMarshallingTestsUnion *union_); GI_TEST_EXTERN void gi_marshalling_tests_union_method (GIMarshallingTestsUnion *union_); typedef enum { GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_NONE, GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_SIMPLE_STRUCT, GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_NESTED_STRUCT, GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_POINTER_STRUCT, GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_BOXED_STRUCT, GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_BOXED_STRUCT_PTR, GI_MARSHALLING_TESTS_STRUCTURED_UNION_TYPE_SINGLE_UNION, } GIMarshallingTestsStructuredUnionType; typedef struct { GIMarshallingTestsStructuredUnionType type; GIMarshallingTestsSimpleStruct parent; } GIMarshallingTestsStructuredUnionSimpleStruct; typedef struct { GIMarshallingTestsStructuredUnionType type; GIMarshallingTestsNestedStruct parent; } GIMarshallingTestsStructuredUnionNestedStruct; typedef struct { GIMarshallingTestsStructuredUnionType type; GIMarshallingTestsPointerStruct parent; } GIMarshallingTestsStructuredUnionPointerStruct; typedef struct { GIMarshallingTestsStructuredUnionType type; GIMarshallingTestsBoxedStruct parent; } GIMarshallingTestsStructuredUnionBoxedStruct; typedef struct { GIMarshallingTestsStructuredUnionType type; GIMarshallingTestsBoxedStruct *parent; } GIMarshallingTestsStructuredUnionBoxedStructPtr; typedef struct { GIMarshallingTestsStructuredUnionType type; GIMarshallingTestsUnion union_; } GIMarshallingTestsStructuredUnionUnionStruct; typedef union { GIMarshallingTestsStructuredUnionUnionStruct parent; } GIMarshallingTestsStructuredUnionSingleUnion; typedef union { /*< private >*/ GIMarshallingTestsStructuredUnionType type; GIMarshallingTestsStructuredUnionSimpleStruct simple_struct; GIMarshallingTestsStructuredUnionNestedStruct nested_struct; GIMarshallingTestsStructuredUnionPointerStruct pointer_struct; GIMarshallingTestsStructuredUnionBoxedStruct boxed_struct; GIMarshallingTestsStructuredUnionBoxedStructPtr boxed_struct_ptr; GIMarshallingTestsStructuredUnionSingleUnion single_union; } GIMarshallingTestsStructuredUnion; GI_TEST_EXTERN GType gi_marshalling_tests_structured_union_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN GIMarshallingTestsStructuredUnion *gi_marshalling_tests_structured_union_new (GIMarshallingTestsStructuredUnionType type); /* we want this to clash with a field value name */ GI_TEST_EXTERN GIMarshallingTestsStructuredUnionType gi_marshalling_tests_structured_union_type (GIMarshallingTestsStructuredUnion *structured_union); typedef union { GIMarshallingTestsStructuredUnionType type; GIMarshallingTestsStructuredUnionSimpleStruct simple_struct1; GIMarshallingTestsStructuredUnionSimpleStruct simple_struct2; } GIMarshallingTestsStructuredUnionSingleType; /* Object */ #define GI_MARSHALLING_TESTS_TYPE_OBJECT (gi_marshalling_tests_object_get_type ()) #define GI_MARSHALLING_TESTS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GI_MARSHALLING_TESTS_TYPE_OBJECT, GIMarshallingTestsObject)) #define GI_MARSHALLING_TESTS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GI_MARSHALLING_TESTS_TYPE_OBJECT, GIMarshallingTestsObjectClass)) #define GI_MARSHALLING_TESTS_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GI_MARSHALLING_TESTS_TYPE_OBJECT)) #define GI_MARSHALLING_TESTS_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GI_MARSHALLING_TESTS_TYPE_OBJECT)) #define GI_MARSHALLING_TESTS_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GI_MARSHALLING_TESTS_TYPE_OBJECT, GIMarshallingTestsObjectClass)) typedef struct _GIMarshallingTestsObjectClass GIMarshallingTestsObjectClass; typedef struct _GIMarshallingTestsObject GIMarshallingTestsObject; typedef int (*GIMarshallingTestsCallbackIntInt) (int val, void *user_data); struct _GIMarshallingTestsObjectClass { GObjectClass parent_class; /** * GIMarshallingTestsObjectClass::method_int8_in: * @in: (in): */ void (*method_int8_in) (GIMarshallingTestsObject *self, gint8 in); /** * GIMarshallingTestsObjectClass::method_int8_out: * @out: (out): */ void (*method_int8_out) (GIMarshallingTestsObject *self, gint8 *out); /** * GIMarshallingTestsObjectClass::method_int8_arg_and_out_caller: * @out: (out): */ void (*method_int8_arg_and_out_caller) (GIMarshallingTestsObject *self, gint8 arg, gint8 *out); /** * GIMarshallingTestsObjectClass::method_int8_arg_and_out_callee: * @out: (out): */ void (*method_int8_arg_and_out_callee) (GIMarshallingTestsObject *self, gint8 arg, gint8 **out); /** * GIMarshallingTestsObjectClass::method_str_arg_out_ret: * @out: (out): * * Returns: (transfer none) */ const gchar *(*method_str_arg_out_ret) (GIMarshallingTestsObject *self, const gchar *arg, guint *out); /** * GIMarshallingTestsObjectClass::method_with_default_implementation: * @in: (in): */ void (*method_with_default_implementation) (GIMarshallingTestsObject *self, gint8 in); /** * GIMarshallingTestsObjectClass::method_deep_hierarchy: * @in: (in): */ void (*method_deep_hierarchy) (GIMarshallingTestsObject *self, gint8 in); void (*vfunc_with_callback) (GIMarshallingTestsObject *self, GIMarshallingTestsCallbackIntInt callback, void *callback_data); /** * GIMarshallingTestsObjectClass::vfunc_return_value_only: */ glong (*vfunc_return_value_only) (GIMarshallingTestsObject *self); /** * GIMarshallingTestsObjectClass::vfunc_one_out_parameter: * @a: (out): */ void (*vfunc_one_out_parameter) (GIMarshallingTestsObject *self, gfloat *a); /** * GIMarshallingTestsObjectClass::vfunc_multiple_out_parameters: * @a: (out): * @b: (out): */ void (*vfunc_multiple_out_parameters) (GIMarshallingTestsObject *self, gfloat *a, gfloat *b); /** * GIMarshallingTestsObjectClass::vfunc_one_inout_parameter: * @a: (inout): */ void (*vfunc_one_inout_parameter) (GIMarshallingTestsObject *self, gfloat *a); /** * GIMarshallingTestsObjectClass::vfunc_multiple_inout_parameters: * @a: (inout): * @b: (inout): */ void (*vfunc_multiple_inout_parameters) (GIMarshallingTestsObject *self, gfloat *a, gfloat *b); /** * GIMarshallingTestsObjectClass::vfunc_caller_allocated_out_parameter: * @a: (out): */ void (*vfunc_caller_allocated_out_parameter) (GIMarshallingTestsObject *self, GValue *a); /** * GIMarshallingTestsObjectClass::vfunc_array_out_parameter: * @a: (out) (array zero-terminated): */ void (*vfunc_array_out_parameter) (GIMarshallingTestsObject *self, gfloat **a); /** * GIMarshallingTestsObjectClass::vfunc_return_value_and_one_out_parameter: * @a: (out): */ glong (*vfunc_return_value_and_one_out_parameter) (GIMarshallingTestsObject *self, glong *a); /** * GIMarshallingTestsObjectClass::vfunc_return_value_and_multiple_out_parameters: * @a: (out): * @b: (out): */ glong (*vfunc_return_value_and_multiple_out_parameters) (GIMarshallingTestsObject *self, glong *a, glong *b); /** * GIMarshallingTestsObjectClass::vfunc_return_value_and_one_inout_parameter: * @a: (inout): */ glong (*vfunc_return_value_and_one_inout_parameter) (GIMarshallingTestsObject *self, glong *a); /** * GIMarshallingTestsObjectClass::vfunc_return_value_and_multiple_inout_parameters: * @a: (inout): * @b: (inout): */ glong (*vfunc_return_value_and_multiple_inout_parameters) (GIMarshallingTestsObject *self, glong *a, glong *b); /** * GIMarshallingTestsObjectClass::vfunc_meth_with_err: * @x: * @error: A #GError */ gboolean (*vfunc_meth_with_err) (GIMarshallingTestsObject *object, gint x, GError **error); /** * GIMarshallingTestsObjectClass::vfunc_return_enum: */ GIMarshallingTestsEnum (*vfunc_return_enum) (GIMarshallingTestsObject *self); /** * GIMarshallingTestsObjectClass::vfunc_out_enum: * @_enum: (out): */ void (*vfunc_out_enum) (GIMarshallingTestsObject *self, GIMarshallingTestsEnum *_enum); /** * GIMarshallingTestsObjectClass::vfunc_return_object_transfer_none: * * Returns: (transfer none) */ GObject *(*vfunc_return_object_transfer_none) (GIMarshallingTestsObject *self); /** * GIMarshallingTestsObjectClass::vfunc_return_object_transfer_full: * * Returns: (transfer full) */ GObject *(*vfunc_return_object_transfer_full) (GIMarshallingTestsObject *self); /** * GIMarshallingTestsObjectClass::vfunc_out_object_transfer_none: * @object: (out) (transfer none): */ void (*vfunc_out_object_transfer_none) (GIMarshallingTestsObject *self, GObject **object); /** * GIMarshallingTestsObjectClass::vfunc_out_object_transfer_full: * @object: (out) (transfer full): */ void (*vfunc_out_object_transfer_full) (GIMarshallingTestsObject *self, GObject **object); /** * GIMarshallingTestsObjectClass::vfunc_in_object_transfer_none: * @object: (in) (transfer none): */ void (*vfunc_in_object_transfer_none) (GIMarshallingTestsObject *self, GObject *object); /** * GIMarshallingTestsObjectClass::vfunc_in_object_transfer_full: * @object: (in) (transfer full): */ void (*vfunc_in_object_transfer_full) (GIMarshallingTestsObject *self, GObject *object); /** * GIMarshallingTestsObjectClass::vfunc_return_flags: */ GIMarshallingTestsFlags (*vfunc_return_flags) (GIMarshallingTestsObject *self); /** * GIMarshallingTestsObjectClass::vfunc_out_flags: * @flags: (out): */ void (*vfunc_out_flags) (GIMarshallingTestsObject *self, GIMarshallingTestsFlags *flags); /** * GIMarshallingTestsObjectClass::vfunc_static_name: */ gchar *(*vfunc_static_name) (void); /** * GIMarshallingTestsObjectClass::vfunc_static_create_new: * @int_: * * Returns: (transfer full): */ GIMarshallingTestsObject *(*vfunc_static_create_new) (gint int_); /** * GIMarshallingTestsObjectClass::vfunc_static_create_new_out: * @out: (out): * @int_: */ void (*vfunc_static_create_new_out) (GIMarshallingTestsObject **out, gint int_); }; struct _GIMarshallingTestsObject { GObject parent_instance; gint int_; }; GI_TEST_EXTERN GType gi_marshalling_tests_object_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN void gi_marshalling_tests_object_static_method (void); GI_TEST_EXTERN void gi_marshalling_tests_object_method (GIMarshallingTestsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_object_overridden_method (GIMarshallingTestsObject *object); GI_TEST_EXTERN GIMarshallingTestsObject *gi_marshalling_tests_object_new (gint int_); GI_TEST_EXTERN GIMarshallingTestsObject *gi_marshalling_tests_object_new_fail (gint int_, GError **error); GI_TEST_EXTERN void gi_marshalling_tests_object_method_array_in (GIMarshallingTestsObject *object, const gint *ints, gint length); GI_TEST_EXTERN void gi_marshalling_tests_object_method_array_out (GIMarshallingTestsObject *object, gint **ints, gint *length); GI_TEST_EXTERN void gi_marshalling_tests_object_method_array_inout (GIMarshallingTestsObject *object, gint **ints, gint *length); GI_TEST_EXTERN const gint *gi_marshalling_tests_object_method_array_return (GIMarshallingTestsObject *object, gint *length); GI_TEST_EXTERN void gi_marshalling_tests_object_method_int8_in (GIMarshallingTestsObject *object, gint8 in); GI_TEST_EXTERN void gi_marshalling_tests_object_method_int8_out (GIMarshallingTestsObject *object, gint8 *out); GI_TEST_EXTERN void gi_marshalling_tests_object_method_int8_arg_and_out_caller (GIMarshallingTestsObject *object, gint8 arg, gint8 *out); GI_TEST_EXTERN void gi_marshalling_tests_object_method_int8_arg_and_out_callee (GIMarshallingTestsObject *object, gint8 arg, gint8 **out); GI_TEST_EXTERN const gchar *gi_marshalling_tests_object_method_str_arg_out_ret (GIMarshallingTestsObject *object, const gchar *arg, guint *out); GI_TEST_EXTERN void gi_marshalling_tests_object_method_with_default_implementation (GIMarshallingTestsObject *object, gint8 in); GI_TEST_EXTERN void gi_marshalling_tests_object_method_variant_array_in (GIMarshallingTestsObject *object, GVariant **in, gsize n_in); GI_TEST_EXTERN glong gi_marshalling_tests_object_vfunc_return_value_only (GIMarshallingTestsObject *self); GI_TEST_EXTERN void gi_marshalling_tests_object_vfunc_one_out_parameter (GIMarshallingTestsObject *self, gfloat *a); GI_TEST_EXTERN void gi_marshalling_tests_object_vfunc_multiple_out_parameters (GIMarshallingTestsObject *self, gfloat *a, gfloat *b); GI_TEST_EXTERN void gi_marshalling_tests_object_vfunc_one_inout_parameter (GIMarshallingTestsObject *self, gfloat *a); GI_TEST_EXTERN void gi_marshalling_tests_object_vfunc_multiple_inout_parameters (GIMarshallingTestsObject *self, gfloat *a, gfloat *b); GI_TEST_EXTERN void gi_marshalling_tests_object_vfunc_caller_allocated_out_parameter (GIMarshallingTestsObject *self, GValue *a); GI_TEST_EXTERN void gi_marshalling_tests_object_vfunc_array_out_parameter (GIMarshallingTestsObject *self, gfloat **a); GI_TEST_EXTERN glong gi_marshalling_tests_object_vfunc_return_value_and_one_out_parameter (GIMarshallingTestsObject *self, glong *a); GI_TEST_EXTERN glong gi_marshalling_tests_object_vfunc_return_value_and_multiple_out_parameters (GIMarshallingTestsObject *self, glong *a, glong *b); GI_TEST_EXTERN glong gi_marshalling_tests_object_vfunc_return_value_and_one_inout_parameter (GIMarshallingTestsObject *self, glong *a); GI_TEST_EXTERN glong gi_marshalling_tests_object_vfunc_return_value_and_multiple_inout_parameters (GIMarshallingTestsObject *self, glong *a, glong *b); GI_TEST_EXTERN gboolean gi_marshalling_tests_object_vfunc_meth_with_error (GIMarshallingTestsObject *object, gint x, GError **error); GI_TEST_EXTERN GIMarshallingTestsEnum gi_marshalling_tests_object_vfunc_return_enum (GIMarshallingTestsObject *self); GI_TEST_EXTERN void gi_marshalling_tests_object_vfunc_out_enum (GIMarshallingTestsObject *self, GIMarshallingTestsEnum *_enum); GI_TEST_EXTERN GIMarshallingTestsFlags gi_marshalling_tests_object_vfunc_return_flags (GIMarshallingTestsObject *self); GI_TEST_EXTERN void gi_marshalling_tests_object_vfunc_out_flags (GIMarshallingTestsObject *self, GIMarshallingTestsFlags *flags); GI_TEST_EXTERN gchar *gi_marshalling_tests_object_vfunc_static_name (void); GI_TEST_EXTERN gchar *gi_marshalling_tests_object_vfunc_static_typed_name (GType gtype); GI_TEST_EXTERN GIMarshallingTestsObject *gi_marshalling_tests_object_vfunc_static_create_new (GType gtype, gint int_); GI_TEST_EXTERN void gi_marshalling_tests_object_vfunc_static_create_new_out (GIMarshallingTestsObject **out, GType gtype, gint int_); GI_TEST_EXTERN void gi_marshalling_tests_object_get_ref_info_for_vfunc_return_object_transfer_none (GIMarshallingTestsObject *self, guint *ref_count, gboolean *is_floating); GI_TEST_EXTERN void gi_marshalling_tests_object_get_ref_info_for_vfunc_return_object_transfer_full (GIMarshallingTestsObject *self, guint *ref_count, gboolean *is_floating); GI_TEST_EXTERN void gi_marshalling_tests_object_get_ref_info_for_vfunc_out_object_transfer_none (GIMarshallingTestsObject *self, guint *ref_count, gboolean *is_floating); GI_TEST_EXTERN void gi_marshalling_tests_object_get_ref_info_for_vfunc_out_object_transfer_full (GIMarshallingTestsObject *self, guint *ref_count, gboolean *is_floating); GI_TEST_EXTERN void gi_marshalling_tests_object_get_ref_info_for_vfunc_in_object_transfer_none (GIMarshallingTestsObject *self, GType type, guint *ref_count, gboolean *is_floating); GI_TEST_EXTERN void gi_marshalling_tests_object_get_ref_info_for_vfunc_in_object_transfer_full (GIMarshallingTestsObject *self, GType type, guint *ref_count, gboolean *is_floating); GI_TEST_EXTERN GIMarshallingTestsObject *gi_marshalling_tests_object_none_return (void); GI_TEST_EXTERN GIMarshallingTestsObject *gi_marshalling_tests_object_full_return (void); GI_TEST_EXTERN void gi_marshalling_tests_object_none_in (GIMarshallingTestsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_object_full_in (GIMarshallingTestsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_object_none_out (GIMarshallingTestsObject **object); GI_TEST_EXTERN gboolean gi_marshalling_tests_object_none_out_uninitialized (GIMarshallingTestsObject **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_object_full_out (GIMarshallingTestsObject **object); GI_TEST_EXTERN gboolean gi_marshalling_tests_object_full_out_uninitialized (GIMarshallingTestsObject **v G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_object_none_inout (GIMarshallingTestsObject **object); GI_TEST_EXTERN void gi_marshalling_tests_object_full_inout (GIMarshallingTestsObject **object); GI_TEST_EXTERN void gi_marshalling_tests_object_int8_in (GIMarshallingTestsObject *object, gint8 in); GI_TEST_EXTERN void gi_marshalling_tests_object_int8_out (GIMarshallingTestsObject *object, gint8 *out); GI_TEST_EXTERN void gi_marshalling_tests_object_vfunc_with_callback (GIMarshallingTestsObject *object, GIMarshallingTestsCallbackIntInt callback, void *callback_data); GI_TEST_EXTERN void gi_marshalling_tests_object_call_vfunc_with_callback (GIMarshallingTestsObject *object); #define GI_MARSHALLING_TESTS_TYPE_SUB_OBJECT (gi_marshalling_tests_sub_object_get_type ()) #define GI_MARSHALLING_TESTS_SUB_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GI_MARSHALLING_TESTS_TYPE_SUB_OBJECT, GIMarshallingTestsSubObject)) #define GI_MARSHALLING_TESTS_SUB_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GI_MARSHALLING_TESTS_TYPE_SUB_OBJECT, GIMarshallingTestsSubObjectClass)) #define GI_MARSHALLING_TESTS_IS_SUB_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GI_MARSHALLING_TESTS_TYPE_SUB_OBJECT)) #define GI_MARSHALLING_TESTS_IS_SUB_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GI_MARSHALLING_TESTS_TYPE_SUB_OBJECT)) #define GI_MARSHALLING_TESTS_SUB_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GI_MARSHALLING_TESTS_TYPE_SUB_OBJECT, GIMarshallingTestsSubObjectClass)) typedef struct _GIMarshallingTestsSubObjectClass GIMarshallingTestsSubObjectClass; typedef struct _GIMarshallingTestsSubObject GIMarshallingTestsSubObject; struct _GIMarshallingTestsSubObjectClass { GIMarshallingTestsObjectClass parent_class; }; struct _GIMarshallingTestsSubObject { GIMarshallingTestsObject parent_instance; }; GI_TEST_EXTERN GType gi_marshalling_tests_sub_object_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN void gi_marshalling_tests_sub_object_sub_method (GIMarshallingTestsSubObject *object); GI_TEST_EXTERN void gi_marshalling_tests_sub_object_overwritten_method (GIMarshallingTestsSubObject *object); #define GI_MARSHALLING_TESTS_TYPE_SUB_SUB_OBJECT (gi_marshalling_tests_sub_sub_object_get_type ()) #define GI_MARSHALLING_TESTS_SUB_SUB_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GI_MARSHALLING_TESTS_TYPE_SUB_SUB_OBJECT, GIMarshallingTestsSubSubObject)) #define GI_MARSHALLING_TESTS_SUB_SUB_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GI_MARSHALLING_TESTS_TYPE_SUB_SUB_OBJECT, GIMarshallingTestsSubSubObjectClass)) #define GI_MARSHALLING_TESTS_IS_SUB_SUB_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GI_MARSHALLING_TESTS_TYPE_SUB_SUB_OBJECT)) #define GI_MARSHALLING_TESTS_IS_SUB_SUB_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GI_MARSHALLING_TESTS_TYPE_SUB_SUB_OBJECT)) #define GI_MARSHALLING_TESTS_SUB_SUB_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GI_MARSHALLING_TESTS_TYPE_SUB_SUB_OBJECT, GIMarshallingTestsSubSubObjectClass)) typedef struct _GIMarshallingTestsSubSubObjectClass GIMarshallingTestsSubSubObjectClass; typedef struct _GIMarshallingTestsSubSubObject GIMarshallingTestsSubSubObject; struct _GIMarshallingTestsSubSubObjectClass { GIMarshallingTestsSubObjectClass parent_class; }; struct _GIMarshallingTestsSubSubObject { GIMarshallingTestsSubObject parent_instance; }; GI_TEST_EXTERN GType gi_marshalling_tests_sub_sub_object_get_type (void) G_GNUC_CONST; /* Interfaces */ #define GI_MARSHALLING_TESTS_TYPE_INTERFACE (gi_marshalling_tests_interface_get_type ()) #define GI_MARSHALLING_TESTS_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GI_MARSHALLING_TESTS_TYPE_INTERFACE, GIMarshallingTestsInterface)) #define GI_MARSHALLING_TESTS_IS_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GI_MARSHALLING_TESTS_TYPE_INTERFACE)) #define GI_MARSHALLING_TESTS_INTERFACE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GI_MARSHALLING_TESTS_TYPE_INTERFACE, GIMarshallingTestsInterfaceIface)) typedef struct _GIMarshallingTestsInterface GIMarshallingTestsInterface; typedef struct _GIMarshallingTestsInterfaceIface GIMarshallingTestsInterfaceIface; struct _GIMarshallingTestsInterfaceIface { GTypeInterface base_iface; /** * GIMarshallingTestsInterfaceIface::test_int8_in: * @in: (in): */ void (*test_int8_in) (GIMarshallingTestsInterface *self, gint8 in); }; GI_TEST_EXTERN GType gi_marshalling_tests_interface_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN void gi_marshalling_tests_interface_test_int8_in (GIMarshallingTestsInterface *self, gint8 in); GI_TEST_EXTERN void gi_marshalling_tests_test_interface_test_int8_in (GIMarshallingTestsInterface *test_iface, gint8 in); /* GIMarshallingTestsInterfaceImpl is a class that implements GIMarshallingTestsInterface */ #define GI_MARSHALLING_TESTS_TYPE_INTERFACE_IMPL (gi_marshalling_tests_interface_impl_get_type ()) #define GI_MARSHALLING_TESTS_INTERFACE_IMPL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GI_MARSHALLING_TESTS_TYPE_INTERFACE_IMPL, GIMarshallingTestsInterfaceImpl)) #define GI_MARSHALLING_TESTS_INTERFACE_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GI_MARSHALLING_TESTS_TYPE_INTERFACE_IMPL, GIMarshallingTestsInterfaceImplClass)) #define GI_MARSHALLING_TESTS_IS_INTERFACE_IMPL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GI_MARSHALLING_TESTS_TYPE_INTERFACE_IMPL)) #define GI_MARSHALLING_TESTS_IS_INTERFACE_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GI_MARSHALLING_TESTS_TYPE_INTERFACE_IMPL)) #define GI_MARSHALLING_TESTS_INTERFACE_IMPL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GI_MARSHALLING_TESTS_TYPE_INTERFACE_IMPL, GIMarshallingTestsInterfaceImplClass)) typedef struct _GIMarshallingTestsInterfaceImplClass GIMarshallingTestsInterfaceImplClass; typedef struct _GIMarshallingTestsInterfaceImpl GIMarshallingTestsInterfaceImpl; struct _GIMarshallingTestsInterfaceImplClass { GObjectClass parent_class; }; struct _GIMarshallingTestsInterfaceImpl { GObject parent_instance; gint int_; }; GI_TEST_EXTERN GType gi_marshalling_tests_interface_impl_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN GIMarshallingTestsInterface *gi_marshalling_tests_interface_impl_get_as_interface (GIMarshallingTestsInterfaceImpl *self); /* GIMarshallingTestsInterface2 allows us testing vfunc clashes when a class' vfunc implementation ambiguously relates to its prototype */ #define GI_MARSHALLING_TESTS_TYPE_INTERFACE2 (gi_marshalling_tests_interface2_get_type ()) #define GI_MARSHALLING_TESTS_INTERFACE2(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GI_MARSHALLING_TESTS_TYPE_INTERFACE2, GIMarshallingTestsInterface2)) #define GI_MARSHALLING_TESTS_IS_INTERFACE2(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GI_MARSHALLING_TESTS_TYPE_INTERFACE2)) #define GI_MARSHALLING_TESTS_INTERFACE2_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GI_MARSHALLING_TESTS_TYPE_INTERFACE2, GIMarshallingTestsInterface2Iface)) typedef struct _GIMarshallingTestsInterface2 GIMarshallingTestsInterface2; typedef struct _GIMarshallingTestsInterface2Iface GIMarshallingTestsInterface2Iface; struct _GIMarshallingTestsInterface2Iface { GTypeInterface base_iface; /** * GIMarshallingTestsInterface2Iface::test_int8_in: * @in: (in): */ void (*test_int8_in) (GIMarshallingTestsInterface2 *self, gint8 in); }; GI_TEST_EXTERN GType gi_marshalling_tests_interface2_get_type (void) G_GNUC_CONST; /* GIMarshallingTestsInterface3 tests passing arrays of variants from C to @lang */ #define GI_MARSHALLING_TESTS_TYPE_INTERFACE3 (gi_marshalling_tests_interface3_get_type ()) #define GI_MARSHALLING_TESTS_INTERFACE3(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GI_MARSHALLING_TESTS_TYPE_INTERFACE3, GIMarshallingTestsInterface3)) #define GI_MARSHALLING_TESTS_IS_INTERFACE3(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GI_MARSHALLING_TESTS_TYPE_INTERFACE3)) #define GI_MARSHALLING_TESTS_INTERFACE3_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GI_MARSHALLING_TESTS_TYPE_INTERFACE3, GIMarshallingTestsInterface3Iface)) typedef struct _GIMarshallingTestsInterface3 GIMarshallingTestsInterface3; typedef struct _GIMarshallingTestsInterface3Iface GIMarshallingTestsInterface3Iface; struct _GIMarshallingTestsInterface3Iface { GTypeInterface base_iface; /** * GIMarshallingTestsInterface3::test_variant_array_in: * @in: (in) (array length=n_in): */ void (*test_variant_array_in) (GIMarshallingTestsInterface3 *self, GVariant **in, gsize n_in); }; GI_TEST_EXTERN GType gi_marshalling_tests_interface3_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN void gi_marshalling_tests_interface3_test_variant_array_in (GIMarshallingTestsInterface3 *self, GVariant **in, gsize n_in); /* Multiple output arguments */ GI_TEST_EXTERN void gi_marshalling_tests_int_out_out (gint *int0, gint *int1); GI_TEST_EXTERN void gi_marshalling_tests_int_three_in_three_out (gint a, gint b, gint c, gint *out0, gint *out1, gint *out2); GI_TEST_EXTERN gint gi_marshalling_tests_int_return_out (gint *int_); /* Default arguments */ GI_TEST_EXTERN void gi_marshalling_tests_int_two_in_utf8_two_in_with_allow_none (gint a, gint b, const gchar *c, const gchar *d); GI_TEST_EXTERN void gi_marshalling_tests_int_one_in_utf8_two_in_one_allows_none (gint a, const gchar *b, const gchar *c); GI_TEST_EXTERN void gi_marshalling_tests_array_in_utf8_two_in (const gint *ints, gint length, const gchar *a, const gchar *b); GI_TEST_EXTERN void gi_marshalling_tests_array_in_utf8_two_in_out_of_order (gint length, const gchar *a, const gint *ints, const gchar *b); /* GError */ #define GI_MARSHALLING_TESTS_CONSTANT_GERROR_DOMAIN "gi-marshalling-tests-gerror-domain" #define GI_MARSHALLING_TESTS_CONSTANT_GERROR_CODE 5 #define GI_MARSHALLING_TESTS_CONSTANT_GERROR_MESSAGE "gi-marshalling-tests-gerror-message" #define GI_MARSHALLING_TESTS_CONSTANT_GERROR_DEBUG_MESSAGE "we got an error, life is shit" GI_TEST_EXTERN void gi_marshalling_tests_gerror (GError **error); GI_TEST_EXTERN void gi_marshalling_tests_gerror_array_in (gint *in_ints, GError **error); GI_TEST_EXTERN void gi_marshalling_tests_gerror_out (GError **error, gchar **debug); GI_TEST_EXTERN gboolean gi_marshalling_tests_gerror_out_uninitialized (GError **v G_GNUC_UNUSED, gchar **v2 G_GNUC_UNUSED); GI_TEST_EXTERN void gi_marshalling_tests_gerror_out_transfer_none (GError **err, const gchar **debug); GI_TEST_EXTERN gboolean gi_marshalling_tests_gerror_out_transfer_none_uninitialized (GError **v G_GNUC_UNUSED, const gchar **v2 G_GNUC_UNUSED); GI_TEST_EXTERN GError *gi_marshalling_tests_gerror_return (void); /* GParamSpec */ GI_TEST_EXTERN void gi_marshalling_tests_param_spec_in_bool (const GParamSpec *param); GI_TEST_EXTERN GParamSpec *gi_marshalling_tests_param_spec_return (void); GI_TEST_EXTERN void gi_marshalling_tests_param_spec_out (GParamSpec **param); GI_TEST_EXTERN gboolean gi_marshalling_tests_param_spec_out_uninitialized (GParamSpec **v G_GNUC_UNUSED); /* Overrides */ #define GI_MARSHALLING_TESTS_OVERRIDES_CONSTANT 42 typedef struct { glong long_; } GIMarshallingTestsOverridesStruct; GI_TEST_EXTERN GType gi_marshalling_tests_overrides_struct_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN GIMarshallingTestsOverridesStruct *gi_marshalling_tests_overrides_struct_new (void); GI_TEST_EXTERN glong gi_marshalling_tests_overrides_struct_method (GIMarshallingTestsOverridesStruct *struct_); GI_TEST_EXTERN GIMarshallingTestsOverridesStruct *gi_marshalling_tests_overrides_struct_returnv (void); #define GI_MARSHALLING_TESTS_TYPE_OVERRIDES_OBJECT (gi_marshalling_tests_overrides_object_get_type ()) #define GI_MARSHALLING_TESTS_OVERRIDES_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GI_MARSHALLING_TESTS_TYPE_OVERRIDES_OBJECT, GIMarshallingTestsOverridesObject)) #define GI_MARSHALLING_TESTS_OVERRIDES_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GI_MARSHALLING_TESTS_TYPE_OVERRIDES_OBJECT, GIMarshallingTestsOverridesObjectClass)) #define GI_MARSHALLING_TESTS_IS_OVERRIDES_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GI_MARSHALLING_TESTS_TYPE_OVERRIDES_OBJECT)) #define GI_MARSHALLING_TESTS_IS_OVERRIDES_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GI_MARSHALLING_TESTS_TYPE_OVERRIDES_OBJECT)) #define GI_MARSHALLING_TESTS_OVERRIDES_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GI_MARSHALLING_TESTS_TYPE_OVERRIDES_OBJECT, GIMarshallingTestsOverridesObjectClass)) typedef struct _GIMarshallingTestsOverridesObjectClass GIMarshallingTestsOverridesObjectClass; typedef struct _GIMarshallingTestsOverridesObject GIMarshallingTestsOverridesObject; struct _GIMarshallingTestsOverridesObjectClass { GObjectClass parent_class; }; struct _GIMarshallingTestsOverridesObject { GObject parent_instance; glong long_; }; GI_TEST_EXTERN GType gi_marshalling_tests_overrides_object_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN GIMarshallingTestsOverridesObject *gi_marshalling_tests_overrides_object_new (void); GI_TEST_EXTERN glong gi_marshalling_tests_overrides_object_method (GIMarshallingTestsOverridesObject *object); GI_TEST_EXTERN GIMarshallingTestsOverridesObject *gi_marshalling_tests_overrides_object_returnv (void); /* Properties Object */ #define GI_MARSHALLING_TESTS_TYPE_PROPERTIES_OBJECT (gi_marshalling_tests_properties_object_get_type ()) #define GI_MARSHALLING_TESTS_PROPERTIES_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GI_MARSHALLING_TESTS_TYPE_PROPERTIES_OBJECT, GIMarshallingTestsPropertiesObject)) #define GI_MARSHALLING_TESTS_PROPERTIES_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GI_MARSHALLING_TESTS_TYPE_PROPERTIES_OBJECT, GIMarshallingTestsPropertiesObjectClass)) #define GI_MARSHALLING_TESTS_IS_PROPERTIES_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GI_MARSHALLING_TESTS_TYPE_PROPERTIES_OBJECT)) #define GI_MARSHALLING_TESTS_IS_PROPERTIES_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GI_MARSHALLING_TESTS_TYPE_PROPERTIES_OBJECT)) #define GI_MARSHALLING_TESTS_PROPERTIES_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GI_MARSHALLING_TESTS_TYPE_PROPERTIES_OBJECT, GIMarshallingTestsPropertiesObjectClass)) typedef struct _GIMarshallingTestsPropertiesObject GIMarshallingTestsPropertiesObject; typedef struct _GIMarshallingTestsPropertiesObjectClass GIMarshallingTestsPropertiesObjectClass; struct _GIMarshallingTestsPropertiesObject { GObject parent_instance; gboolean some_boolean; gchar some_char; guchar some_uchar; gint some_int; gint some_deprecated_int; guint some_uint; glong some_long; gulong some_ulong; gint64 some_int64; guint64 some_uint64; gfloat some_float; gdouble some_double; gchar *some_string; gchar **some_strv; GIMarshallingTestsBoxedStruct *some_boxed_struct; GList *some_boxed_glist; GValue *some_gvalue; GVariant *some_variant; GObject *some_object; GIMarshallingTestsFlags some_flags; GIMarshallingTestsGEnum some_enum; GByteArray *some_byte_array; }; struct _GIMarshallingTestsPropertiesObjectClass { GObjectClass parent_class; }; GI_TEST_EXTERN GType gi_marshalling_tests_properties_object_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN GIMarshallingTestsPropertiesObject *gi_marshalling_tests_properties_object_new (void); /* Object with properties setters/getters */ #define GI_MARSHALLING_TESTS_TYPE_ACCESSORS_TESTS_PROPERTIES_OBJECT \ (gi_marshalling_tests_properties_accessors_object_get_type ()) GI_TEST_EXTERN G_DECLARE_FINAL_TYPE (GIMarshallingTestsPropertiesAccessorsObject, gi_marshalling_tests_properties_accessors_object, GI_MARSHALLING_TESTS, PROPERTIES_ACCESSORS_OBJECT, GObject); struct _GIMarshallingTestsPropertiesAccessorsObject { GObject parent_instance; gboolean some_boolean; gchar some_char; guchar some_uchar; gint some_int; gint some_deprecated_int; guint some_uint; glong some_long; gulong some_ulong; gint64 some_int64; guint64 some_uint64; gfloat some_float; gdouble some_double; gchar *some_string; gchar **some_strv; GIMarshallingTestsBoxedStruct *some_boxed_struct; GList *some_boxed_glist; GValue *some_gvalue; GVariant *some_variant; GObject *some_object; GIMarshallingTestsFlags some_flags; GIMarshallingTestsGEnum some_enum; GByteArray *some_byte_array; }; GI_TEST_EXTERN GIMarshallingTestsPropertiesAccessorsObject * gi_marshalling_tests_properties_accessors_object_new (void); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_boolean (GIMarshallingTestsPropertiesAccessorsObject *self, gboolean some_boolean); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_char (GIMarshallingTestsPropertiesAccessorsObject *self, gchar some_char); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_uchar (GIMarshallingTestsPropertiesAccessorsObject *self, guchar some_uchar); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_int (GIMarshallingTestsPropertiesAccessorsObject *self, gint some_int); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_uint (GIMarshallingTestsPropertiesAccessorsObject *self, guint some_uint); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_long (GIMarshallingTestsPropertiesAccessorsObject *self, glong some_long); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_ulong (GIMarshallingTestsPropertiesAccessorsObject *self, gulong some_ulong); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_int64 (GIMarshallingTestsPropertiesAccessorsObject *self, gint64 some_int64); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_uint64 (GIMarshallingTestsPropertiesAccessorsObject *self, guint64 some_uint64); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_float (GIMarshallingTestsPropertiesAccessorsObject *self, gfloat some_float); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_double (GIMarshallingTestsPropertiesAccessorsObject *self, gdouble some_double); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_string (GIMarshallingTestsPropertiesAccessorsObject *self, gchar *some_string); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_strv (GIMarshallingTestsPropertiesAccessorsObject *self, GStrv some_strv); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_boxed_struct (GIMarshallingTestsPropertiesAccessorsObject *self, GIMarshallingTestsBoxedStruct *some_boxed_struct); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_boxed_glist (GIMarshallingTestsPropertiesAccessorsObject *self, GList *some_boxed_glist); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_gvalue (GIMarshallingTestsPropertiesAccessorsObject *self, GValue *some_gvalue); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_variant (GIMarshallingTestsPropertiesAccessorsObject *self, GVariant *some_variant); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_object (GIMarshallingTestsPropertiesAccessorsObject *self, GObject *some_object); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_flags (GIMarshallingTestsPropertiesAccessorsObject *self, GIMarshallingTestsFlags some_flags); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_enum (GIMarshallingTestsPropertiesAccessorsObject *self, GIMarshallingTestsGEnum some_enum); GI_TEST_EXTERN void gi_marshalling_tests_properties_accessors_object_set_byte_array (GIMarshallingTestsPropertiesAccessorsObject *self, GByteArray *some_byte_array); GI_TEST_EXTERN gboolean gi_marshalling_tests_properties_accessors_object_get_boolean (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN gchar gi_marshalling_tests_properties_accessors_object_get_char (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN guchar gi_marshalling_tests_properties_accessors_object_get_uchar (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN gint gi_marshalling_tests_properties_accessors_object_get_int (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN guint gi_marshalling_tests_properties_accessors_object_get_uint (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN glong gi_marshalling_tests_properties_accessors_object_get_long (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN gulong gi_marshalling_tests_properties_accessors_object_get_ulong (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN gint64 gi_marshalling_tests_properties_accessors_object_get_int64 (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN guint64 gi_marshalling_tests_properties_accessors_object_get_uint64 (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN gfloat gi_marshalling_tests_properties_accessors_object_get_float (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN gdouble gi_marshalling_tests_properties_accessors_object_get_double (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN const gchar *gi_marshalling_tests_properties_accessors_object_get_string (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN gchar **gi_marshalling_tests_properties_accessors_object_get_strv (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN GIMarshallingTestsBoxedStruct *gi_marshalling_tests_properties_accessors_object_get_boxed_struct (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN GList *gi_marshalling_tests_properties_accessors_object_get_boxed_glist (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN GValue *gi_marshalling_tests_properties_accessors_object_get_gvalue (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN GVariant *gi_marshalling_tests_properties_accessors_object_get_variant (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN GObject *gi_marshalling_tests_properties_accessors_object_get_object (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN GIMarshallingTestsFlags gi_marshalling_tests_properties_accessors_object_get_flags (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN GIMarshallingTestsGEnum gi_marshalling_tests_properties_accessors_object_get_enum (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN GByteArray *gi_marshalling_tests_properties_accessors_object_get_byte_array (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN gint gi_marshalling_tests_properties_accessors_object_get_readonly (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN G_DEPRECATED gint gi_marshalling_tests_properties_accessors_object_get_deprecated_int (GIMarshallingTestsPropertiesAccessorsObject *self); GI_TEST_EXTERN G_DEPRECATED void gi_marshalling_tests_properties_accessors_object_set_deprecated_int (GIMarshallingTestsPropertiesAccessorsObject *self, gint some_deprecated_int); /* Signals object */ #define GI_MARSHALLING_TESTS_TYPE_SIGNALS_OBJECT (gi_marshalling_tests_signals_object_get_type ()) #define GI_MARSHALLING_TESTS_SIGNALS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GI_MARSHALLING_TESTS_TYPE_SIGNALS_OBJECT, GIMarshallingTestsSignalsObject)) #define GI_MARSHALLING_TESTS_SIGNALS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GI_MARSHALLING_TESTS_TYPE_SIGNALS_OBJECT, GIMarshallingTestsSignalsObjectClass)) #define GI_MARSHALLING_TESTS_IS_SIGNALS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GI_MARSHALLING_TESTS_TYPE_SIGNALS_OBJECT)) #define GI_MARSHALLING_TESTS_IS_SIGNALS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GI_MARSHALLING_TESTS_TYPE_SIGNALS_OBJECT)) #define GI_MARSHALLING_TESTS_SIGNALS_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GI_MARSHALLING_TESTS_TYPE_SIGNALS_OBJECT, GIMarshallingTestsSignalsObjectClass)) typedef struct _GIMarshallingTestsSignalsObject GIMarshallingTestsSignalsObject; typedef struct _GIMarshallingTestsSignalsObjectClass GIMarshallingTestsSignalsObjectClass; struct _GIMarshallingTestsSignalsObject { GObject parent_instance; }; struct _GIMarshallingTestsSignalsObjectClass { GObjectClass parent_class; }; GI_TEST_EXTERN GType gi_marshalling_tests_signals_object_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN GIMarshallingTestsSignalsObject *gi_marshalling_tests_signals_object_new (void); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_utf8 (GIMarshallingTestsSignalsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_utf8_container (GIMarshallingTestsSignalsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_utf8_full (GIMarshallingTestsSignalsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_boxed_struct (GIMarshallingTestsSignalsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_boxed_struct_container (GIMarshallingTestsSignalsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_boxed_gptrarray_boxed_struct_full (GIMarshallingTestsSignalsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_hash_table_utf8_int (GIMarshallingTestsSignalsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_hash_table_utf8_int_container (GIMarshallingTestsSignalsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_hash_table_utf8_int_full (GIMarshallingTestsSignalsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_boxed_struct (GIMarshallingTestsSignalsObject *object); GI_TEST_EXTERN void gi_marshalling_tests_signals_object_emit_boxed_struct_full (GIMarshallingTestsSignalsObject *object); ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/gimarshallingtestsextra.c0000664000000000000000000001310315056773103027475 0ustar00rootroot/* gimarshallingtestsextra.c * * SPDX-License-Identifier: LGPL-2.1-or-later * SPDX-FileCopyrightText: 2016 Thibault Saunier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include "gimarshallingtestsextra.h" void gi_marshalling_tests_compare_two_gerrors_in_gvalue (GValue *v, GValue *v1) { GError *error, *error1; g_assert_cmpstr (g_type_name (G_VALUE_TYPE (v)), ==, g_type_name (G_TYPE_ERROR)); g_assert_cmpstr (g_type_name (G_VALUE_TYPE (v1)), ==, g_type_name (G_TYPE_ERROR)); error = (GError *) g_value_get_boxed (v); error1 = (GError *) g_value_get_boxed (v1); g_assert_cmpint (error->domain, ==, error1->domain); g_assert_cmpint (error->code, ==, error1->code); g_assert_cmpstr (error->message, ==, error1->message); } /** * gi_marshalling_tests_nullable_gerror: * @error: (in) (nullable) (transfer full): * an optional #GError. * * So we've got an API which takes a `GError *` as `(in)` argument, * and we want this to be optional, so we added `(nullable)`. * * Returns: 1 or 0, depending if the error was set. */ gboolean gi_marshalling_tests_nullable_gerror (GError *error) { gboolean retval = error ? 1 : 0; g_clear_error(&error); return retval; } /** * gi_marshalling_tests_ghashtable_enum_none_in: * @hash_table: (element-type gint GIMarshallingTestsExtraEnum) (transfer none): */ void gi_marshalling_tests_ghashtable_enum_none_in (GHashTable *hash_table) { g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (hash_table, GINT_TO_POINTER (1))), ==, GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE1); g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (hash_table, GINT_TO_POINTER (2))), ==, GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE2); g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (hash_table, GINT_TO_POINTER (3))), ==, GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE3); } /** * gi_marshalling_tests_ghashtable_enum_none_return: * * Returns: (element-type gint GIMarshallingTestsExtraEnum) (transfer none): */ GHashTable * gi_marshalling_tests_ghashtable_enum_none_return (void) { static GHashTable *hash_table = NULL; if (hash_table == NULL) { hash_table = g_hash_table_new (NULL, NULL); g_hash_table_insert (hash_table, GINT_TO_POINTER (1), GINT_TO_POINTER (GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE1)); g_hash_table_insert (hash_table, GINT_TO_POINTER (2), GINT_TO_POINTER (GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE2)); g_hash_table_insert (hash_table, GINT_TO_POINTER (3), GINT_TO_POINTER (GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE3)); } return hash_table; } /** * gi_marshalling_tests_filename_copy: * @path_in: (type filename) (nullable) * * Returns: (type filename) (nullable) */ gchar * gi_marshalling_tests_filename_copy (gchar *path_in) { return g_strdup (path_in); } /** * gi_marshalling_tests_filename_to_glib_repr: * @path_in: (type filename) (nullable) * * Returns: (array length=len) (element-type guint8) */ gchar * gi_marshalling_tests_filename_to_glib_repr (gchar *path_in, gsize *len) { *len = strlen (path_in); return g_strdup (path_in); } /** * gi_marshalling_tests_filename_exists: * @path: (type filename) */ gboolean gi_marshalling_tests_filename_exists (gchar *path) { return g_file_test (path, G_FILE_TEST_EXISTS); } /** * gi_marshalling_tests_enum_array_return_type: * @n_members: (out): The number of members * * Returns: (array length=n_members) (transfer full): An array of enum values */ GIMarshallingTestsExtraEnum * gi_marshalling_tests_enum_array_return_type (gsize *n_members) { GIMarshallingTestsExtraEnum *res = g_new0 (GIMarshallingTestsExtraEnum, 3); *n_members = 3; res[0] = GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE1; res[1] = GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE2; res[2] = GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE3; return res; } GType gi_marshalling_tests_extra_flags_get_type (void) { static GType type = 0; if (G_UNLIKELY (type == 0)) { static const GFlagsValue values[] = { { GI_MARSHALLING_TESTS_EXTRA_FLAGS_VALUE1, "GI_MARSHALLING_TESTS_EXTRA_FLAGS_VALUE1", "value1" }, { GI_MARSHALLING_TESTS_EXTRA_FLAGS_VALUE2, "GI_MARSHALLING_TESTS_EXTRA_FLAGS_VALUE2", "value2" }, { 0, NULL, NULL } }; type = g_flags_register_static ( g_intern_static_string ("GIMarshallingTestsExtraFlags"), values); } return type; } /** * gi_marshalling_tests_extra_flags_large_in: */ void gi_marshalling_tests_extra_flags_large_in (GIMarshallingTestsExtraFlags value) { g_assert_cmpint (value, ==, GI_MARSHALLING_TESTS_EXTRA_FLAGS_VALUE2); } /** * gi_marshalling_tests_extra_utf8_full_return_invalid: */ gchar * gi_marshalling_tests_extra_utf8_full_return_invalid (void) { return g_strdup ("invalid utf8 \xff\xfe"); } /** * gi_marshalling_tests_extra_utf8_full_out_invalid: * @utf8: (out) (transfer full): */ void gi_marshalling_tests_extra_utf8_full_out_invalid (gchar **utf8) { *utf8 = g_strdup ("invalid utf8 \xff\xfe"); } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/gimarshallingtestsextra.h0000664000000000000000000000453415056773103027512 0ustar00rootroot/* gimarshallingtestsextra.h * * SPDX-License-Identifier: LGPL-2.1-or-later * SPDX-FileCopyrightText: 2016 Thibault Saunier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #pragma once #include #include #include "gitestmacros.h" typedef enum { GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE1, GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE2, GI_MARSHALLING_TESTS_EXTRA_ENUM_VALUE3 = 42 } GIMarshallingTestsExtraEnum; typedef enum { GI_MARSHALLING_TESTS_EXTRA_FLAGS_VALUE1 = 0, GI_MARSHALLING_TESTS_EXTRA_FLAGS_VALUE2 = (gint) (1 << 31), } GIMarshallingTestsExtraFlags; GI_TEST_EXTERN GType gi_marshalling_tests_extra_flags_get_type (void) G_GNUC_CONST; #define GI_MARSHALLING_TESTS_TYPE_EXTRA_FLAGS (gi_marshalling_tests_extra_flags_get_type ()) GI_TEST_EXTERN void gi_marshalling_tests_compare_two_gerrors_in_gvalue (GValue *v, GValue *v1); GI_TEST_EXTERN gboolean gi_marshalling_tests_nullable_gerror (GError *error); GI_TEST_EXTERN void gi_marshalling_tests_ghashtable_enum_none_in (GHashTable *hash_table); GI_TEST_EXTERN GHashTable *gi_marshalling_tests_ghashtable_enum_none_return (void); GI_TEST_EXTERN gchar *gi_marshalling_tests_filename_copy (gchar *path_in); GI_TEST_EXTERN gboolean gi_marshalling_tests_filename_exists (gchar *path); GI_TEST_EXTERN gchar *gi_marshalling_tests_filename_to_glib_repr (gchar *path_in, gsize *len); GI_TEST_EXTERN GIMarshallingTestsExtraEnum *gi_marshalling_tests_enum_array_return_type (gsize *n_members); GI_TEST_EXTERN void gi_marshalling_tests_extra_flags_large_in (GIMarshallingTestsExtraFlags value); GI_TEST_EXTERN gchar *gi_marshalling_tests_extra_utf8_full_return_invalid (void); GI_TEST_EXTERN void gi_marshalling_tests_extra_utf8_full_out_invalid (gchar **utf8); ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/gitestmacros.h0000664000000000000000000000030315056773103025234 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2014 Chun-wei Fan */ #pragma once #ifndef GI_TEST_EXTERN #define GI_TEST_EXTERN extern #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/gobject-introspection-tests.doap0000664000000000000000000000706415056773103030712 0ustar00rootroot GObject Introspection Tests gobject-introspection-tests Tests for GNOME language bindings This is a test suite for language bindings for the GNOME platform that use GObject Introspection. C Andy Holmes andyholmes Arjan Molenaar amolenaar Christoph Reiter creiter Colin Walters walters Dan Yeaw danyeaw Emmanuele Bassi ebassi Evan Welsh ewlsh Marco Trevisan (Treviño) 3v1n0 marcotrevi Philip Chimento ptomato pchimento Rico Tzschichholz ricotz ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/meson.build0000664000000000000000000001455015056773103024532 0ustar00rootroot# SPDX-License-Identifier: MIT # SPDX-FileCopyrightText: 2024 Philip Chimento project( 'gobject-introspection-tests', 'c', version: 'unversioned', meson_version: '>= 0.61', default_options: ['c_std=c99', 'warning_level=2'] ) gnome = import('gnome') cc = meson.get_compiler('c') msvc = cc.get_argument_syntax() == 'msvc' build_cairo = get_option('cairo') install_dir = get_option('install_dir') install = (install_dir != '') glib_version = '>= 2.66.8' glib_dep = dependency('glib-2.0', version: glib_version) gobject_dep = dependency('gobject-2.0', version: glib_version) gio_dep = dependency('gio-2.0', version: glib_version) if build_cairo cairo_dep = dependency('cairo', required: not msvc) cairo_gobject_dep = dependency('cairo-gobject', required: not msvc) # We might need to look for the headers and libs for Cairo manually on # MSVC/clang-cl builds... if not cairo_dep.found() cairo_dep = cc.find_library( 'cairo', has_headers: ['cairo.h'], required: true ) endif if not cairo_gobject_dep.found() cairo_gobject_dep = cc.find_library( 'cairo-gobject', has_headers: ['cairo-gobject.h'], required: true ) endif endif args = [] if host_machine.system() == 'windows' extern_def = '__declspec(dllexport) extern' else extern_def = '__attribute__((visibility("default"))) extern' endif args += ['-DGI_TEST_EXTERN=@0@'.format(extern_def)] if not build_cairo args += ['-DGI_TEST_DISABLE_CAIRO'] endif add_project_arguments(args, language: 'c') utility_sources = ['utility.c', 'utility.h'] regress_sources = [ 'annotation.c', 'annotation.h', 'drawable.c', 'drawable.h', 'foo.c', 'foo.h', 'regress.c', 'regress.h', 'regressextra.c', 'regressextra.h', ] regress_unix_sources = ['regress-unix.c', 'regress-unix.h'] warnlib_sources = ['warnlib.c', 'warnlib.h'] gimarshallingtests_sources = [ 'gimarshallingtests.c', 'gimarshallingtests.h', 'gimarshallingtestsextra.c', 'gimarshallingtestsextra.h', ] libutility = library( 'utility', utility_sources, dependencies: [glib_dep, gobject_dep], gnu_symbol_visibility: 'hidden', install: install, install_dir: install_dir, ) utility_gir = gnome.generate_gir( libutility, sources: utility_sources, includes: ['GObject-2.0'], namespace: 'Utility', nsversion: '1.0', symbol_prefix: 'utility_', header: 'utility.h', fatal_warnings: get_option('werror'), install_gir: false, install_typelib: install, install_dir_typelib: install_dir, ) utility_typelib = utility_gir[1] regress_dependencies = [glib_dep, gobject_dep, gio_dep] regress_gir_includes = ['Gio-2.0', utility_gir[0]] if build_cairo regress_gir_includes += 'cairo-1.0' regress_dependencies += [cairo_dep, cairo_gobject_dep] endif libregress = library( 'regress', regress_sources + regress_unix_sources, dependencies: regress_dependencies, gnu_symbol_visibility: 'hidden', install: install, install_dir: install_dir, override_options: ['unity=off'], ) regress_gir = gnome.generate_gir( libregress, sources: regress_sources, includes: regress_gir_includes, namespace: 'Regress', nsversion: '1.0', identifier_prefix: 'Regress', symbol_prefix: 'regress_', header: 'regress.h', extra_args: ['--warn-all'], include_directories: meson.current_build_dir(), fatal_warnings: get_option('werror'), install_gir: false, install_typelib: install, install_dir_typelib: install_dir, ) regress_typelib = regress_gir[1] if host_machine.system() != 'windows' regress_unix_gir = gnome.generate_gir( libregress, sources: regress_unix_sources, includes: regress_gir_includes, namespace: 'RegressUnix', nsversion: '1.0', symbol_prefix: 'regress_unix_', header: 'regress-unix.h', include_directories: meson.current_build_dir(), fatal_warnings: get_option('werror'), install_gir: false, install_typelib: install, install_dir_typelib: install_dir, ) else regress_unix_gir = [disabler(), disabler()] endif regress_unix_typelib = regress_unix_gir[1] libwarnlib = library( 'warnlib', warnlib_sources, dependencies: [glib_dep, gobject_dep, gio_dep], gnu_symbol_visibility: 'hidden', install: install, install_dir: install_dir, ) # This should have --warn-all turned off, but there is currently no way to do so # in gnome.generate_gir(). See https://github.com/mesonbuild/meson/issues/5876 warnlib_gir = gnome.generate_gir( libwarnlib, includes: ['Gio-2.0'], sources: warnlib_sources, namespace: 'WarnLib', nsversion: '1.0', symbol_prefix: 'warnlib_', header: 'warnlib.h', fatal_warnings: false, install_gir: false, install_typelib: install, install_dir_typelib: install_dir, ) warnlib_typelib = warnlib_gir[1] libgimarshallingtests = library( 'gimarshallingtests', gimarshallingtests_sources, dependencies: [glib_dep, gobject_dep, gio_dep], gnu_symbol_visibility: 'hidden', install: install, install_dir: install_dir, ) gimarshallingtests_gir = gnome.generate_gir( libgimarshallingtests, sources: gimarshallingtests_sources, includes: ['Gio-2.0'], namespace: 'GIMarshallingTests', nsversion: '1.0', symbol_prefix: 'gi_marshalling_tests_', fatal_warnings: get_option('werror'), install_gir: false, install_typelib: install, install_dir_typelib: install_dir, ) gimarshallingtests_typelib = gimarshallingtests_gir[1] deps = [glib_dep] if build_cairo deps += [cairo_dep, cairo_gobject_dep] endif locations = [] foreach dep: deps if dep.type_name() == 'pkgconfig' locations += 'in @0@'.format(dep.get_variable(pkgconfig: 'prefix')) else locations += dep.type_name() endif endforeach summary({ 'Build type': get_option('buildtype'), 'Install test libraries': install, 'GLib': '@0@ (@1@)'.format(glib_dep.version(), locations[0]), 'Cairo support': build_cairo, }, bool_yn: true) if build_cairo summary({ 'Cairo': '@0@ (@1@)'.format(cairo_dep.version(), locations[1]), 'Cairo-gobject': '@0@ (@1@)'.format(cairo_gobject_dep.version(), locations[2]) }) endif if install summary('Install location', install_dir) endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/meson_options.txt0000664000000000000000000000044115056773103026017 0ustar00rootroot# SPDX-License-Identifier: MIT # SPDX-FileCopyrightText: 2024 Philip Chimento option('cairo', type: 'boolean', value: true, description: 'Cairo support') option('install_dir', type: 'string', description: 'Location to install test libraries and typelibs') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/regress-unix.c0000664000000000000000000000066215056773103025166 0ustar00rootroot/* SPDX-License-Identifier: MIT SPDX-FileCopyrightText: 2024 Simon McVittie */ #include "regress-unix.h" #ifdef G_OS_UNIX dev_t regress_unix_test_devt (dev_t in) { return in; } gid_t regress_unix_test_gidt (gid_t in) { return in; } pid_t regress_unix_test_pidt (pid_t in) { return in; } socklen_t regress_unix_test_socklent (socklen_t in) { return in; } uid_t regress_unix_test_uidt (uid_t in) { return in; } #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/regress-unix.h0000664000000000000000000000077615056773103025201 0ustar00rootroot/* SPDX-License-Identifier: MIT SPDX-FileCopyrightText: 2024 Simon McVittie */ #pragma once #include #ifdef G_OS_UNIX #include #include #include "gitestmacros.h" GI_TEST_EXTERN dev_t regress_unix_test_devt (dev_t in); GI_TEST_EXTERN gid_t regress_unix_test_gidt (gid_t in); GI_TEST_EXTERN pid_t regress_unix_test_pidt (pid_t in); GI_TEST_EXTERN socklen_t regress_unix_test_socklent (socklen_t in); GI_TEST_EXTERN uid_t regress_unix_test_uidt (uid_t in); #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/regress.c0000664000000000000000000040206115056773103024204 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2008-2015 Colin Walters SPDX-FileCopyrightText: 2008 Johan Bilien SPDX-FileCopyrightText: 2008 Lucas Almeida Rocha SPDX-FileCopyrightText: 2008, 2010 Owen W. Taylor SPDX-FileCopyrightText: 2008 Tommi Komulainen SPDX-FileCopyrightText: 2009 Andreas Rottmann SPDX-FileCopyrightText: 2009 Havoc Pennington SPDX-FileCopyrightText: 2009-2010 Johan Dahlin SPDX-FileCopyrightText: 2009-2011 litl, LLC SPDX-FileCopyrightText: 2009 Mark Lee SPDX-FileCopyrightText: 2009 Maxim Ermilov SPDX-FileCopyrightText: 2009 Simon van der Linden SPDX-FileCopyrightText: 2009-2010 Sugar Labs SPDX-FileCopyrightText: 2010-2012, 2015 Collabora, Ltd. SPDX-FileCopyrightText: 2010 Jonathan Matthew SPDX-FileCopyrightText: 2010 Zach Goldberg SPDX-FileCopyrightText: 2011-2012, 2014 Giovanni Campagna SPDX-FileCopyrightText: 2011-2013 Martin Pitt SPDX-FileCopyrightText: 2011 Pavel Holejsovsky SPDX-FileCopyrightText: 2011, 2024 Red Hat, Inc. SPDX-FileCopyrightText: 2011 Xavier Claessens SPDX-FileCopyrightText: 2012 Bastian Winkler SPDX-FileCopyrightText: 2012 Canonical Ltd. SPDX-FileCopyrightText: 2012 Coeus Group SPDX-FileCopyrightText: 2012 Dieter Verfaillie SPDX-FileCopyrightText: 2012 Jasper St. Pierre SPDX-FileCopyrightText: 2012 Jon Nordby SPDX-FileCopyrightText: 2012 Paolo Borelli SPDX-FileCopyrightText: 2012 Simon Feltman SPDX-FileCopyrightText: 2012 Torsten Schönfeld SPDX-FileCopyrightText: 2014-2015 RIFT.io, Inc. SPDX-FileCopyrightText: 2015, 2018 Christoph Reiter SPDX-FileCopyrightText: 2015 Debarshi Ray SPDX-FileCopyrightText: 2015 Ben Iofel SPDX-FileCopyrightText: 2016 Lionel Landwerlin SPDX-FileCopyrightText: 2016-2019, 2024 Philip Chimento SPDX-FileCopyrightText: 2017 Endless Mobile, Inc. SPDX-FileCopyrightText: 2017 Rico Tzschichholz SPDX-FileCopyrightText: 2018-2019 Tomasz MiÄ…sko SPDX-FileCopyrightText: 2019, 2021 Emmanuele Bassi SPDX-FileCopyrightText: 2021, 2023 Marco Trevisan SPDX-FileCopyrightText: 2023 Evan Welsh SPDX-FileCopyrightText: 2024 Simon McVittie */ #include #include #include #include #ifndef GI_TEST_DISABLE_CAIRO #include #include #endif /* GI_TEST_DISABLE_CAIRO */ #include "regress.h" /* return annotations */ /** * regress_test_return_allow_none: * * Returns: (allow-none): */ char * regress_test_return_allow_none (void) { return NULL; } /** * regress_test_return_nullable: * * Returns: (nullable): */ char * regress_test_return_nullable (void) { return NULL; } /* basic types */ gboolean regress_test_boolean (gboolean in) { return in; } gboolean regress_test_boolean_true (gboolean in) { g_assert_true (in); return in; } gboolean regress_test_boolean_false (gboolean in) { g_assert_false (in); return in; } gint8 regress_test_int8 (gint8 in) { return in; } guint8 regress_test_uint8 (guint8 in) { return in; } gint16 regress_test_int16 (gint16 in) { return in; } guint16 regress_test_uint16 (guint16 in) { return in; } gint32 regress_test_int32 (gint32 in) { return in; } guint32 regress_test_uint32 (guint32 in) { return in; } gint64 regress_test_int64 (gint64 in) { return in; } guint64 regress_test_uint64 (guint64 in) { return in; } gshort regress_test_short (gshort in) { return in; } gushort regress_test_ushort (gushort in) { return in; } gint regress_test_int (gint in) { return in; } guint regress_test_uint (guint in) { return in; } glong regress_test_long (glong in) { return in; } gulong regress_test_ulong (gulong in) { return in; } gssize regress_test_ssize (gssize in) { return in; } gsize regress_test_size (gsize in) { return in; } gfloat regress_test_float (gfloat in) { return in; } gdouble regress_test_double (gdouble in) { return in; } gunichar regress_test_unichar (gunichar in) { return in; } time_t regress_test_timet (time_t in) { return in; } off_t regress_test_offt (off_t in) { return in; } GType regress_test_gtype (GType in) { return in; } int regress_test_closure (GClosure *closure) { GValue return_value = { 0, }; int ret; g_value_init (&return_value, G_TYPE_INT); g_closure_invoke (closure, &return_value, 0, NULL, NULL); ret = g_value_get_int (&return_value); g_value_unset (&return_value); return ret; } int regress_test_closure_one_arg (GClosure *closure, int arg) { GValue return_value = { 0, }; GValue arguments[1]; int ret; g_value_init (&return_value, G_TYPE_INT); memset (&arguments[0], 0, sizeof (arguments)); g_value_init (&arguments[0], G_TYPE_INT); g_value_set_int (&arguments[0], arg); g_closure_invoke (closure, &return_value, 1, arguments, NULL); ret = g_value_get_int (&return_value); g_value_unset (&return_value); g_value_unset (&arguments[0]); return ret; } /** * regress_test_closure_variant: * @closure: GClosure which takes one GVariant and returns a GVariant * @arg: (allow-none) (transfer none): a GVariant passed as argument to @closure * * Return value: (transfer full): the return value of @closure */ GVariant * regress_test_closure_variant (GClosure *closure, GVariant *arg) { GValue return_value = { 0, }; GValue arguments[1] = { { 0, } }; GVariant *ret; g_value_init (&return_value, G_TYPE_VARIANT); g_value_init (&arguments[0], G_TYPE_VARIANT); g_value_set_variant (&arguments[0], arg); g_closure_invoke (closure, &return_value, 1, arguments, NULL); ret = g_value_get_variant (&return_value); if (ret != NULL) g_variant_ref (ret); g_value_unset (&return_value); g_value_unset (&arguments[0]); return ret; } /** * regress_test_value_arg: * @v: (transfer none): a GValue expected to contain an int * * Return value: the int contained in the GValue. */ int regress_test_int_value_arg (const GValue *v) { int i; i = g_value_get_int (v); return i; } static GValue global_value; /** * regress_test_value_return: * @i: an int * * Return value: (transfer none): the int wrapped in a GValue. */ const GValue * regress_test_value_return (int i) { memset (&global_value, '\0', sizeof (GValue)); g_value_init (&global_value, G_TYPE_INT); g_value_set_int (&global_value, i); return &global_value; } /************************************************************************/ /* foreign structs */ #ifndef GI_TEST_DISABLE_CAIRO /** * regress_test_cairo_context_full_return: * * Returns: (transfer full): */ cairo_t * regress_test_cairo_context_full_return (void) { cairo_surface_t *surface; cairo_t *cr; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 10, 10); cr = cairo_create (surface); cairo_surface_destroy (surface); return cr; } /** * regress_test_cairo_context_none_in: * @context: (transfer none): */ void regress_test_cairo_context_none_in (cairo_t *context) { cairo_surface_t *surface = cairo_get_target (context); g_assert (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_ARGB32); g_assert (cairo_image_surface_get_width (surface) == 10); g_assert (cairo_image_surface_get_height (surface) == 10); } /** * regress_test_cairo_surface_none_return: * * Returns: (transfer none): */ cairo_surface_t * regress_test_cairo_surface_none_return (void) { static cairo_surface_t *surface; if (surface == NULL) { surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 10, 10); } return surface; } /** * regress_test_cairo_surface_full_return: * * Returns: (transfer full): */ cairo_surface_t * regress_test_cairo_surface_full_return (void) { return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 10, 10); } /** * regress_test_cairo_surface_none_in: * @surface: (transfer none): */ void regress_test_cairo_surface_none_in (cairo_surface_t *surface) { g_assert (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_ARGB32); g_assert (cairo_image_surface_get_width (surface) == 10); g_assert (cairo_image_surface_get_height (surface) == 10); } /** * regress_test_cairo_surface_full_out: * @surface: (out) (transfer full): */ void regress_test_cairo_surface_full_out (cairo_surface_t **surface) { *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 10, 10); } #endif /* GI_TEST_DISABLE_CAIRO */ /** * regress_test_gvariant_i: * * Returns: (transfer none): New variant */ GVariant * regress_test_gvariant_i (void) { return g_variant_new_int32 (1); } /** * regress_test_gvariant_s: * * Returns: (transfer none): New variant */ GVariant * regress_test_gvariant_s (void) { return g_variant_new_string ("one"); } /** * regress_test_gvariant_asv: * * Returns: (transfer none): New variant */ GVariant * regress_test_gvariant_asv (void) { GVariantBuilder b; g_variant_builder_init (&b, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&b, "{sv}", "name", g_variant_new_string ("foo")); g_variant_builder_add (&b, "{sv}", "timeout", g_variant_new_int32 (10)); return g_variant_builder_end (&b); } /** * regress_test_gvariant_v: * * Returns: (transfer none): New variant */ GVariant * regress_test_gvariant_v (void) { return g_variant_new_variant (g_variant_new_string ("contents")); } /** * regress_test_gvariant_as: * * Returns: (transfer none): New variant */ GVariant * regress_test_gvariant_as (void) { const char *as[] = { "one", "two", "three", NULL }; return g_variant_new_strv (as, -1); } /************************************************************************/ /* utf8 */ /* insert BLACK HEART SUIT to ensure UTF-8 doesn't get mangled */ static const char utf8_const[] = "const \xe2\x99\xa5 utf8"; static const char utf8_nonconst[] = "nonconst \xe2\x99\xa5 utf8"; /** * regress_test_utf8_const_return: * * Return value: UTF-8 string */ const char * regress_test_utf8_const_return (void) { /* transfer mode none */ return utf8_const; } /** * regress_test_utf8_nonconst_return: * * Return value: (transfer full): UTF-8 string */ char * regress_test_utf8_nonconst_return (void) { return g_strdup (utf8_nonconst); } /** * regress_test_utf8_const_in: * */ void regress_test_utf8_const_in (const char *in) { /* transfer mode none */ g_assert (strcmp (in, utf8_const) == 0); } /** * regress_test_utf8_out: * @out: (out) (transfer full): */ void regress_test_utf8_out (char **out) { /* out parameter, transfer mode full */ *out = g_strdup (utf8_nonconst); } /** * regress_test_utf8_inout: * @inout: (inout) (transfer full): */ void regress_test_utf8_inout (char **inout) { /* inout parameter, transfer mode full */ g_assert (strcmp (*inout, utf8_const) == 0); g_free (*inout); *inout = g_strdup (utf8_nonconst); } /** * regress_test_filename_return: * * Return value: (element-type filename) (transfer full): list of strings */ GSList * regress_test_filename_return (void) { GSList *filenames = NULL; filenames = g_slist_prepend (filenames, g_filename_from_utf8 ("/etc/fstab", -1, NULL, NULL, NULL)); filenames = g_slist_prepend (filenames, g_filename_from_utf8 ("åäö", -1, NULL, NULL, NULL)); return filenames; } /* in arguments after out arguments */ /** * regress_test_int_out_utf8: * @length: (out): * @in: */ void regress_test_int_out_utf8 (int *length, const char *in) { *length = g_utf8_strlen (in, -1); } /* multiple output arguments */ /** * regress_test_multi_double_args: * @in: * @one: (out): * @two: (out): */ void regress_test_multi_double_args (gdouble in, gdouble *one, gdouble *two) { *one = in * 2; *two = in * 3; } /** * regress_test_utf8_out_out: * @out0: (out) (transfer full): a copy of "first" * @out1: (out) (transfer full): a copy of "second" */ void regress_test_utf8_out_out (char **out0, char **out1) { *out0 = g_strdup ("first"); *out1 = g_strdup ("second"); } /** * regress_test_utf8_out_nonconst_return: * @out: (out) (transfer full): a copy of "second" * * Returns: (transfer full): a copy of "first" */ char * regress_test_utf8_out_nonconst_return (char **out) { *out = g_strdup ("second"); return g_strdup ("first"); } /** * regress_test_utf8_null_in: * @in: (allow-none): */ void regress_test_utf8_null_in (char *in) { g_assert (in == NULL); } /** * regress_test_utf8_null_out: * @char_out: (allow-none) (out): */ void regress_test_utf8_null_out (char **char_out) { *char_out = NULL; } /* non-basic-types */ static const char *test_sequence[] = { "1", "2", "3" }; /* array */ /** * regress_test_array_int_in: * @n_ints: * @ints: (array length=n_ints): List of ints */ int regress_test_array_int_in (int n_ints, int *ints) { int i, sum = 0; for (i = 0; i < n_ints; i++) sum += ints[i]; return sum; } /** * regress_test_array_int_out: * @n_ints: (out): the length of @ints * @ints: (out) (array length=n_ints) (transfer full): a list of 5 integers, from 0 to 4 in consecutive order */ void regress_test_array_int_out (int *n_ints, int **ints) { int i; *n_ints = 5; *ints = g_malloc0 (sizeof (**ints) * *n_ints); for (i = 1; i < *n_ints; i++) (*ints)[i] = (*ints)[i - 1] + 1; } /** * regress_test_array_int_inout: * @n_ints: (inout): the length of @ints * @ints: (inout) (array length=n_ints) (transfer full): a list of integers whose items will be increased by 1, except the first that will be dropped */ void regress_test_array_int_inout (int *n_ints, int **ints) { int i; int *new_ints; if (0 < *n_ints) { *n_ints -= 1; new_ints = g_malloc (sizeof (**ints) * *n_ints); for (i = 0; i < *n_ints; i++) new_ints[i] = (*ints)[i + 1] + 1; g_free (*ints); *ints = new_ints; } } /** * regress_test_array_gint8_in: * @n_ints: * @ints: (array length=n_ints): List of ints */ int regress_test_array_gint8_in (int n_ints, gint8 *ints) { int i, sum = 0; for (i = 0; i < n_ints; i++) sum += ints[i]; return sum; } /** * regress_test_array_gint16_in: * @n_ints: * @ints: (array length=n_ints): List of ints */ int regress_test_array_gint16_in (int n_ints, gint16 *ints) { int i, sum = 0; for (i = 0; i < n_ints; i++) sum += ints[i]; return sum; } /** * regress_test_array_gint32_in: * @n_ints: * @ints: (array length=n_ints): List of ints */ gint32 regress_test_array_gint32_in (int n_ints, gint32 *ints) { int i; gint32 sum = 0; for (i = 0; i < n_ints; i++) sum += ints[i]; return sum; } /** * regress_test_array_gint64_in: * @n_ints: * @ints: (array length=n_ints): List of ints */ gint64 regress_test_array_gint64_in (int n_ints, gint64 *ints) { int i; gint64 sum = 0; for (i = 0; i < n_ints; i++) sum += ints[i]; return sum; } /** * regress_test_strv_in: * @arr: (array zero-terminated=1) (transfer none): */ gboolean regress_test_strv_in (char **arr) { if (g_strv_length (arr) != 3) return FALSE; if (strcmp (arr[0], "1") != 0) return FALSE; if (strcmp (arr[1], "2") != 0) return FALSE; if (strcmp (arr[2], "3") != 0) return FALSE; return TRUE; } /** * regress_test_array_gtype_in: * @n_types: * @types: (array length=n_types): List of types * * Return value: (transfer full): string representation of provided types */ char * regress_test_array_gtype_in (int n_types, GType *types) { GString *string; int i; string = g_string_new ("["); for (i = 0; i < n_types; i++) { g_string_append (string, g_type_name (types[i])); g_string_append_c (string, ','); } g_string_append_c (string, ']'); return g_string_free (string, FALSE); } /** * regress_test_strv_out: * * Returns: (transfer full): */ char ** regress_test_strv_out (void) { int i = 0; int n = 6; char **ret = g_new (char *, n); ret[i++] = g_strdup ("thanks"); ret[i++] = g_strdup ("for"); ret[i++] = g_strdup ("all"); ret[i++] = g_strdup ("the"); ret[i++] = g_strdup ("fish"); ret[i++] = NULL; g_assert (i == n); return ret; } /** * regress_test_strv_out_container: * * Return value: (array zero-terminated=1) (transfer container): */ const char ** regress_test_strv_out_container (void) { const char **ret = g_new (const char *, 4); ret[0] = "1"; ret[1] = "2"; ret[2] = "3"; ret[3] = NULL; return ret; } /** * regress_test_strv_outarg: * @retp: (array zero-terminated=1) (out) (transfer container): */ void regress_test_strv_outarg (const char ***retp) { const char **ret = g_new (const char *, 4); ret[0] = "1"; ret[1] = "2"; ret[2] = "3"; ret[3] = NULL; *retp = ret; } /** * regress_test_array_fixed_size_int_in: * @ints: (array fixed-size=5): a list of 5 integers * * Returns: the sum of the items in @ints */ int regress_test_array_fixed_size_int_in (int *ints) { int i, sum = 0; for (i = 0; i < 5; i++) sum += ints[i]; return sum; } /** * regress_test_array_fixed_size_int_out: * @ints: (out) (array fixed-size=5) (transfer full): a list of 5 integers ranging from 0 to 4 */ void regress_test_array_fixed_size_int_out (int **ints) { int i; *ints = g_malloc0 (sizeof (**ints) * 5); for (i = 1; i < 5; i++) (*ints)[i] = (*ints)[i - 1] + 1; } /** * regress_test_array_fixed_size_int_return: * * Returns: (array fixed-size=5) (transfer full): a list of 5 integers ranging from 0 to 4 */ int * regress_test_array_fixed_size_int_return (void) { int i, *ints; ints = g_malloc0 (sizeof (*ints) * 5); for (i = 1; i < 5; i++) ints[i] = ints[i - 1] + 1; return ints; } /** * regress_test_array_static_in_int * @x: (array fixed-size=10): a list of 10 integers */ #if (defined(__GNUC__) || defined(__clang__)) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L void regress_test_array_static_in_int (int x[static 10] G_GNUC_UNUSED) { } #else void regress_test_array_static_in_int (int x[10]) { } #endif /** * regress_test_strv_out_c: * * Returns: (transfer none): */ const char *const * regress_test_strv_out_c (void) { static char **ret = NULL; if (ret == NULL) ret = regress_test_strv_out (); return (const char *const *) ret; } /** * regress_test_array_int_full_out: * @len: length of the returned array. * * Returns: (array length=len) (transfer full): a new array of integers. */ int * regress_test_array_int_full_out (int *len) { int *result, i; *len = 5; result = g_malloc0 (sizeof (*result) * (*len)); for (i = 1; i < (*len); i++) result[i] = result[i - 1] + 1; return result; } /** * regress_test_array_int_none_out: * @len: length of the returned array. * * Returns: (array length=len) (transfer none): a static array of integers. */ int * regress_test_array_int_none_out (int *len) { static int result[5] = { 1, 2, 3, 4, 5 }; *len = 5; return result; } /** * regress_test_array_int_null_in: * @arr: (array length=len) (allow-none): * @len: length */ void regress_test_array_int_null_in (int *arr, int len G_GNUC_UNUSED) { g_assert (arr == NULL); } /** * regress_test_array_int_null_out: * @arr: (out) (array length=len) (allow-none): * @len: (out) : length */ void regress_test_array_int_null_out (int **arr, int *len) { *arr = NULL; *len = 0; } /* interface */ /************************************************************************/ /* GList */ static /*const*/ GList * regress_test_sequence_list (void) { static GList *list = NULL; if (!list) { gsize i; for (i = 0; i < G_N_ELEMENTS (test_sequence); ++i) { list = g_list_prepend (list, (gpointer) test_sequence[i]); } list = g_list_reverse (list); } return list; } /** * regress_test_glist_nothing_return: * * Return value: (element-type utf8) (transfer none): */ const GList * regress_test_glist_nothing_return (void) { return regress_test_sequence_list (); } /** * regress_test_glist_nothing_return2: * * Return value: (element-type utf8) (transfer none): */ GList * regress_test_glist_nothing_return2 (void) { return regress_test_sequence_list (); } /** * regress_test_glist_container_return: * * Return value: (element-type utf8) (transfer container): */ GList * regress_test_glist_container_return (void) { return g_list_copy (regress_test_sequence_list ()); } /** * regress_test_glist_everything_return: * * Return value: (element-type utf8) (transfer full): */ GList * regress_test_glist_everything_return (void) { GList *list; GList *l; list = g_list_copy (regress_test_sequence_list ()); for (l = list; l != NULL; l = l->next) l->data = g_strdup (l->data); return list; } static void regress_assert_test_sequence_list (const GList *in) { const GList *l; gsize i; for (i = 0, l = in; l != NULL; ++i, l = l->next) { g_assert (i < G_N_ELEMENTS (test_sequence)); g_assert (strcmp (l->data, test_sequence[i]) == 0); } g_assert (i == G_N_ELEMENTS (test_sequence)); } /** * regress_test_glist_gtype_container_in: * @in: (element-type GType) (transfer container): */ void regress_test_glist_gtype_container_in (GList *in) { GList *l = in; g_assert (GPOINTER_TO_SIZE (l->data) == REGRESS_TEST_TYPE_OBJ); l = l->next; g_assert (GPOINTER_TO_SIZE (l->data) == REGRESS_TEST_TYPE_SUB_OBJ); l = l->next; g_assert (l == NULL); g_list_free (in); } /** * regress_test_glist_nothing_in: * @in: (element-type utf8): */ void regress_test_glist_nothing_in (const GList *in) { regress_assert_test_sequence_list (in); } /** * regress_test_glist_nothing_in2: * @in: (element-type utf8): */ void regress_test_glist_nothing_in2 (GList *in) { regress_assert_test_sequence_list (in); } /** * regress_test_glist_null_in: * @in: (element-type utf8) (allow-none): */ void regress_test_glist_null_in (GSList *in) { g_assert (in == NULL); } /** * regress_test_glist_null_out: * @out_list: (out) (element-type utf8) (allow-none): */ void regress_test_glist_null_out (GSList **out_list) { *out_list = NULL; } /************************************************************************/ /* GSList */ static /*const*/ GSList * regress_test_sequence_slist (void) { static GSList *list = NULL; if (!list) { gsize i; for (i = 0; i < G_N_ELEMENTS (test_sequence); ++i) { list = g_slist_prepend (list, (gpointer) test_sequence[i]); } list = g_slist_reverse (list); } return list; } /** * regress_test_gslist_nothing_return: * * Return value: (element-type utf8) (transfer none): */ const GSList * regress_test_gslist_nothing_return (void) { return regress_test_sequence_slist (); } /** * regress_test_gslist_nothing_return2: * * Return value: (element-type utf8) (transfer none): */ GSList * regress_test_gslist_nothing_return2 (void) { return regress_test_sequence_slist (); } /** * regress_test_gslist_container_return: * * Return value: (element-type utf8) (transfer container): */ GSList * regress_test_gslist_container_return (void) { return g_slist_copy (regress_test_sequence_slist ()); } /** * regress_test_gslist_everything_return: * * Return value: (element-type utf8) (transfer full): */ GSList * regress_test_gslist_everything_return (void) { GSList *list; GSList *l; list = g_slist_copy (regress_test_sequence_slist ()); for (l = list; l != NULL; l = l->next) l->data = g_strdup (l->data); return list; } static void regress_assert_test_sequence_slist (const GSList *in) { const GSList *l; gsize i; for (i = 0, l = in; l != NULL; ++i, l = l->next) { g_assert (i < G_N_ELEMENTS (test_sequence)); g_assert (strcmp (l->data, test_sequence[i]) == 0); } g_assert (i == G_N_ELEMENTS (test_sequence)); } /** * regress_test_gslist_nothing_in: * @in: (element-type utf8): */ void regress_test_gslist_nothing_in (const GSList *in) { regress_assert_test_sequence_slist (in); } /** * regress_test_gslist_nothing_in2: * @in: (element-type utf8): */ void regress_test_gslist_nothing_in2 (GSList *in) { regress_assert_test_sequence_slist (in); } /** * regress_test_gslist_null_in: * @in: (element-type utf8) (allow-none): */ void regress_test_gslist_null_in (GSList *in) { g_assert (in == NULL); } /** * regress_test_gslist_null_out: * @out_list: (out) (element-type utf8) (allow-none): */ void regress_test_gslist_null_out (GSList **out_list) { *out_list = NULL; } /************************************************************************/ /* GHash */ static const char *table_data[3][2] = { { "foo", "bar" }, { "baz", "bat" }, { "qux", "quux" } }; static GHashTable * regress_test_table_ghash_new_container (void) { GHashTable *hash; int i; hash = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; i < 3; i++) g_hash_table_insert (hash, (gpointer) table_data[i][0], (gpointer) table_data[i][1]); return hash; } static GHashTable * regress_test_table_ghash_new_full (void) { GHashTable *hash; int i; hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (i = 0; i < 3; i++) g_hash_table_insert (hash, g_strdup (table_data[i][0]), g_strdup (table_data[i][1])); return hash; } static /*const*/ GHashTable * regress_test_table_ghash_const (void) { static GHashTable *hash = NULL; if (!hash) { hash = regress_test_table_ghash_new_container (); } return hash; } /** * regress_test_ghash_null_return: * * Return value: (element-type utf8 utf8) (transfer none) (allow-none): */ const GHashTable * regress_test_ghash_null_return (void) { return NULL; } /** * regress_test_ghash_nothing_return: * * Return value: (element-type utf8 utf8) (transfer none): */ const GHashTable * regress_test_ghash_nothing_return (void) { return regress_test_table_ghash_const (); } /** * regress_test_ghash_nothing_return2: * * Return value: (element-type utf8 utf8) (transfer none): */ GHashTable * regress_test_ghash_nothing_return2 (void) { return regress_test_table_ghash_const (); } static GValue * g_value_new (GType type) { GValue *value = g_slice_new0 (GValue); g_value_init (value, type); return value; } static void g_value_free (GValue *value) { g_value_unset (value); g_slice_free (GValue, value); } static const gchar *string_array[] = { "first", "second", "third", NULL }; /** * regress_test_ghash_gvalue_return: * * Return value: (element-type utf8 GValue) (transfer none): */ GHashTable * regress_test_ghash_gvalue_return (void) { static GHashTable *hash = NULL; if (hash == NULL) { GValue *value; hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_value_free); value = g_value_new (G_TYPE_INT); g_value_set_int (value, 12); g_hash_table_insert (hash, g_strdup ("integer"), value); value = g_value_new (G_TYPE_BOOLEAN); g_value_set_boolean (value, TRUE); g_hash_table_insert (hash, g_strdup ("boolean"), value); value = g_value_new (G_TYPE_STRING); g_value_set_string (value, "some text"); g_hash_table_insert (hash, g_strdup ("string"), value); value = g_value_new (G_TYPE_STRV); g_value_set_boxed (value, string_array); g_hash_table_insert (hash, g_strdup ("strings"), value); value = g_value_new (REGRESS_TEST_TYPE_FLAGS); g_value_set_flags (value, REGRESS_TEST_FLAG1 | REGRESS_TEST_FLAG3); g_hash_table_insert (hash, g_strdup ("flags"), value); value = g_value_new (regress_test_enum_get_type ()); g_value_set_enum (value, REGRESS_TEST_VALUE2); g_hash_table_insert (hash, g_strdup ("enum"), value); } return hash; } /** * regress_test_ghash_gvalue_in: * @hash: (element-type utf8 GValue): the hash table returned by * regress_test_ghash_gvalue_return(). */ void regress_test_ghash_gvalue_in (GHashTable *hash) { GValue *value; const gchar **strings; int i; g_assert (hash != NULL); value = g_hash_table_lookup (hash, "integer"); g_assert (value != NULL); g_assert (G_VALUE_HOLDS_INT (value)); g_assert (g_value_get_int (value) == 12); value = g_hash_table_lookup (hash, "boolean"); g_assert (value != NULL); g_assert (G_VALUE_HOLDS_BOOLEAN (value)); g_assert (g_value_get_boolean (value) == TRUE); value = g_hash_table_lookup (hash, "string"); g_assert (value != NULL); g_assert (G_VALUE_HOLDS_STRING (value)); g_assert (strcmp (g_value_get_string (value), "some text") == 0); value = g_hash_table_lookup (hash, "strings"); g_assert (value != NULL); g_assert (G_VALUE_HOLDS (value, G_TYPE_STRV)); strings = g_value_get_boxed (value); g_assert (strings != NULL); for (i = 0; string_array[i] != NULL; i++) g_assert (strcmp (strings[i], string_array[i]) == 0); value = g_hash_table_lookup (hash, "flags"); g_assert (value != NULL); g_assert (G_VALUE_HOLDS_FLAGS (value)); g_assert (g_value_get_flags (value) == (REGRESS_TEST_FLAG1 | REGRESS_TEST_FLAG3)); value = g_hash_table_lookup (hash, "enum"); g_assert (value != NULL); g_assert (G_VALUE_HOLDS_ENUM (value)); g_assert (g_value_get_enum (value) == REGRESS_TEST_VALUE2); } /** * regress_test_ghash_container_return: * * Return value: (element-type utf8 utf8) (transfer container): */ GHashTable * regress_test_ghash_container_return (void) { return regress_test_table_ghash_new_container (); } /** * regress_test_ghash_everything_return: * * Return value: (element-type utf8 utf8) (transfer full): */ GHashTable * regress_test_ghash_everything_return (void) { return regress_test_table_ghash_new_full (); } static void assert_test_table_ghash (const GHashTable *in) { GHashTable *h = regress_test_table_ghash_const (); GHashTableIter iter; gpointer key, value; g_assert (g_hash_table_size (h) == g_hash_table_size ((GHashTable *) in)); g_hash_table_iter_init (&iter, (GHashTable *) in); while (g_hash_table_iter_next (&iter, &key, &value)) g_assert (strcmp (g_hash_table_lookup (h, (char *) key), (char *) value) == 0); } /** * regress_test_ghash_null_in: * @in: (element-type utf8 utf8) (allow-none): */ void regress_test_ghash_null_in (const GHashTable *in) { g_assert (in == NULL); } /** * regress_test_ghash_null_out: * @out: (element-type utf8 utf8) (allow-none) (out): */ void regress_test_ghash_null_out (const GHashTable **out) { *out = NULL; } /** * regress_test_ghash_nothing_in: * @in: (element-type utf8 utf8): */ void regress_test_ghash_nothing_in (const GHashTable *in) { assert_test_table_ghash (in); } /** * regress_test_ghash_nothing_in2: * @in: (element-type utf8 utf8): */ void regress_test_ghash_nothing_in2 (GHashTable *in) { assert_test_table_ghash (in); } /* Nested collection types */ /** * regress_test_ghash_nested_everything_return: * * Specify nested parameterized types directly with the (type ) annotation. * * Return value: (type GLib.HashTable>) (transfer full): */ GHashTable * regress_test_ghash_nested_everything_return (void) { GHashTable *hash; hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (void (*) (gpointer)) g_hash_table_destroy); g_hash_table_insert (hash, g_strdup ("wibble"), regress_test_table_ghash_new_full ()); return hash; } /** * regress_test_ghash_nested_everything_return2: * * Another way of specifying nested parameterized types: using the * element-type annotation. * * Return value: (element-type utf8 GLib.HashTable) (transfer full): */ GHashTable * regress_test_ghash_nested_everything_return2 (void) { return regress_test_ghash_nested_everything_return (); } /************************************************************************/ /** * regress_test_garray_container_return: * * Returns: (transfer container) (type GLib.PtrArray) (element-type utf8): */ GPtrArray * regress_test_garray_container_return (void) { GPtrArray *array; array = g_ptr_array_new_with_free_func (g_free); g_ptr_array_add (array, g_strdup ("regress")); return array; } /** * regress_test_garray_full_return: * * Returns: (transfer full) (type GLib.PtrArray) (element-type utf8): */ GPtrArray * regress_test_garray_full_return (void) { GPtrArray *array; array = g_ptr_array_new (); g_ptr_array_add (array, g_strdup ("regress")); return array; } /************************************************************************/ /* error? */ /* enums / flags */ /** * NUM_REGRESS_FOO: (skip) * * num of elements in RegressFoo */ GType regress_test_enum_get_type (void) { static GType etype = 0; if (G_UNLIKELY (etype == 0)) { static const GEnumValue values[] = { { REGRESS_TEST_VALUE1, "REGRESS_TEST_VALUE1", "value1" }, { REGRESS_TEST_VALUE2, "REGRESS_TEST_VALUE2", "value2" }, { REGRESS_TEST_VALUE3, "REGRESS_TEST_VALUE3", "value3" }, { REGRESS_TEST_VALUE4, "REGRESS_TEST_VALUE4", "value4" }, { REGRESS_TEST_VALUE5, "REGRESS_TEST_VALUE5", "value5" }, { 0, NULL, NULL } }; etype = g_enum_register_static (g_intern_static_string ("RegressTestEnum"), values); } return etype; } GType regress_test_enum_unsigned_get_type (void) { static GType etype = 0; if (G_UNLIKELY (etype == 0)) { static const GEnumValue values[] = { { REGRESS_TEST_UNSIGNED_VALUE1, "REGRESS_TEST_UNSIGNED_VALUE1", "value1" }, { REGRESS_TEST_UNSIGNED_VALUE2, "REGRESS_TEST_UNSIGNED_VALUE2", "value2" }, { 0, NULL, NULL } }; etype = g_enum_register_static (g_intern_static_string ("RegressTestEnumUnsigned"), values); } return etype; } GType regress_test_flags_get_type (void) { static GType etype = 0; if (G_UNLIKELY (etype == 0)) { static const GFlagsValue values[] = { { REGRESS_TEST_FLAG1, "TEST_FLAG1", "flag1" }, { REGRESS_TEST_FLAG2, "TEST_FLAG2", "flag2" }, { REGRESS_TEST_FLAG3, "TEST_FLAG3", "flag3" }, { 0, NULL, NULL } }; etype = g_flags_register_static (g_intern_static_string ("RegressTestFlags"), values); } return etype; } const gchar * regress_test_enum_param (RegressTestEnum e) { GEnumValue *ev; GEnumClass *ec; ec = g_type_class_ref (regress_test_enum_get_type ()); ev = g_enum_get_value (ec, e); g_type_class_unref (ec); return ev->value_nick; } const gchar * regress_test_unsigned_enum_param (RegressTestEnumUnsigned e) { GEnumValue *ev; GEnumClass *ec; ec = g_type_class_ref (regress_test_enum_unsigned_get_type ()); ev = g_enum_get_value (ec, e); g_type_class_unref (ec); return ev->value_nick; } /** * regress_global_get_flags_out: * @v: (out): A flags value * */ void regress_global_get_flags_out (RegressTestFlags *v) { *v = REGRESS_TEST_FLAG1 | REGRESS_TEST_FLAG3; } /* error domains */ GType regress_test_error_get_type (void) { static GType etype = 0; if (G_UNLIKELY (etype == 0)) { static const GEnumValue values[] = { { REGRESS_TEST_ERROR_CODE1, "REGRESS_TEST_ERROR_CODE1", "code1" }, { REGRESS_TEST_ERROR_CODE2, "REGRESS_TEST_ERROR_CODE2", "code2" }, { REGRESS_TEST_ERROR_CODE3, "REGRESS_TEST_ERROR_CODE3", "code3" }, { 0, NULL, NULL } }; etype = g_enum_register_static (g_intern_static_string ("RegressTestError"), values); } return etype; } GQuark regress_test_error_quark (void) { return g_quark_from_static_string ("regress-test-error"); } GType regress_test_abc_error_get_type (void) { static GType etype = 0; if (G_UNLIKELY (etype == 0)) { static const GEnumValue values[] = { { REGRESS_TEST_ABC_ERROR_CODE1, "REGRESS_TEST_ABC_ERROR_CODE1", "code1" }, { REGRESS_TEST_ABC_ERROR_CODE2, "REGRESS_TEST_ABC_ERROR_CODE2", "code2" }, { REGRESS_TEST_ABC_ERROR_CODE3, "REGRESS_TEST_ABC_ERROR_CODE3", "code3" }, { 0, NULL, NULL } }; etype = g_enum_register_static (g_intern_static_string ("RegressTestABCError"), values); } return etype; } GQuark regress_test_abc_error_quark (void) { return g_quark_from_static_string ("regress-test-abc-error"); } GType regress_test_unconventional_error_get_type (void) { static GType etype = 0; if (G_UNLIKELY (etype == 0)) { static const GEnumValue values[] = { { REGRESS_TEST_OTHER_ERROR_CODE1, "REGRESS_TEST_OTHER_ERROR_CODE1", "code1" }, { REGRESS_TEST_OTHER_ERROR_CODE2, "REGRESS_TEST_OTHER_ERROR_CODE2", "code2" }, { REGRESS_TEST_OTHER_ERROR_CODE3, "REGRESS_TEST_OTHER_ERROR_CODE3", "code3" }, { 0, NULL, NULL } }; etype = g_enum_register_static (g_intern_static_string ("RegressTestOtherError"), values); } return etype; } GQuark regress_test_unconventional_error_quark (void) { return g_quark_from_static_string ("regress-test-other-error"); } GQuark regress_test_def_error_quark (void) { return g_quark_from_static_string ("regress-test-def-error"); } GQuark regress_atest_error_quark (void) { return g_quark_from_static_string ("regress-atest-error"); } /* structures */ /** * regress_test_struct_a_clone: * @a: the structure * @a_out: (out caller-allocates): the cloned structure * * Make a copy of a RegressTestStructA */ void regress_test_struct_a_clone (RegressTestStructA *a, RegressTestStructA *a_out) { *a_out = *a; } /** * regress_test_struct_a_parse: * @a_out: (out caller-allocates): the structure that is to be filled * @string: ignored */ void regress_test_struct_a_parse (RegressTestStructA *a_out, const gchar *string G_GNUC_UNUSED) { a_out->some_int = 23; } /** * regress_test_array_struct_out: * @arr: (out) (array length=len) (transfer full): * @len: (out) * * This is similar to gdk_keymap_get_entries_for_keyval(). */ void regress_test_array_struct_out (RegressTestStructA **arr, int *len) { *arr = g_new0 (RegressTestStructA, 3); (*arr)[0].some_int = 22; (*arr)[1].some_int = 33; (*arr)[2].some_int = 44; *len = 3; } /** * regress_test_struct_b_clone: * @b: the structure * @b_out: (out): the cloned structure * * Make a copy of a RegressTestStructB */ void regress_test_struct_b_clone (RegressTestStructB *b, RegressTestStructB *b_out) { *b_out = *b; } /* plain-old-data boxed types */ RegressTestSimpleBoxedA * regress_test_simple_boxed_a_copy (RegressTestSimpleBoxedA *a) { RegressTestSimpleBoxedA *new_a = g_slice_new (RegressTestSimpleBoxedA); *new_a = *a; return new_a; } static void regress_test_simple_boxed_a_free (RegressTestSimpleBoxedA *a) { g_slice_free (RegressTestSimpleBoxedA, a); } GType regress_test_simple_boxed_a_get_gtype (void) { static GType our_type = 0; if (our_type == 0) our_type = g_boxed_type_register_static (g_intern_static_string ("RegressTestSimpleBoxedA"), (GBoxedCopyFunc) regress_test_simple_boxed_a_copy, (GBoxedFreeFunc) regress_test_simple_boxed_a_free); return our_type; } RegressTestSimpleBoxedB * regress_test_simple_boxed_b_copy (RegressTestSimpleBoxedB *b) { RegressTestSimpleBoxedB *new_b = g_slice_new (RegressTestSimpleBoxedB); *new_b = *b; return new_b; } gboolean regress_test_simple_boxed_a_equals (RegressTestSimpleBoxedA *a, RegressTestSimpleBoxedA *other_a) { return (a->some_int == other_a->some_int && a->some_int8 == other_a->some_int8 && a->some_double == other_a->some_double); } const RegressTestSimpleBoxedA * regress_test_simple_boxed_a_const_return (void) { static RegressTestSimpleBoxedA simple_a = { 5, 6, 7.0, REGRESS_TEST_VALUE1 }; return &simple_a; } static void regress_test_simple_boxed_b_free (RegressTestSimpleBoxedB *a) { g_slice_free (RegressTestSimpleBoxedB, a); } GType regress_test_simple_boxed_b_get_type (void) { static GType our_type = 0; if (our_type == 0) our_type = g_boxed_type_register_static (g_intern_static_string ("RegressTestSimpleBoxedB"), (GBoxedCopyFunc) regress_test_simple_boxed_b_copy, (GBoxedFreeFunc) regress_test_simple_boxed_b_free); return our_type; } /* opaque boxed */ struct _RegressTestBoxedPrivate { guint magic; }; /** * regress_test_boxed_new: * * Returns: (transfer full): */ RegressTestBoxed * regress_test_boxed_new (void) { RegressTestBoxed *boxed = g_slice_new0 (RegressTestBoxed); boxed->priv = g_slice_new0 (RegressTestBoxedPrivate); boxed->priv->magic = 0xdeadbeef; return boxed; } /** * regress_test_boxed_new_alternative_constructor1: * * Returns: (transfer full): */ RegressTestBoxed * regress_test_boxed_new_alternative_constructor1 (int i) { RegressTestBoxed *boxed = g_slice_new0 (RegressTestBoxed); boxed->priv = g_slice_new0 (RegressTestBoxedPrivate); boxed->priv->magic = 0xdeadbeef; boxed->some_int8 = i; return boxed; } /** * regress_test_boxed_new_alternative_constructor2: * * Returns: (transfer full): */ RegressTestBoxed * regress_test_boxed_new_alternative_constructor2 (int i, int j) { RegressTestBoxed *boxed = g_slice_new0 (RegressTestBoxed); boxed->priv = g_slice_new0 (RegressTestBoxedPrivate); boxed->priv->magic = 0xdeadbeef; boxed->some_int8 = i + j; return boxed; } /** * regress_test_boxed_new_alternative_constructor3: * * Returns: (transfer full): */ RegressTestBoxed * regress_test_boxed_new_alternative_constructor3 (char *s) { RegressTestBoxed *boxed = g_slice_new0 (RegressTestBoxed); boxed->priv = g_slice_new0 (RegressTestBoxedPrivate); boxed->priv->magic = 0xdeadbeef; boxed->some_int8 = atoi (s); return boxed; } /** * regress_test_boxed_copy: * * Returns: (transfer full): */ RegressTestBoxed * regress_test_boxed_copy (RegressTestBoxed *boxed) { RegressTestBoxed *new_boxed = regress_test_boxed_new (); RegressTestBoxedPrivate *save; save = new_boxed->priv; *new_boxed = *boxed; new_boxed->priv = save; return new_boxed; } gboolean regress_test_boxed_equals (RegressTestBoxed *boxed, RegressTestBoxed *other) { return (other->some_int8 == boxed->some_int8 && regress_test_simple_boxed_a_equals (&other->nested_a, &boxed->nested_a)); } void regress_test_boxeds_not_a_method (RegressTestBoxed *boxed G_GNUC_UNUSED) { } void regress_test_boxeds_not_a_static (void) { } static void regress_test_boxed_free (RegressTestBoxed *boxed) { g_assert (boxed->priv->magic == 0xdeadbeef); g_slice_free (RegressTestBoxedPrivate, boxed->priv); g_slice_free (RegressTestBoxed, boxed); } GType regress_test_boxed_get_type (void) { static GType our_type = 0; if (our_type == 0) our_type = g_boxed_type_register_static (g_intern_static_string ("RegressTestBoxed"), (GBoxedCopyFunc) regress_test_boxed_copy, (GBoxedFreeFunc) regress_test_boxed_free); return our_type; } RegressTestBoxedB * regress_test_boxed_b_new (gint8 some_int8, glong some_long) { RegressTestBoxedB *boxed; boxed = g_slice_new (RegressTestBoxedB); boxed->some_int8 = some_int8; boxed->some_long = some_long; return boxed; } RegressTestBoxedB * regress_test_boxed_b_copy (RegressTestBoxedB *boxed) { return regress_test_boxed_b_new (boxed->some_int8, boxed->some_long); } static void regress_test_boxed_b_free (RegressTestBoxedB *boxed) { g_slice_free (RegressTestBoxedB, boxed); } G_DEFINE_BOXED_TYPE (RegressTestBoxedB, regress_test_boxed_b, regress_test_boxed_b_copy, regress_test_boxed_b_free); RegressTestBoxedC * regress_test_boxed_c_new (void) { RegressTestBoxedC *boxed; boxed = g_slice_new (RegressTestBoxedC); boxed->refcount = 1; boxed->another_thing = 42; /* what else */ return boxed; } gboolean regress_test_boxed_c_name_conflict (RegressTestBoxedC *boxed) { return boxed->name_conflict; } static RegressTestBoxedC * regress_test_boxed_c_ref (RegressTestBoxedC *boxed) { g_atomic_int_inc (&boxed->refcount); return boxed; } static void regress_test_boxed_c_unref (RegressTestBoxedC *boxed) { if (g_atomic_int_dec_and_test (&boxed->refcount)) { g_slice_free (RegressTestBoxedC, boxed); } } G_DEFINE_BOXED_TYPE (RegressTestBoxedC, regress_test_boxed_c, regress_test_boxed_c_ref, regress_test_boxed_c_unref); struct _RegressTestBoxedD { char *a_string; gint a_int; }; RegressTestBoxedD * regress_test_boxed_d_new (const char *a_string, int a_int) { RegressTestBoxedD *boxed; boxed = g_slice_new (RegressTestBoxedD); boxed->a_string = g_strdup (a_string); boxed->a_int = a_int; return boxed; } RegressTestBoxedD * regress_test_boxed_d_copy (RegressTestBoxedD *boxed) { RegressTestBoxedD *ret; ret = g_slice_new (RegressTestBoxedD); ret->a_string = g_strdup (boxed->a_string); ret->a_int = boxed->a_int; return ret; } void regress_test_boxed_d_free (RegressTestBoxedD *boxed) { g_free (boxed->a_string); g_slice_free (RegressTestBoxedD, boxed); } int regress_test_boxed_d_get_magic (RegressTestBoxedD *boxed) { return strlen (boxed->a_string) + boxed->a_int; } G_DEFINE_BOXED_TYPE (RegressTestBoxedD, regress_test_boxed_d, regress_test_boxed_d_copy, regress_test_boxed_d_free); G_DEFINE_TYPE (RegressTestObj, regress_test_obj, G_TYPE_OBJECT); enum { PROP_TEST_OBJ_BARE = 1, PROP_TEST_OBJ_BOXED, PROP_TEST_OBJ_HASH_TABLE, PROP_TEST_OBJ_LIST, PROP_TEST_OBJ_PPTRARRAY, PROP_TEST_OBJ_HASH_TABLE_OLD, PROP_TEST_OBJ_LIST_OLD, PROP_TEST_OBJ_INT, PROP_TEST_OBJ_FLOAT, PROP_TEST_OBJ_DOUBLE, PROP_TEST_OBJ_STRING, PROP_TEST_OBJ_GTYPE, PROP_TEST_OBJ_NAME_CONFLICT, PROP_TEST_OBJ_BYTE_ARRAY, PROP_TEST_OBJ_WRITE_ONLY, }; static void regress_test_obj_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { RegressTestObj *self = REGRESS_TEST_OBJECT (object); GList *list; switch (property_id) { case PROP_TEST_OBJ_BARE: regress_test_obj_set_bare (self, g_value_get_object (value)); break; case PROP_TEST_OBJ_BOXED: if (self->boxed) regress_test_boxed_free (self->boxed); self->boxed = g_value_dup_boxed (value); break; case PROP_TEST_OBJ_HASH_TABLE: case PROP_TEST_OBJ_HASH_TABLE_OLD: if (self->hash_table) g_hash_table_unref (self->hash_table); self->hash_table = g_hash_table_ref (g_value_get_boxed (value)); break; case PROP_TEST_OBJ_LIST: case PROP_TEST_OBJ_LIST_OLD: g_list_free_full (self->list, g_free); list = g_value_get_pointer (value); self->list = g_list_copy_deep (list, (GCopyFunc) (void *) g_strdup, NULL); break; case PROP_TEST_OBJ_INT: self->some_int8 = g_value_get_int (value); break; case PROP_TEST_OBJ_FLOAT: self->some_float = g_value_get_float (value); break; case PROP_TEST_OBJ_DOUBLE: self->some_double = g_value_get_double (value); break; case PROP_TEST_OBJ_STRING: g_clear_pointer (&self->string, g_free); self->string = g_value_dup_string (value); break; case PROP_TEST_OBJ_GTYPE: self->gtype = g_value_get_gtype (value); break; case PROP_TEST_OBJ_NAME_CONFLICT: self->name_conflict = g_value_get_int (value); break; case PROP_TEST_OBJ_BYTE_ARRAY: self->byte_array = g_value_get_boxed (value); break; case PROP_TEST_OBJ_WRITE_ONLY: if (g_value_get_boolean (value)) self->some_int8 = 0; break; default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void regress_test_obj_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { RegressTestObj *self = REGRESS_TEST_OBJECT (object); switch (property_id) { case PROP_TEST_OBJ_BARE: g_value_set_object (value, self->bare); break; case PROP_TEST_OBJ_BOXED: g_value_set_boxed (value, self->boxed); break; case PROP_TEST_OBJ_HASH_TABLE: case PROP_TEST_OBJ_HASH_TABLE_OLD: if (self->hash_table != NULL) g_hash_table_ref (self->hash_table); g_value_set_boxed (value, self->hash_table); break; case PROP_TEST_OBJ_LIST: case PROP_TEST_OBJ_LIST_OLD: g_value_set_pointer (value, self->list); break; case PROP_TEST_OBJ_INT: g_value_set_int (value, self->some_int8); break; case PROP_TEST_OBJ_FLOAT: g_value_set_float (value, self->some_float); break; case PROP_TEST_OBJ_DOUBLE: g_value_set_double (value, self->some_double); break; case PROP_TEST_OBJ_STRING: g_value_set_string (value, self->string); break; case PROP_TEST_OBJ_GTYPE: g_value_set_gtype (value, self->gtype); break; case PROP_TEST_OBJ_NAME_CONFLICT: g_value_set_int (value, self->name_conflict); break; case PROP_TEST_OBJ_BYTE_ARRAY: g_value_set_boxed (value, self->byte_array); break; default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void regress_test_obj_dispose (GObject *gobject) { RegressTestObj *self = REGRESS_TEST_OBJECT (gobject); if (self->bare) { g_object_unref (self->bare); self->bare = NULL; } if (self->boxed) { regress_test_boxed_free (self->boxed); self->boxed = NULL; } if (self->list) { g_list_free_full (self->list, g_free); self->list = NULL; } g_clear_pointer (&self->hash_table, g_hash_table_unref); g_clear_pointer (&self->string, g_free); /* Chain up to the parent class */ G_OBJECT_CLASS (regress_test_obj_parent_class)->dispose (gobject); } static int regress_test_obj_default_matrix (RegressTestObj *obj G_GNUC_UNUSED, const char *somestr G_GNUC_UNUSED) { return 42; } enum { REGRESS_TEST_OBJ_SIGNAL_SIG_NEW_WITH_ARRAY_PROP, REGRESS_TEST_OBJ_SIGNAL_SIG_NEW_WITH_ARRAY_LEN_PROP, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_HASH_PROP, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_STRV, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_STRV_FULL, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_OBJ, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_OBJ_FULL, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_FOREIGN_STRUCT, REGRESS_TEST_OBJ_SIGNAL_FIRST, REGRESS_TEST_OBJ_SIGNAL_CLEANUP, REGRESS_TEST_OBJ_SIGNAL_ALL, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_INT64_PROP, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_UINT64_PROP, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_INTARRAY_RET, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_INOUT_INT, REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_GERROR, N_REGRESS_TEST_OBJ_SIGNALS }; static guint regress_test_obj_signals[N_REGRESS_TEST_OBJ_SIGNALS] = { 0 }; static void regress_test_obj_class_init (RegressTestObjClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; GType param_types[1]; klass->test_signal = g_signal_newv ("test", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL /* closure */, NULL /* accumulator */, NULL /* accumulator data */, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE /* return_type */, 0 /* n_params */, NULL /* param_types */); param_types[0] = regress_test_simple_boxed_a_get_gtype () | G_SIGNAL_TYPE_STATIC_SCOPE; klass->test_signal_with_static_scope_arg = g_signal_newv ("test-with-static-scope-arg", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL /* closure */, NULL /* accumulator */, NULL /* accumulator data */, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE /* return_type */, 1 /* n_params */, param_types); /** * RegressTestObj::sig-with-array-prop: * @self: an object * @arr: (type GArray) (element-type uint): numbers * * This test signal is like TelepathyGlib's * TpChannel:: group-members-changed-detailed: */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_NEW_WITH_ARRAY_PROP] = g_signal_new ("sig-with-array-prop", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_ARRAY); /** * RegressTestObj::sig-with-array-len-prop: * @self: an object * @arr: (array length=len) (element-type uint) (allow-none): numbers, or %NULL * @len: length of @arr, or 0 * * This test signal similar to GSettings::change-event. * You can use this with regress_test_obj_emit_sig_with_array_len_prop(), or * raise from the introspection client language. */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_NEW_WITH_ARRAY_LEN_PROP] = g_signal_new ("sig-with-array-len-prop", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_INT); /** * RegressTestObj::sig-with-hash-prop: * @self: an object * @hash: (element-type utf8 GObject.Value): * * This test signal is like TelepathyGlib's * TpAccount::status-changed */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_HASH_PROP] = g_signal_new ("sig-with-hash-prop", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_HASH_TABLE); /** * RegressTestObj::sig-with-strv: * @self: an object * @strs: strings * * Test GStrv as a param. */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_STRV] = g_signal_new ("sig-with-strv", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_STRV); /** * RegressTestObj::sig-with-strv-full: * @self: an object * @strs: (transfer full): strings * * Test GStrv as a param. */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_STRV_FULL] = g_signal_new ("sig-with-strv-full", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_STRV); /** * RegressTestObj::sig-with-obj: * @self: an object * @obj: (transfer none): A newly created RegressTestObj * * Test transfer none GObject as a param (tests refcounting). * Use with regress_test_obj_emit_sig_with_obj */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_OBJ] = g_signal_new ("sig-with-obj", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); /** * RegressTestObj::sig-with-obj-full: * @self: an object * @obj: (transfer full): A newly created RegressTestObj * * Test transfer full GObject as a param (tests refcounting). * Use with regress_test_obj_emit_sig_with_obj_full */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_OBJ_FULL] = g_signal_new ("sig-with-obj-full", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); #ifndef GI_TEST_DISABLE_CAIRO /** * RegressTestObj::sig-with-foreign-struct: * @self: an object * @cr: (transfer none): A cairo context. */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_FOREIGN_STRUCT] = g_signal_new ("sig-with-foreign-struct", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, CAIRO_GOBJECT_TYPE_CONTEXT); #endif /* GI_TEST_DISABLE_CAIRO */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_FIRST] = g_signal_new ("first", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_CLEANUP] = g_signal_new ("cleanup", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_CLEANUP, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_ALL] = g_signal_new ("all", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_ACTION | G_SIGNAL_NO_HOOKS, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * RegressTestObj::sig-with-int64-prop: * @self: an object * @i: an integer * * You can use this with regress_test_obj_emit_sig_with_int64, or raise from * the introspection client langage. */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_INT64_PROP] = g_signal_new ("sig-with-int64-prop", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_INT64, 1, G_TYPE_INT64); /** * RegressTestObj::sig-with-uint64-prop: * @self: an object * @i: an integer * * You can use this with regress_test_obj_emit_sig_with_uint64, or raise from * the introspection client langage. */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_UINT64_PROP] = g_signal_new ("sig-with-uint64-prop", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_UINT64, 1, G_TYPE_UINT64); /** * RegressTestObj::sig-with-intarray-ret: * @self: an object * @i: an integer * * Returns: (array zero-terminated=1) (element-type gint) (transfer full): */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_INTARRAY_RET] = g_signal_new ("sig-with-intarray-ret", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_ARRAY, 1, G_TYPE_INT); /** * RegressTestObj::sig-with-inout-int * @self: The object that emitted the signal * @position: (inout) (type int): The position, in characters, at which to * insert the new text. This is an in-out paramter. After the signal * emission is finished, it should point after the newly inserted text. * * This signal is modeled after GtkEditable::insert-text. */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_INOUT_INT] = g_signal_new ("sig-with-inout-int", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * RegressTestObj::sig-with-gerror: * @self: The object that emitted the signal * @error: (nullable) (type GLib.Error): A #GError if something went wrong * internally in @self. You must not free this #GError. * * This signal is modeled after #GstDiscoverer::discovered, and is added to * exercise the path of a #GError being marshalled as a boxed type instead of * an exception in the introspected language. * * Use via regress_test_obj_emit_sig_with_error() and * regress_test_obj_emit_sig_with_null_error(), or emit via the introspected * language. */ regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_GERROR] = g_signal_new ("sig-with-gerror", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_ERROR | G_SIGNAL_TYPE_STATIC_SCOPE); gobject_class->set_property = regress_test_obj_set_property; gobject_class->get_property = regress_test_obj_get_property; gobject_class->dispose = regress_test_obj_dispose; pspec = g_param_spec_object ("bare", "Bare property", "A contained object", G_TYPE_OBJECT, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_BARE, pspec); pspec = g_param_spec_boxed ("boxed", "Boxed property", "A contained boxed struct", REGRESS_TEST_TYPE_BOXED, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_BOXED, pspec); /** * RegressTestObj:hash-table: (type GLib.HashTable(utf8,gint8)) (transfer container) */ pspec = g_param_spec_boxed ("hash-table", "GHashTable property", "A contained GHashTable", G_TYPE_HASH_TABLE, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_HASH_TABLE, pspec); /** * RegressTestObj:list: (type GLib.List(utf8)) (transfer none) (default-value NULL) */ pspec = g_param_spec_pointer ("list", "GList property", "A contained GList", G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_LIST, pspec); /** * RegressTestObj:pptrarray: (type GLib.PtrArray(utf8)) (transfer none) */ pspec = g_param_spec_pointer ("pptrarray", "PtrArray property as a pointer", "Test annotating with GLib.PtrArray", G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_PPTRARRAY, pspec); /** * RegressTestObj:hash-table-old: (type GLib.HashTable) (transfer container) */ pspec = g_param_spec_boxed ("hash-table-old", "GHashTable property with <>", "A contained GHashTable with <>", G_TYPE_HASH_TABLE, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_HASH_TABLE_OLD, pspec); /** * RegressTestObj:list-old: (type GLib.List) (transfer none) */ pspec = g_param_spec_pointer ("list-old", "GList property with ()", "A contained GList with <>", G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_LIST_OLD, pspec); /** * RegressTestObj:int: */ pspec = g_param_spec_int ("int", "int property", "A contained int", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_INT, pspec); /** * RegressTestObj:float: */ pspec = g_param_spec_float ("float", "float property", "A contained float", G_MINFLOAT, G_MAXFLOAT, 1.0f, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_FLOAT, pspec); /** * RegressTestObj:double: */ pspec = g_param_spec_double ("double", "double property", "A contained double", G_MINDOUBLE, G_MAXDOUBLE, 1.0, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_DOUBLE, pspec); /** * RegressTestObj:string: (setter set_string) (getter get_string) */ pspec = g_param_spec_string ("string", "string property", "A contained string", NULL, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_STRING, pspec); /** * RegressTestObj:gtype: (default-value G_TYPE_INVALID) */ pspec = g_param_spec_gtype ("gtype", "GType property", "A GType property", G_TYPE_NONE, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_GTYPE, pspec); /** * RegressTestObj:name-conflict: */ pspec = g_param_spec_int ("name-conflict", "name-conflict property", "A property name that conflicts with a method", G_MININT, G_MAXINT, 42, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_NAME_CONFLICT, pspec); /** * RegressTestObj:byte-array: */ pspec = g_param_spec_boxed ("byte-array", "GByteArray property", "A contained byte array without any element-type annotations", G_TYPE_BYTE_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_BYTE_ARRAY, pspec); /** * RegressTestObj:write-only: */ pspec = g_param_spec_boolean ("write-only", "Write-only property", "A write-only bool property that resets the value of TestObj:int to 0 when true", FALSE, G_PARAM_WRITABLE); g_object_class_install_property (gobject_class, PROP_TEST_OBJ_WRITE_ONLY, pspec); klass->matrix = regress_test_obj_default_matrix; } static void regress_test_obj_init (RegressTestObj *obj) { obj->bare = NULL; obj->boxed = NULL; obj->hash_table = NULL; obj->gtype = G_TYPE_INVALID; } /** * regress_test_obj_new: (constructor) * @obj: A #RegressTestObj */ RegressTestObj * regress_test_obj_new (RegressTestObj *obj G_GNUC_UNUSED) { return g_object_new (REGRESS_TEST_TYPE_OBJ, NULL); } /** * regress_constructor: (constructor) * */ RegressTestObj * regress_constructor (void) { return g_object_new (REGRESS_TEST_TYPE_OBJ, NULL); } /** * regress_test_obj_new_from_file: */ RegressTestObj * regress_test_obj_new_from_file (const char *x G_GNUC_UNUSED, GError **error G_GNUC_UNUSED) { return g_object_new (REGRESS_TEST_TYPE_OBJ, NULL); } /** * regress_test_obj_set_bare: * @bare: (allow-none): */ void regress_test_obj_set_bare (RegressTestObj *obj, GObject *bare) { if (obj->bare) g_object_unref (obj->bare); obj->bare = bare; if (obj->bare) g_object_ref (obj->bare); } /** * regress_test_obj_set_string: (set-property string) * @obj: * @str: */ void regress_test_obj_set_string (RegressTestObj *obj, const char *str) { if (g_strcmp0 (str, obj->string) == 0) return; g_free (obj->string); obj->string = g_strdup (str); g_object_notify (G_OBJECT (obj), "string"); } /** * regress_test_obj_get_string: (get-property string) * @obj: * * Returns: (transfer none): */ const char * regress_test_obj_get_string (RegressTestObj *obj) { return obj->string; } void regress_test_obj_emit_sig_with_obj (RegressTestObj *obj) { RegressTestObj *obj_param = regress_constructor (); g_object_set (obj_param, "int", 3, NULL); g_signal_emit_by_name (obj, "sig-with-obj", obj_param); g_object_unref (obj_param); } void regress_test_obj_emit_sig_with_obj_full (RegressTestObj *obj) { RegressTestObj *obj_param = regress_constructor (); g_object_set (obj_param, "int", 5, NULL); g_signal_emit (obj, regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_OBJ_FULL], 0, g_steal_pointer (&obj_param)); } #if GLIB_CHECK_VERSION(2, 68, 0) void regress_test_obj_emit_sig_with_gstrv_full (RegressTestObj *obj) { GStrvBuilder *builder = g_strv_builder_new (); g_strv_builder_add_many (builder, "foo", "bar", "baz", NULL); g_signal_emit (obj, regress_test_obj_signals[REGRESS_TEST_OBJ_SIGNAL_SIG_WITH_STRV_FULL], 0, g_strv_builder_end (builder)); g_strv_builder_unref (builder); } #endif #ifndef GI_TEST_DISABLE_CAIRO void regress_test_obj_emit_sig_with_foreign_struct (RegressTestObj *obj) { cairo_t *cr = regress_test_cairo_context_full_return (); g_signal_emit_by_name (obj, "sig-with-foreign-struct", cr); cairo_destroy (cr); } #endif /* GI_TEST_DISABLE_CAIRO */ void regress_test_obj_emit_sig_with_int64 (RegressTestObj *obj) { gint64 ret = 0; RegressTestObj *obj_param = regress_constructor (); g_signal_emit_by_name (obj, "sig-with-int64-prop", G_MAXINT64, &ret); g_object_unref (obj_param); g_assert (ret == G_MAXINT64); } void regress_test_obj_emit_sig_with_uint64 (RegressTestObj *obj) { guint64 ret = 0; RegressTestObj *obj_param = regress_constructor (); g_signal_emit_by_name (obj, "sig-with-uint64-prop", G_MAXUINT64, &ret); g_object_unref (obj_param); g_assert (ret == G_MAXUINT64); } /** * regress_test_obj_emit_sig_with_array_len_prop: */ void regress_test_obj_emit_sig_with_array_len_prop (RegressTestObj *obj) { int arr[] = { 0, 1, 2, 3, 4 }; g_signal_emit_by_name (obj, "sig-with-array-len-prop", &arr, 5); } /** * regress_test_obj_emit_sig_with_inout_int: * @obj: The object to emit the signal. * * The signal handler must increment the inout parameter by 1. */ void regress_test_obj_emit_sig_with_inout_int (RegressTestObj *obj) { int inout = 42; g_signal_emit_by_name (obj, "sig-with-inout-int", &inout); g_assert_cmpint (inout, ==, 43); } /** * regress_test_obj_emit_sig_with_error: * @self: The object to emit the signal. */ void regress_test_obj_emit_sig_with_error (RegressTestObj *self) { GError *err = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, "Something failed"); g_signal_emit_by_name (self, "sig-with-gerror", err); g_error_free (err); } /** * regress_test_obj_emit_sig_with_null_error: * @self: The object to emit the signal. */ void regress_test_obj_emit_sig_with_null_error (RegressTestObj *self) { g_signal_emit_by_name (self, "sig-with-gerror", NULL); } int regress_test_obj_instance_method (RegressTestObj *obj G_GNUC_UNUSED) { return -1; } /** * regress_test_obj_instance_method_full: * @obj: (transfer full): * */ void regress_test_obj_instance_method_full (RegressTestObj *obj) { g_object_unref (obj); } double regress_test_obj_static_method (int x) { return x; } /** * regress_forced_method: (method) * @obj: A #RegressTestObj * */ void regress_forced_method (RegressTestObj *obj G_GNUC_UNUSED) { } /** * regress_test_obj_torture_signature_0: * @obj: A #RegressTestObj * @x: * @y: (out): * @z: (out): * @foo: * @q: (out): * @m: * */ void regress_test_obj_torture_signature_0 (RegressTestObj *obj G_GNUC_UNUSED, int x, double *y, int *z, const char *foo, int *q, guint m) { *y = x; *z = x * 2; *q = g_utf8_strlen (foo, -1) + m; } /** * regress_test_obj_torture_signature_1: * @obj: A #RegressTestObj * @x: * @y: (out): * @z: (out): * @foo: * @q: (out): * @m: * @error: A #GError * * This function throws an error if m is odd. */ gboolean regress_test_obj_torture_signature_1 (RegressTestObj *obj G_GNUC_UNUSED, int x, double *y, int *z, const char *foo, int *q, guint m, GError **error) { *y = x; *z = x * 2; *q = g_utf8_strlen (foo, -1) + m; if (m % 2 == 0) return TRUE; g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "m is odd"); return FALSE; } /** * regress_test_obj_skip_return_val: * @obj: a #RegressTestObj * @a: Parameter. * @out_b: (out): A return value. * @c: Other parameter. * @inout_d: (inout): Will be incremented. * @out_sum: (out): Return value. * @num1: Number. * @num2: Number. * @error: Return location for error. * * Check that the return value is skipped * * Returns: (skip): %TRUE if the call succeeds, %FALSE if @error is set. */ gboolean regress_test_obj_skip_return_val (RegressTestObj *obj G_GNUC_UNUSED, gint a, gint *out_b, gdouble c G_GNUC_UNUSED, gint *inout_d, gint *out_sum, gint num1, gint num2, GError **error G_GNUC_UNUSED) { if (out_b != NULL) *out_b = a + 1; if (inout_d != NULL) *inout_d = *inout_d + 1; if (out_sum != NULL) *out_sum = num1 + 10 * num2; return TRUE; } /** * regress_test_obj_skip_return_val_no_out: * @obj: a #RegressTestObj * @a: Parameter. * @error: Return location for error. * * Check that the return value is skipped. Succeed if a is nonzero, otherwise * raise an error. * * Returns: (skip): %TRUE if the call succeeds, %FALSE if @error is set. */ gboolean regress_test_obj_skip_return_val_no_out (RegressTestObj *obj G_GNUC_UNUSED, gint a, GError **error) { if (a == 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "a is zero"); return FALSE; } else { return TRUE; } } /** * regress_test_obj_skip_param: * @obj: A #RegressTestObj. * @a: Parameter. * @out_b: (out): Return value. * @c: (skip): Other parameter. * @inout_d: (inout): Will be incremented. * @out_sum: (out): Return value. * @num1: Number. * @num2: Number. * @error: Return location for error. * * Check that a parameter is skipped * * Returns: %TRUE if the call succeeds, %FALSE if @error is set. */ gboolean regress_test_obj_skip_param (RegressTestObj *obj G_GNUC_UNUSED, gint a, gint *out_b, gdouble c G_GNUC_UNUSED, gint *inout_d, gint *out_sum, gint num1, gint num2, GError **error G_GNUC_UNUSED) { if (out_b != NULL) *out_b = a + 1; if (inout_d != NULL) *inout_d = *inout_d + 1; if (out_sum != NULL) *out_sum = num1 + 10 * num2; return TRUE; } /** * regress_test_obj_skip_out_param: * @obj: A #RegressTestObj. * @a: Parameter. * @out_b: (out) (skip): Return value. * @c: Other parameter. * @inout_d: (inout): Will be incremented. * @out_sum: (out): Return value. * @num1: Number. * @num2: Number. * @error: Return location for error. * * Check that the out value is skipped * * Returns: %TRUE if the call succeeds, %FALSE if @error is set. */ gboolean regress_test_obj_skip_out_param (RegressTestObj *obj G_GNUC_UNUSED, gint a, gint *out_b, gdouble c G_GNUC_UNUSED, gint *inout_d, gint *out_sum, gint num1, gint num2, GError **error G_GNUC_UNUSED) { if (out_b != NULL) *out_b = a + 1; if (inout_d != NULL) *inout_d = *inout_d + 1; if (out_sum != NULL) *out_sum = num1 + 10 * num2; return TRUE; } /** * regress_test_obj_skip_inout_param: * @obj: A #RegressTestObj. * @a: Parameter. * @out_b: (out): Return value. * @c: Other parameter. * @inout_d: (inout) (skip): Will be incremented. * @out_sum: (out): Return value. * @num1: Number. * @num2: Number. * @error: Return location for error. * * Check that the out value is skipped * * Returns: %TRUE if the call succeeds, %FALSE if @error is set. */ gboolean regress_test_obj_skip_inout_param (RegressTestObj *obj G_GNUC_UNUSED, gint a, gint *out_b, gdouble c G_GNUC_UNUSED, gint *inout_d, gint *out_sum, gint num1, gint num2, GError **error G_GNUC_UNUSED) { if (out_b != NULL) *out_b = a + 1; if (inout_d != NULL) *inout_d = *inout_d + 1; if (out_sum != NULL) *out_sum = num1 + 10 * num2; return TRUE; } /** * regress_test_obj_do_matrix: (virtual matrix) * @obj: A #RegressTestObj * @somestr: Meaningless string * * This method is virtual. Notably its name differs from the virtual * slot name, which makes it useful for testing bindings handle this * case. */ int regress_test_obj_do_matrix (RegressTestObj *obj, const char *somestr) { return REGRESS_TEST_OBJ_GET_CLASS (obj)->matrix (obj, somestr); } /** * regress_func_obj_null_in: * @obj: (allow-none): A #RegressTestObj */ void regress_func_obj_null_in (RegressTestObj *obj G_GNUC_UNUSED) { } /** * regress_test_obj_null_out: * @obj: (allow-none) (out): A #RegressTestObj */ void regress_test_obj_null_out (RegressTestObj **obj) { if (obj) *obj = NULL; } /** * regress_func_obj_nullable_in: * @obj: (nullable): A #RegressTestObj */ void regress_func_obj_nullable_in (RegressTestObj *obj G_GNUC_UNUSED) { } /** * regress_test_obj_not_nullable_typed_gpointer_in: * @obj: A #RegressTestObj * @input: (type GObject): some #GObject */ void regress_test_obj_not_nullable_typed_gpointer_in (RegressTestObj *obj G_GNUC_UNUSED, gpointer input G_GNUC_UNUSED) { } /** * regress_test_obj_not_nullable_element_typed_gpointer_in: * @obj: A #RegressTestObj * @input: (element-type guint8) (array length=count): some uint8 array * @count: length of @input */ void regress_test_obj_not_nullable_element_typed_gpointer_in (RegressTestObj *obj G_GNUC_UNUSED, gpointer input G_GNUC_UNUSED, guint count G_GNUC_UNUSED) { } /** * regress_test_obj_name_conflict: * @obj: A #RegressTestObj */ void regress_test_obj_name_conflict (RegressTestObj *obj G_GNUC_UNUSED) { } /** * regress_test_array_fixed_out_objects: * @objs: (out) (array fixed-size=2) (transfer full): An array of #RegressTestObj */ void regress_test_array_fixed_out_objects (RegressTestObj ***objs) { RegressTestObj **values = (RegressTestObj **) g_new (gpointer, 2); values[0] = regress_constructor (); values[1] = regress_constructor (); *objs = values; } typedef struct _CallbackInfo CallbackInfo; struct _CallbackInfo { RegressTestCallbackUserData callback; GDestroyNotify notify; gpointer user_data; }; static void regress_test_sub_obj_iface_init (RegressTestInterfaceIface *iface G_GNUC_UNUSED) { } enum { PROP_TEST_SUB_OBJ_NUMBER = 1, PROP_TEST_SUB_OBJ_BOOLEAN, }; G_DEFINE_TYPE_WITH_CODE (RegressTestSubObj, regress_test_sub_obj, REGRESS_TEST_TYPE_OBJ, G_IMPLEMENT_INTERFACE (REGRESS_TEST_TYPE_INTERFACE, regress_test_sub_obj_iface_init)); static void regress_test_sub_obj_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { RegressTestSubObj *self = REGRESS_TEST_SUB_OBJECT (object); switch (property_id) { case PROP_TEST_SUB_OBJ_NUMBER: self->number = g_value_get_int (value); break; case PROP_TEST_SUB_OBJ_BOOLEAN: self->boolean = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void regress_test_sub_obj_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { RegressTestSubObj *self = REGRESS_TEST_SUB_OBJECT (object); switch (property_id) { case PROP_TEST_SUB_OBJ_NUMBER: g_value_set_int (value, self->number); break; case PROP_TEST_SUB_OBJ_BOOLEAN: g_value_set_boolean (value, self->boolean); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void regress_test_sub_obj_class_init (RegressTestSubObjClass *klass) { const guint flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS; GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->get_property = regress_test_sub_obj_get_property; gobject_class->set_property = regress_test_sub_obj_set_property; g_object_class_install_property (gobject_class, PROP_TEST_SUB_OBJ_BOOLEAN, g_param_spec_boolean ("boolean", "Boolean", "Boolean", TRUE, flags)); g_object_class_override_property (gobject_class, PROP_TEST_SUB_OBJ_NUMBER, "number"); } static void regress_test_sub_obj_init (RegressTestSubObj *self G_GNUC_UNUSED) { } RegressTestObj * regress_test_sub_obj_new (void) { return g_object_new (REGRESS_TEST_TYPE_SUB_OBJ, NULL); } int regress_test_sub_obj_instance_method (RegressTestSubObj *self G_GNUC_UNUSED) { return 0; } void regress_test_sub_obj_unset_bare (RegressTestSubObj *obj) { regress_test_obj_set_bare (REGRESS_TEST_OBJECT (obj), NULL); } /* RegressTestFundamental */ /** * regress_test_fundamental_object_ref: * * Returns: (transfer full): A new #RegressTestFundamentalObject */ RegressTestFundamentalObject * regress_test_fundamental_object_ref (RegressTestFundamentalObject *fundamental_object) { g_return_val_if_fail (fundamental_object != NULL, NULL); g_atomic_int_inc (&fundamental_object->refcount); return fundamental_object; } static void regress_test_fundamental_object_free (RegressTestFundamentalObject *fundamental_object) { RegressTestFundamentalObjectClass *mo_class; regress_test_fundamental_object_ref (fundamental_object); mo_class = REGRESS_TEST_FUNDAMENTAL_OBJECT_GET_CLASS (fundamental_object); mo_class->finalize (fundamental_object); if (G_LIKELY (g_atomic_int_dec_and_test (&fundamental_object->refcount))) { g_type_free_instance ((GTypeInstance *) fundamental_object); } } void regress_test_fundamental_object_unref (RegressTestFundamentalObject *fundamental_object) { g_return_if_fail (fundamental_object != NULL); g_return_if_fail (fundamental_object->refcount > 0); if (G_UNLIKELY (g_atomic_int_dec_and_test (&fundamental_object->refcount))) { regress_test_fundamental_object_free (fundamental_object); } } static void regress_test_fundamental_object_replace (RegressTestFundamentalObject **olddata, RegressTestFundamentalObject *newdata) { RegressTestFundamentalObject *olddata_val; g_return_if_fail (olddata != NULL); olddata_val = g_atomic_pointer_get ((gpointer *) olddata); if (olddata_val == newdata) return; if (newdata) regress_test_fundamental_object_ref (newdata); while (!g_atomic_pointer_compare_and_exchange ((gpointer *) olddata, olddata_val, newdata)) { olddata_val = g_atomic_pointer_get ((gpointer *) olddata); } if (olddata_val) regress_test_fundamental_object_unref (olddata_val); } static void regress_test_value_fundamental_object_init (GValue *value) { value->data[0].v_pointer = NULL; } static void regress_test_value_fundamental_object_free (GValue *value) { if (value->data[0].v_pointer) { regress_test_fundamental_object_unref (REGRESS_TEST_FUNDAMENTAL_OBJECT_CAST (value->data[0].v_pointer)); } } static void regress_test_value_fundamental_object_copy (const GValue *src_value, GValue *dest_value) { if (src_value->data[0].v_pointer) { dest_value->data[0].v_pointer = regress_test_fundamental_object_ref (REGRESS_TEST_FUNDAMENTAL_OBJECT_CAST (src_value->data[0].v_pointer)); } else { dest_value->data[0].v_pointer = NULL; } } static gpointer regress_test_value_fundamental_object_peek_pointer (const GValue *value) { return value->data[0].v_pointer; } static gchar * regress_test_value_fundamental_object_collect (GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags G_GNUC_UNUSED) { g_assert (n_collect_values > 0); if (collect_values[0].v_pointer) { value->data[0].v_pointer = regress_test_fundamental_object_ref (collect_values[0].v_pointer); } else { value->data[0].v_pointer = NULL; } return NULL; } static gchar * regress_test_value_fundamental_object_lcopy (const GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags) { gpointer *fundamental_object_p; g_assert (n_collect_values > 0); fundamental_object_p = collect_values[0].v_pointer; if (!fundamental_object_p) { return g_strdup_printf ("value location for '%s' passed as NULL", G_VALUE_TYPE_NAME (value)); } if (!value->data[0].v_pointer) *fundamental_object_p = NULL; else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) *fundamental_object_p = value->data[0].v_pointer; else *fundamental_object_p = regress_test_fundamental_object_ref (value->data[0].v_pointer); return NULL; } static void regress_test_fundamental_object_finalize (RegressTestFundamentalObject *self G_GNUC_UNUSED) { } static RegressTestFundamentalObject * regress_test_fundamental_object_copy_default (const RegressTestFundamentalObject *self G_GNUC_UNUSED) { g_warning ("RegressTestFundamentalObject classes must implement RegressTestFundamentalObject::copy"); return NULL; } static void regress_test_fundamental_object_class_init (gpointer g_class, gpointer class_data G_GNUC_UNUSED) { RegressTestFundamentalObjectClass *mo_class = REGRESS_TEST_FUNDAMENTAL_OBJECT_CLASS (g_class); mo_class->copy = regress_test_fundamental_object_copy_default; mo_class->finalize = regress_test_fundamental_object_finalize; } static void regress_test_fundamental_object_init (GTypeInstance *instance, gpointer klass G_GNUC_UNUSED) { RegressTestFundamentalObject *fundamental_object = REGRESS_TEST_FUNDAMENTAL_OBJECT_CAST (instance); fundamental_object->refcount = 1; } /** * RegressTestFundamentalObject: (ref-func regress_test_fundamental_object_ref) (unref-func regress_test_fundamental_object_unref) (set-value-func regress_test_value_set_fundamental_object) (get-value-func regress_test_value_get_fundamental_object) */ GType regress_test_fundamental_object_get_type (void) { static GType _test_fundamental_object_type = 0; if (G_UNLIKELY (_test_fundamental_object_type == 0)) { static const GTypeValueTable value_table = { regress_test_value_fundamental_object_init, regress_test_value_fundamental_object_free, regress_test_value_fundamental_object_copy, regress_test_value_fundamental_object_peek_pointer, (char *) "p", regress_test_value_fundamental_object_collect, (char *) "p", regress_test_value_fundamental_object_lcopy }; static const GTypeInfo fundamental_object_info = { sizeof (RegressTestFundamentalObjectClass), NULL, NULL, regress_test_fundamental_object_class_init, NULL, NULL, sizeof (RegressTestFundamentalObject), 0, (GInstanceInitFunc) regress_test_fundamental_object_init, &value_table }; static const GTypeFundamentalInfo fundamental_object_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; _test_fundamental_object_type = g_type_fundamental_next (); g_type_register_fundamental (_test_fundamental_object_type, "RegressTestFundamentalObject", &fundamental_object_info, &fundamental_object_fundamental_info, G_TYPE_FLAG_ABSTRACT); } return _test_fundamental_object_type; } /** * regress_test_value_set_fundamental_object: (skip) * @value: * @fundamental_object: */ void regress_test_value_set_fundamental_object (GValue *value, RegressTestFundamentalObject *fundamental_object) { gpointer *pointer_p; g_return_if_fail (REGRESS_TEST_VALUE_HOLDS_FUNDAMENTAL_OBJECT (value)); g_return_if_fail (fundamental_object == NULL || REGRESS_TEST_IS_FUNDAMENTAL_OBJECT (fundamental_object)); pointer_p = &value->data[0].v_pointer; regress_test_fundamental_object_replace ((RegressTestFundamentalObject **) pointer_p, fundamental_object); } /** * regress_test_value_get_fundamental_object: (skip) * @value: */ RegressTestFundamentalObject * regress_test_value_get_fundamental_object (const GValue *value) { g_return_val_if_fail (REGRESS_TEST_VALUE_HOLDS_FUNDAMENTAL_OBJECT (value), NULL); return value->data[0].v_pointer; } static RegressTestFundamentalObjectClass *parent_class = NULL; G_DEFINE_TYPE (RegressTestFundamentalSubObject, regress_test_fundamental_sub_object, REGRESS_TEST_TYPE_FUNDAMENTAL_OBJECT); static RegressTestFundamentalSubObject * _regress_test_fundamental_sub_object_copy (RegressTestFundamentalSubObject *fundamental_sub_object) { RegressTestFundamentalSubObject *copy; copy = regress_test_fundamental_sub_object_new (NULL); copy->data = g_strdup (fundamental_sub_object->data); return copy; } static void regress_test_fundamental_sub_object_finalize (RegressTestFundamentalSubObject *fundamental_sub_object) { g_return_if_fail (fundamental_sub_object != NULL); g_free (fundamental_sub_object->data); regress_test_fundamental_object_finalize (REGRESS_TEST_FUNDAMENTAL_OBJECT (fundamental_sub_object)); } static void regress_test_fundamental_sub_object_class_init (RegressTestFundamentalSubObjectClass *klass) { parent_class = g_type_class_peek_parent (klass); klass->fundamental_object_class.copy = (RegressTestFundamentalObjectCopyFunction) _regress_test_fundamental_sub_object_copy; klass->fundamental_object_class.finalize = (RegressTestFundamentalObjectFinalizeFunction) regress_test_fundamental_sub_object_finalize; } static void regress_test_fundamental_sub_object_init (RegressTestFundamentalSubObject *self G_GNUC_UNUSED) { } /** * regress_test_fundamental_sub_object_new: */ RegressTestFundamentalSubObject * regress_test_fundamental_sub_object_new (const char *data) { RegressTestFundamentalSubObject *object; object = (RegressTestFundamentalSubObject *) g_type_create_instance (regress_test_fundamental_sub_object_get_type ()); object->data = g_strdup (data); return object; } /**/ #define regress_test_fundamental_hidden_sub_object_get_type \ _regress_test_fundamental_hidden_sub_object_get_type GType regress_test_fundamental_hidden_sub_object_get_type (void); typedef struct _RegressTestFundamentalHiddenSubObject RegressTestFundamentalHiddenSubObject; typedef struct _GObjectClass RegressTestFundamentalHiddenSubObjectClass; struct _RegressTestFundamentalHiddenSubObject { RegressTestFundamentalObject parent_instance; }; G_DEFINE_TYPE (RegressTestFundamentalHiddenSubObject, regress_test_fundamental_hidden_sub_object, REGRESS_TEST_TYPE_FUNDAMENTAL_OBJECT); static void regress_test_fundamental_hidden_sub_object_init (RegressTestFundamentalHiddenSubObject *self G_GNUC_UNUSED) { } static void regress_test_fundamental_hidden_sub_object_class_init (RegressTestFundamentalHiddenSubObjectClass *klass G_GNUC_UNUSED) { } /** * regress_test_create_fundamental_hidden_class_instance: * * Return value: (transfer full): */ RegressTestFundamentalObject * regress_test_create_fundamental_hidden_class_instance (void) { return (RegressTestFundamentalObject *) g_type_create_instance (_regress_test_fundamental_hidden_sub_object_get_type ()); } /** * RegressTestFundamentalObjectNoGetSetFunc: (ref-func regress_test_fundamental_object_ref) (unref-func regress_test_fundamental_object_unref) * * Just like a #RegressTestFundamentalObject but without gvalue setter and getter */ static void regress_test_fundamental_object_no_get_set_func_finalize (RegressTestFundamentalObjectNoGetSetFunc *self) { g_clear_pointer (&self->data, g_free); } static RegressTestFundamentalObjectNoGetSetFunc * regress_test_fundamental_object_no_get_set_func_copy (RegressTestFundamentalObjectNoGetSetFunc *self) { return regress_test_fundamental_object_no_get_set_func_new (self->data); } static void regress_test_fundamental_object_no_get_set_func_class_init (gpointer g_class, gpointer class_data G_GNUC_UNUSED) { RegressTestFundamentalObjectClass *mo_class = (RegressTestFundamentalObjectClass *) (g_class); mo_class->copy = (RegressTestFundamentalObjectCopyFunction) regress_test_fundamental_object_no_get_set_func_copy; mo_class->finalize = (RegressTestFundamentalObjectFinalizeFunction) regress_test_fundamental_object_no_get_set_func_finalize; } static void regress_test_fundamental_object_no_get_set_func_init (GTypeInstance *instance, gpointer klass G_GNUC_UNUSED) { RegressTestFundamentalObject *object = (RegressTestFundamentalObject *) (instance); object->refcount = 1; } GType regress_test_fundamental_object_no_get_set_func_get_type (void) { static GType _test_fundamental_object_type = 0; if (G_UNLIKELY (_test_fundamental_object_type == 0)) { static const GTypeValueTable value_table = { regress_test_value_fundamental_object_init, regress_test_value_fundamental_object_free, regress_test_value_fundamental_object_copy, regress_test_value_fundamental_object_peek_pointer, (char *) "p", regress_test_value_fundamental_object_collect, (char *) "p", regress_test_value_fundamental_object_lcopy }; static const GTypeInfo fundamental_object_info = { sizeof (RegressTestFundamentalObjectNoGetSetFuncClass), NULL, NULL, regress_test_fundamental_object_no_get_set_func_class_init, NULL, NULL, sizeof (RegressTestFundamentalObjectNoGetSetFunc), 0, (GInstanceInitFunc) regress_test_fundamental_object_no_get_set_func_init, &value_table }; static const GTypeFundamentalInfo fundamental_object_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; _test_fundamental_object_type = g_type_fundamental_next (); g_type_register_fundamental (_test_fundamental_object_type, "RegressTestFundamentalObjectNoGetSetFunc", &fundamental_object_info, &fundamental_object_fundamental_info, 0); } return _test_fundamental_object_type; } /** * regress_test_fundamental_object_no_get_set_func_new: * * Return value: (transfer full): */ RegressTestFundamentalObjectNoGetSetFunc * regress_test_fundamental_object_no_get_set_func_new (const char *data) { RegressTestFundamentalObjectNoGetSetFunc *object; object = (RegressTestFundamentalObjectNoGetSetFunc *) g_type_create_instance (regress_test_fundamental_object_no_get_set_func_get_type ()); object->data = g_strdup (data); return object; } const char * regress_test_fundamental_object_no_get_set_func_get_data (RegressTestFundamentalObjectNoGetSetFunc *fundamental) { g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (fundamental, regress_test_fundamental_object_no_get_set_func_get_type ()), NULL); return fundamental->data; } G_DEFINE_TYPE (RegressTestFundamentalSubObjectNoGetSetFunc, regress_test_fundamental_sub_object_no_get_set_func, regress_test_fundamental_object_no_get_set_func_get_type ()); static void regress_test_fundamental_sub_object_no_get_set_func_class_init (RegressTestFundamentalSubObjectNoGetSetFuncClass *klass G_GNUC_UNUSED) { } static void regress_test_fundamental_sub_object_no_get_set_func_init (RegressTestFundamentalSubObjectNoGetSetFunc *self G_GNUC_UNUSED) { } /** * regress_test_fundamental_sub_object_no_get_set_func_new: * * Return value: (transfer full): */ RegressTestFundamentalSubObjectNoGetSetFunc * regress_test_fundamental_sub_object_no_get_set_func_new (const char *data) { RegressTestFundamentalSubObjectNoGetSetFunc *object; RegressTestFundamentalObjectNoGetSetFunc *parent_object; object = (RegressTestFundamentalSubObjectNoGetSetFunc *) g_type_create_instance (regress_test_fundamental_sub_object_no_get_set_func_get_type ()); parent_object = (RegressTestFundamentalObjectNoGetSetFunc *) object; parent_object->data = g_strdup (data); return object; } static void fundamental_object_no_get_set_func_transform_to_compatible_with_fundamental_sub_object (const GValue *src_value, GValue *dest_value) { RegressTestFundamentalObjectNoGetSetFunc *src_object; RegressTestFundamentalSubObject *dest_object; g_return_if_fail (G_VALUE_TYPE (src_value) == regress_test_fundamental_object_no_get_set_func_get_type ()); g_return_if_fail (G_VALUE_TYPE (dest_value) == regress_test_fundamental_sub_object_get_type ()); src_object = g_value_peek_pointer (src_value); dest_object = regress_test_fundamental_sub_object_new (src_object->data); g_value_set_instance (dest_value, dest_object); regress_test_fundamental_object_unref ((RegressTestFundamentalObject *) dest_object); } void regress_test_fundamental_object_no_get_set_func_make_compatible_with_fundamental_sub_object (void) { g_value_register_transform_func ( regress_test_fundamental_object_no_get_set_func_get_type (), regress_test_fundamental_sub_object_get_type (), fundamental_object_no_get_set_func_transform_to_compatible_with_fundamental_sub_object); } /** * regress_test_callback: * @callback: (scope call) (allow-none): * **/ int regress_test_callback (RegressTestCallback callback) { if (callback != NULL) return callback (); return 0; } /** * regress_test_multi_callback: * @callback: (scope call) (allow-none): * **/ int regress_test_multi_callback (RegressTestCallback callback) { int sum = 0; if (callback != NULL) { sum += callback (); sum += callback (); } return sum; } /** * regress_test_array_callback: * @callback: (scope call): * **/ int regress_test_array_callback (RegressTestCallbackArray callback) { static const char *strings[] = { "one", "two", "three" }; static int ints[] = { -1, 0, 1, 2 }; int sum = 0; sum += callback (ints, 4, strings, 3); sum += callback (ints, 4, strings, 3); return sum; } /** * regress_test_array_inout_callback: * @callback: (scope call): * */ int regress_test_array_inout_callback (RegressTestCallbackArrayInOut callback) { int *ints; int length; ints = g_new (int, 5); for (length = 0; length < 5; ++length) ints[length] = length - 2; callback (&ints, &length); g_assert_cmpint (length, ==, 4); for (length = 0; length < 4; ++length) g_assert_cmpint (ints[length], ==, length - 1); callback (&ints, &length); g_assert_cmpint (length, ==, 3); for (length = 0; length < 3; ++length) g_assert_cmpint (ints[length], ==, length); g_free (ints); return length; } /** * regress_test_simple_callback: * @callback: (scope call) (allow-none): * **/ void regress_test_simple_callback (RegressTestSimpleCallback callback) { if (callback != NULL) callback (); return; } /** * regress_test_noptr_callback: * @callback: (scope call) (allow-none): * **/ void regress_test_noptr_callback (RegressTestNoPtrCallback callback) { if (callback != NULL) callback (); return; } /** * regress_test_callback_user_data: * @callback: (scope call): * @user_data: (not nullable): * * Call - callback parameter persists for the duration of the method * call and can be released on return. **/ int regress_test_callback_user_data (RegressTestCallbackUserData callback, gpointer user_data) { return callback (user_data); } /** * regress_test_callback_return_full: * @callback: (scope call): * **/ void regress_test_callback_return_full (RegressTestCallbackReturnFull callback) { RegressTestObj *obj; obj = callback (); g_object_unref (obj); } static GSList *notified_callbacks = NULL; /** * regress_test_callback_destroy_notify: * @callback: (scope notified): * * Notified - callback persists until a DestroyNotify delegate * is invoked. **/ int regress_test_callback_destroy_notify (RegressTestCallbackUserData callback, gpointer user_data, GDestroyNotify notify) { int retval; CallbackInfo *info; retval = callback (user_data); info = g_slice_new (CallbackInfo); info->callback = callback; info->notify = notify; info->user_data = user_data; notified_callbacks = g_slist_prepend (notified_callbacks, info); return retval; } /** * regress_test_callback_destroy_notify_no_user_data: * @callback: (scope notified): * * Adds a scope notified callback with no user data. This can invoke an error * condition in bindings which needs to be tested. **/ int regress_test_callback_destroy_notify_no_user_data (RegressTestCallbackUserData callback, GDestroyNotify notify) { return regress_test_callback_destroy_notify (callback, NULL, notify); } /** * regress_test_callback_thaw_notifications: * * Invokes all callbacks installed by #test_callback_destroy_notify(), * adding up their return values, and removes them, invoking the * corresponding destroy notfications. * * Return value: Sum of the return values of the invoked callbacks. */ int regress_test_callback_thaw_notifications (void) { int retval = 0; GSList *node; for (node = notified_callbacks; node != NULL; node = node->next) { CallbackInfo *info = node->data; retval += info->callback (info->user_data); if (info->notify) info->notify (info->user_data); g_slice_free (CallbackInfo, info); } g_slist_free (notified_callbacks); notified_callbacks = NULL; return retval; } static GSList *async_callbacks = NULL; /** * regress_test_callback_async: * @callback: (scope async): * **/ void regress_test_callback_async (RegressTestCallbackUserData callback, gpointer user_data) { CallbackInfo *info; info = g_slice_new (CallbackInfo); info->callback = callback; info->user_data = user_data; async_callbacks = g_slist_prepend (async_callbacks, info); } /** * regress_test_callback_thaw_async: */ int regress_test_callback_thaw_async (void) { int retval = 0; GSList *node; for (node = async_callbacks; node != NULL; node = node->next) { CallbackInfo *info = node->data; retval = info->callback (info->user_data); g_slice_free (CallbackInfo, info); } g_slist_free (async_callbacks); async_callbacks = NULL; return retval; } void regress_test_async_ready_callback (GAsyncReadyCallback callback) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS GSimpleAsyncResult *result = g_simple_async_result_new (NULL, callback, NULL, regress_test_async_ready_callback); g_simple_async_result_complete_in_idle (result); g_object_unref (result); G_GNUC_END_IGNORE_DEPRECATIONS } static GSList *async_function_tasks; /** * regress_test_function_async: * */ void regress_test_function_async (int io_priority G_GNUC_UNUSED, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task = g_task_new (NULL, cancellable, callback, user_data); async_function_tasks = g_slist_prepend (async_function_tasks, task); } /** * regress_test_function_thaw_async: * * Returns: the number of callbacks that were thawed. */ int regress_test_function_thaw_async (void) { int retval = 0; GSList *node; for (node = async_function_tasks; node != NULL; node = node->next) { GTask *task = node->data; g_task_return_boolean (task, TRUE); g_object_unref (task); retval++; } g_slist_free (async_function_tasks); async_function_tasks = NULL; return retval; } /** * regress_test_function_finish: * */ gboolean regress_test_function_finish (GAsyncResult *res, GError **error) { return g_task_propagate_boolean (G_TASK(res), error); } /** * regress_test_function_sync: * */ gboolean regress_test_function_sync (int io_priority G_GNUC_UNUSED) { return TRUE; } /** * regress_test_obj_instance_method_callback: * @callback: (scope call) (allow-none): * **/ void regress_test_obj_instance_method_callback (RegressTestObj *self G_GNUC_UNUSED, RegressTestCallback callback) { if (callback != NULL) callback (); } /** * regress_test_obj_static_method_callback: * @callback: (scope call) (allow-none): * **/ void regress_test_obj_static_method_callback (RegressTestCallback callback) { if (callback != NULL) callback (); } /** * regress_test_obj_new_callback: * @callback: (scope notified): **/ RegressTestObj * regress_test_obj_new_callback (RegressTestCallbackUserData callback, gpointer user_data, GDestroyNotify notify) { CallbackInfo *info; callback (user_data); info = g_slice_new (CallbackInfo); info->callback = callback; info->notify = notify; info->user_data = user_data; notified_callbacks = g_slist_prepend (notified_callbacks, info); return g_object_new (REGRESS_TEST_TYPE_OBJ, NULL); } static GSList *async_constructor_tasks; /** * regress_test_obj_new_async: * */ void regress_test_obj_new_async (const char *x G_GNUC_UNUSED, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task = g_task_new (NULL, cancellable, callback, user_data); async_constructor_tasks = g_slist_prepend (async_constructor_tasks, task); } /** * regress_test_obj_constructor_thaw_async: * * Returns: the number of callbacks that were thawed. */ int regress_test_obj_constructor_thaw_async (void) { int retval = 0; GSList *node; for (node = async_constructor_tasks; node != NULL; node = node->next) { GTask *task = node->data; RegressTestObj *obj = g_object_new (REGRESS_TEST_TYPE_OBJ, NULL); g_task_return_pointer (task, obj, g_object_unref); g_object_unref (task); retval++; } g_slist_free (async_constructor_tasks); async_constructor_tasks = NULL; return retval; } /** * regress_test_obj_new_finish: * */ RegressTestObj * regress_test_obj_new_finish (GAsyncResult *res, GError **error) { return g_task_propagate_pointer (G_TASK (res), error); } /** * regress_test_hash_table_callback: * @data: (element-type utf8 gint): GHashTable that gets passed to callback * @callback: (scope call): **/ void regress_test_hash_table_callback (GHashTable *data, RegressTestCallbackHashtable callback) { callback (data); } /** * regress_test_gerror_callback: * @callback: (scope call): **/ void regress_test_gerror_callback (RegressTestCallbackGError callback) { GError *error; error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "regression test error"); callback (error); g_error_free (error); } /** * regress_test_null_gerror_callback: * @callback: (scope call): **/ void regress_test_null_gerror_callback (RegressTestCallbackGError callback) { callback (NULL); } /** * regress_test_owned_gerror_callback: * @callback: (scope call): **/ void regress_test_owned_gerror_callback (RegressTestCallbackOwnedGError callback) { GError *error; error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, "regression test owned error"); callback (error); } /** * regress_test_skip_unannotated_callback: (skip) * @callback: No annotation here * * Should not emit a warning: * https://bugzilla.gnome.org/show_bug.cgi?id=685399 */ void regress_test_skip_unannotated_callback (RegressTestCallback callback G_GNUC_UNUSED) { } /* interface */ typedef RegressTestInterfaceIface RegressTestInterfaceInterface; G_DEFINE_INTERFACE (RegressTestInterface, regress_test_interface, G_TYPE_OBJECT) static void regress_test_interface_default_init (RegressTestInterfaceIface *iface) { const guint flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS; static gboolean initialized = FALSE; if (initialized) return; /** * RegressTestInterface::interface-signal: * @self: the object which emitted the signal * @ptr: (type int): the code must look up the signal with * g_interface_info_find_signal() in order to get this to work. */ g_signal_new ("interface-signal", REGRESS_TEST_TYPE_INTERFACE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * RegressTestInterface:number: */ g_object_interface_install_property (iface, g_param_spec_int ("number", "Number", "Number", 0, 10, 0, flags)); initialized = TRUE; } /** * regress_test_interface_emit_signal: * @self: the object to emit the signal */ void regress_test_interface_emit_signal (RegressTestInterface *self) { g_signal_emit_by_name (self, "interface-signal", NULL); } /* gobject with non-standard prefix */ G_DEFINE_TYPE (RegressTestWi8021x, regress_test_wi_802_1x, G_TYPE_OBJECT); enum { PROP_TEST_WI_802_1X_TESTBOOL = 1 }; static void regress_test_wi_802_1x_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { RegressTestWi8021x *self = REGRESS_TEST_WI_802_1X (object); switch (property_id) { case PROP_TEST_WI_802_1X_TESTBOOL: regress_test_wi_802_1x_set_testbool (self, g_value_get_boolean (value)); break; default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void regress_test_wi_802_1x_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { RegressTestWi8021x *self = REGRESS_TEST_WI_802_1X (object); switch (property_id) { case PROP_TEST_WI_802_1X_TESTBOOL: g_value_set_boolean (value, regress_test_wi_802_1x_get_testbool (self)); break; default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void regress_test_wi_802_1x_dispose (GObject *gobject) { /* Chain up to the parent class */ G_OBJECT_CLASS (regress_test_wi_802_1x_parent_class)->dispose (gobject); } static void regress_test_wi_802_1x_class_init (RegressTestWi8021xClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; gobject_class->set_property = regress_test_wi_802_1x_set_property; gobject_class->get_property = regress_test_wi_802_1x_get_property; gobject_class->dispose = regress_test_wi_802_1x_dispose; pspec = g_param_spec_boolean ("testbool", "Nick for testbool", "Blurb for testbool", TRUE, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_TEST_WI_802_1X_TESTBOOL, pspec); } static void regress_test_wi_802_1x_init (RegressTestWi8021x *obj) { obj->testbool = TRUE; } RegressTestWi8021x * regress_test_wi_802_1x_new (void) { return g_object_new (REGRESS_TEST_TYPE_WI_802_1X, NULL); } void regress_test_wi_802_1x_set_testbool (RegressTestWi8021x *obj, gboolean val) { obj->testbool = val; } gboolean regress_test_wi_802_1x_get_testbool (RegressTestWi8021x *obj) { return obj->testbool; } int regress_test_wi_802_1x_static_method (int x) { return 2 * x; } /* floating gobject */ G_DEFINE_TYPE (RegressTestFloating, regress_test_floating, G_TYPE_INITIALLY_UNOWNED); static void regress_test_floating_finalize (GObject *object) { g_assert (!g_object_is_floating (object)); G_OBJECT_CLASS (regress_test_floating_parent_class)->finalize (object); } static void regress_test_floating_class_init (RegressTestFloatingClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = regress_test_floating_finalize; } static void regress_test_floating_init (RegressTestFloating *self G_GNUC_UNUSED) { } /** * regress_test_floating_new: * * Returns:: A new floating #RegressTestFloating */ RegressTestFloating * regress_test_floating_new (void) { return g_object_new (REGRESS_TEST_TYPE_FLOATING, NULL); } /** * regress_test_torture_signature_0: * @x: * @y: (out): * @z: (out): * @foo: * @q: (out): * @m: * */ void regress_test_torture_signature_0 (int x, double *y, int *z, const char *foo, int *q, guint m) { *y = x; *z = x * 2; *q = g_utf8_strlen (foo, -1) + m; } /** * regress_test_torture_signature_1: * @x: * @y: (out): * @z: (out): * @foo: * @q: (out): * @m: * @error: A #GError * * This function throws an error if m is odd. */ gboolean regress_test_torture_signature_1 (int x, double *y, int *z, const char *foo, int *q, guint m, GError **error) { *y = x; *z = x * 2; *q = g_utf8_strlen (foo, -1) + m; if (m % 2 == 0) return TRUE; g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "m is odd"); return FALSE; } /** * regress_test_torture_signature_2: * @x: * @callback: * @user_data: * @notify: * @y: (out): * @z: (out): * @foo: * @q: (out): * @m: * */ void regress_test_torture_signature_2 (int x, RegressTestCallbackUserData callback, gpointer user_data, GDestroyNotify notify, double *y, int *z, const char *foo, int *q, guint m) { *y = x; *z = x * 2; *q = g_utf8_strlen (foo, -1) + m; callback (user_data); notify (user_data); } /** * regress_test_date_in_gvalue: * * Returns: (transfer full): */ GValue * regress_test_date_in_gvalue (void) { GValue *value = g_new0 (GValue, 1); GDate *date = g_date_new_dmy (5, 12, 1984); g_value_init (value, G_TYPE_DATE); g_value_take_boxed (value, date); return value; } /** * regress_test_strv_in_gvalue: * * Returns: (transfer full): */ GValue * regress_test_strv_in_gvalue (void) { GValue *value = g_new0 (GValue, 1); const char *strv[] = { "one", "two", "three", NULL }; g_value_init (value, G_TYPE_STRV); g_value_set_boxed (value, strv); return value; } /** * regress_test_null_strv_in_gvalue: * * Returns: (transfer full): */ GValue * regress_test_null_strv_in_gvalue (void) { GValue *value = g_new0 (GValue, 1); const char **strv = NULL; g_value_init (value, G_TYPE_STRV); g_value_set_boxed (value, strv); return value; } /** * regress_test_multiline_doc_comments: * * This is a function. * * It has multiple lines in the documentation. * * The sky is blue. * * You will give me your credit card number. */ void regress_test_multiline_doc_comments (void) { } /** * regress_test_nested_parameter: * @a: An integer * * * * * * Syntax * Explanation * Examples * * * * * rgb(@r, @g, @b) * An opaque color; @r, @g, @b can be either integers between * 0 and 255 or percentages * rgb(128, 10, 54) * rgb(20%, 30%, 0%) * * * rgba(@r, @g, @b, @a) * A translucent color; @r, @g, @b are as in the previous row, * @a is a floating point number between 0 and 1 * rgba(255, 255, 0, 0.5) * * * * * * What we're testing here is that the scanner ignores the @a nested inside XML. */ void regress_test_nested_parameter (int a G_GNUC_UNUSED) { } /** * regress_introspectable_via_alias: * */ void regress_introspectable_via_alias (RegressPtrArrayAlias *data G_GNUC_UNUSED) { } /** * regress_not_introspectable_via_alias: * */ void regress_not_introspectable_via_alias (RegressVaListAlias ok G_GNUC_UNUSED) { } /** * regress_aliased_caller_alloc: * @boxed: (out): */ void regress_aliased_caller_alloc (RegressAliasedTestBoxed *boxed) { boxed->priv = g_slice_new0 (RegressTestBoxedPrivate); boxed->priv->magic = 0xdeadbeef; } void regress_test_struct_fixed_array_frob (RegressTestStructFixedArray *str) { guint i; str->just_int = 7; for (i = 0; i < G_N_ELEMENTS (str->array); i++) str->array[i] = 42 + i; } /** * regress_has_parameter_named_attrs: * @foo: some int * @attributes: (type guint32) (array fixed-size=32): list of attributes * * This test case mirrors GnomeKeyringPasswordSchema from * libgnome-keyring. */ void regress_has_parameter_named_attrs (int foo G_GNUC_UNUSED, gpointer attributes G_GNUC_UNUSED) { } /** * regress_test_versioning: * * Since: 1.32.1: Actually, this function was introduced earlier * than this, but it didn't do anything before this version. * Deprecated: 1.33.3: This function has been deprecated, * because it sucks. Use foobar instead. * Stability: Unstable: Maybe someday we will find the time * to stabilize this function. Who knows? */ void regress_test_versioning (void) { } void regress_like_xkl_config_item_set_name (RegressLikeXklConfigItem *self, char const *name) { strncpy (self->name, name, sizeof (self->name) - 1); self->name[sizeof (self->name) - 1] = '\0'; } /** * regress_get_variant: * * Returns: (transfer floating): A new variant */ GVariant * regress_get_variant (void) { return g_variant_new_int32 (42); } /** * regress_test_array_struct_out_none: * @arr: (out) (array length=len) (transfer none): An array * @len: (out): Length of @arr * * Test flat array output with transfer none. * * Similar to: * - mm_modem_peek_ports() with structs * - gdk_query_visual_types() with enums * - gdk_event_get_axes() with doubles */ void regress_test_array_struct_out_none (RegressTestStructA **arr, gsize *len) { static RegressTestStructA array[3] = { { .some_int = 111 }, { .some_int = 222 }, { .some_int = 333 }, }; *arr = array; *len = 3; } /** * regress_test_array_struct_out_container: * @arr: (out) (array length=len) (transfer container): An array * @len: (out): Length of @arr * * Test flat array output with transfer container. * * Similar to pango_layout_get_log_attrs(). */ void regress_test_array_struct_out_container (RegressTestStructA **arr, gsize *len) { *arr = g_new0 (RegressTestStructA, 5); (*arr)[0].some_int = 11; (*arr)[1].some_int = 13; (*arr)[2].some_int = 17; (*arr)[3].some_int = 19; (*arr)[4].some_int = 23; *len = 5; } /** * regress_test_array_struct_out_full_fixed: * @arr: (out) (array fixed-size=4) (transfer full): An array * * Test flat fixed-size array output with transfer full. */ void regress_test_array_struct_out_full_fixed (RegressTestStructA **arr) { *arr = g_new0 (RegressTestStructA, 4); (*arr)[0].some_int = 2; (*arr)[1].some_int = 3; (*arr)[2].some_int = 5; (*arr)[3].some_int = 7; } /** * regress_test_array_struct_out_caller_alloc: * @arr: (out caller-allocates) (array length=len): An array * @len: Length of @arr * * Test flat caller-allocated array output. * * Similar to g_main_context_query(). */ void regress_test_array_struct_out_caller_alloc (RegressTestStructA *arr, gsize len) { guint i; g_assert (arr != NULL); memset (arr, 0, sizeof (RegressTestStructA) * len); for (i = 0; i != len; ++i) arr[i].some_int = 111 * (i + 1); } /** * regress_test_array_struct_in_full: * @arr: (in) (array length=len) (transfer full): An array * @len: Length of @arr * * Test flat array input with transfer full. * * Similar to: * - gsf_property_settings_free() with structs but they contain pointers * - g_byte_array_new_take() with guint8s */ void regress_test_array_struct_in_full (RegressTestStructA *arr, gsize len) { g_assert_cmpint (len, ==, 2); g_assert_cmpint (arr[0].some_int, ==, 201); g_assert_cmpint (arr[1].some_int, ==, 202); g_free (arr); } /** * regress_test_array_struct_in_none: * @arr: (in) (array length=len) (transfer none): An array. * @len: Length of @arr * * Test flat array input with transfer none. * * Similar to g_main_context_check() or gtk_target_list_new(). */ void regress_test_array_struct_in_none (RegressTestStructA *arr, gsize len) { g_assert_cmpint (len, ==, 3); g_assert_cmpint (arr[0].some_int, ==, 301); g_assert_cmpint (arr[1].some_int, ==, 302); g_assert_cmpint (arr[2].some_int, ==, 303); } static GSList *async_method_tasks; /** * regress_test_obj_function_async: * */ void regress_test_obj_function_async (RegressTestObj *self, int io_priority G_GNUC_UNUSED, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task = g_task_new (self, cancellable, callback, user_data); async_method_tasks = g_slist_prepend (async_method_tasks, task); } /** * regress_test_obj_function_thaw_async: * @self: * * Returns: the number of callbacks that were thawed. */ int regress_test_obj_function_thaw_async (RegressTestObj *self G_GNUC_UNUSED) { int retval = 0; GSList *node; for (node = async_method_tasks; node != NULL; node = node->next) { GTask *task = node->data; g_task_return_boolean (task, TRUE); g_object_unref (task); retval++; } g_slist_free (async_method_tasks); async_method_tasks = NULL; return retval; } /** * regress_test_obj_function_finish: * */ gboolean regress_test_obj_function_finish (RegressTestObj *self G_GNUC_UNUSED, GAsyncResult *res, GError **error) { return g_task_propagate_boolean (G_TASK(res), error); } /** * regress_test_obj_function_sync: * */ gboolean regress_test_obj_function_sync (RegressTestObj *self G_GNUC_UNUSED, int io_priority G_GNUC_UNUSED) { return TRUE; } /** * regress_test_obj_function2: * @self: a #RegressTestObj * @io_priority: a number * @cancellable: (nullable): a #GCancellable, or %NULL * @test_cb: (nullable) (scope notified) (closure test_data): match reporting callback * @test_data: user data for @test_cb * @test_destroy: (destroy test_data): Destroy notify for @match_data * @callback: the function to call on completion * @user_data: the data to pass to @callback * * This is an example taken from FPrint: `fp_device_verify`. */ void regress_test_obj_function2 (RegressTestObj *self, int io_priority G_GNUC_UNUSED, GCancellable *cancellable, RegressTestCallbackUserData test_cb, gpointer test_data, GDestroyNotify test_destroy, GAsyncReadyCallback callback, gpointer user_data) { GTask *task = g_task_new (self, cancellable, callback, user_data); async_method_tasks = g_slist_prepend (async_method_tasks, task); if (test_cb != NULL) test_cb (test_data); if (test_destroy != NULL) test_destroy (test_data); } /** * regress_test_obj_function2_finish: * @self: A #TestObj * @result: A #GAsyncResult * @match: (out): An extra parameter, similar to `fp_device_verify_finish()` * @some_obj: (out) (transfer full) (nullable): An output object, or %NULL to ignore * @error: Return location for errors, or %NULL to ignore * * Finish function for `regress_test_obj_function2_async()`. * * Returns: (type void): %FALSE on error, %TRUE otherwise */ gboolean regress_test_obj_function2_finish (RegressTestObj *self G_GNUC_UNUSED, GAsyncResult *result, gboolean *match, GObject **some_obj, GError **error) { gboolean res = g_task_propagate_boolean (G_TASK (result), error); *match = res; if (some_obj) *some_obj = NULL; return res; } /** * regress_test_obj_function2_sync: * */ gboolean regress_test_obj_function2_sync (RegressTestObj *self G_GNUC_UNUSED, int io_priority G_GNUC_UNUSED) { return TRUE; } G_DEFINE_FLAGS_TYPE (RegressTestDiscontinuousFlags, regress_test_discontinuous_flags, G_DEFINE_ENUM_VALUE (REGRESS_TEST_DISCONTINUOUS_FLAG1, "discontinuous1"), G_DEFINE_ENUM_VALUE (REGRESS_TEST_DISCONTINUOUS_FLAG2, "discontinuous2")) /** * regress_test_discontinuous_1_with_private_values: * * Returns: REGRESS_TEST_DISCONTINUOUS_FLAG1 with a private value lower than the smallest RegressTestDiscontinuousFlags enum value. */ RegressTestDiscontinuousFlags regress_test_discontinuous_1_with_private_values (void) { return 1 << 3 | REGRESS_TEST_DISCONTINUOUS_FLAG1; } /** * regress_test_discontinuous_2_with_private_values: * * Returns: REGRESS_TEST_DISCONTINUOUS_FLAG2 with a private value higher than the largest RegressTestDiscontinuousFlags enum value. */ RegressTestDiscontinuousFlags regress_test_discontinuous_2_with_private_values (void) { return 1 << 30 | REGRESS_TEST_DISCONTINUOUS_FLAG2; }././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/regress.h0000664000000000000000000014335115056773103024215 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2008-2013, 2015 Colin Walters SPDX-FileCopyrightText: 2008 Johan Bilien SPDX-FileCopyrightText: 2008-2010 Johan Dahlin SPDX-FileCopyrightText: 2008 Lucas Almeida Rocha SPDX-FileCopyrightText: 2008, 2010 Owen W. Taylor SPDX-FileCopyrightText: 2009 Andreas Rottmann SPDX-FileCopyrightText: 2009 Havoc Pennington SPDX-FileCopyrightText: 2009-2010 litl, LLC SPDX-FileCopyrightText: 2009 Mark Lee SPDX-FileCopyrightText: 2009, 2011 Maxim Ermilov SPDX-FileCopyrightText: 2009 Simon van der Linden SPDX-FileCopyrightText: 2009-2010 Sugar Labs SPDX-FileCopyrightText: 2010-2012, 2015 Collabora, Ltd. SPDX-FileCopyrightText: 2010 Jonathan Matthew SPDX-FileCopyrightText: 2010 Zach Goldberg SPDX-FileCopyrightText: 2011-2012, 2014 Giovanni Campagna SPDX-FileCopyrightText: 2011-2012 Martin Pitt SPDX-FileCopyrightText: 2011 Pavel Holejsovsky SPDX-FileCopyrightText: 2011, 2024 Red Hat, Inc. SPDX-FileCopyrightText: 2011-2012 Torsten Schönfeld SPDX-FileCopyrightText: 2011 Xavier Claessens SPDX-FileCopyrightText: 2012 Alban Browaeys SPDX-FileCopyrightText: 2012 Bastian Winkler SPDX-FileCopyrightText: 2012 Canonical Ltd. SPDX-FileCopyrightText: 2012 Coeus Group SPDX-FileCopyrightText: 2012 Dieter Verfaillie SPDX-FileCopyrightText: 2012-2013 Jasper St. Pierre SPDX-FileCopyrightText: 2012 Jon Nordby SPDX-FileCopyrightText: 2012 Krzesimir Nowak SPDX-FileCopyrightText: 2012 Paolo Borelli SPDX-FileCopyrightText: 2012, 2014 Simon Feltman SPDX-FileCopyrightText: 2013, 2019, 2021-2022 Emmanuele Bassi SPDX-FileCopyrightText: 2013 Florian Müllner SPDX-FileCopyrightText: 2013 Stef Walter SPDX-FileCopyrightText: 2014-2015 RIFT.io, Inc. SPDX-FileCopyrightText: 2015 Ben Iofel SPDX-FileCopyrightText: 2015 Christoph Reiter SPDX-FileCopyrightText: 2015 Debarshi Ray SPDX-FileCopyrightText: 2016 Intel SPDX-FileCopyrightText: 2016 Lionel Landwerlin SPDX-FileCopyrightText: 2017 Endless Mobile, Inc. SPDX-FileCopyrightText: 2016-2019, 2024 Philip Chimento SPDX-FileCopyrightText: 2017 Rico Tzschichholz SPDX-FileCopyrightText: 2018-2019 Tomasz MiÄ…sko SPDX-FileCopyrightText: 2020 Centricular SPDX-FileCopyrightText: 2021, 2023 Marco Trevisan SPDX-FileCopyrightText: 2022 Lubomir Rintel SPDX-FileCopyrightText: 2023-2024 Simon McVittie SPDX-FileCopyrightText: 2023 Evan Welsh */ #pragma once #include #include #include #include #include #ifndef GI_TEST_DISABLE_CAIRO #include #endif /* GI_TEST_DISABLE_CAIRO */ #include "gitestmacros.h" GI_TEST_EXTERN void regress_set_abort_on_error (gboolean abort_on_error); /* return annotations */ GI_TEST_EXTERN char *regress_test_return_allow_none (void); GI_TEST_EXTERN char *regress_test_return_nullable (void); /* basic types */ GI_TEST_EXTERN gboolean regress_test_boolean (gboolean in); GI_TEST_EXTERN gboolean regress_test_boolean_true (gboolean in); GI_TEST_EXTERN gboolean regress_test_boolean_false (gboolean in); GI_TEST_EXTERN gint8 regress_test_int8 (gint8 in); GI_TEST_EXTERN guint8 regress_test_uint8 (guint8 in); GI_TEST_EXTERN gint16 regress_test_int16 (gint16 in); GI_TEST_EXTERN guint16 regress_test_uint16 (guint16 in); GI_TEST_EXTERN gint32 regress_test_int32 (gint32 in); GI_TEST_EXTERN guint32 regress_test_uint32 (guint32 in); GI_TEST_EXTERN gint64 regress_test_int64 (gint64 in); GI_TEST_EXTERN guint64 regress_test_uint64 (guint64 in); GI_TEST_EXTERN gshort regress_test_short (gshort in); GI_TEST_EXTERN gushort regress_test_ushort (gushort in); GI_TEST_EXTERN gint regress_test_int (gint in); GI_TEST_EXTERN guint regress_test_uint (guint in); GI_TEST_EXTERN glong regress_test_long (glong in); GI_TEST_EXTERN gulong regress_test_ulong (gulong in); GI_TEST_EXTERN gssize regress_test_ssize (gssize in); GI_TEST_EXTERN gsize regress_test_size (gsize in); GI_TEST_EXTERN gfloat regress_test_float (gfloat in); GI_TEST_EXTERN gdouble regress_test_double (gdouble in); GI_TEST_EXTERN gunichar regress_test_unichar (gunichar in); GI_TEST_EXTERN time_t regress_test_timet (time_t in); GI_TEST_EXTERN off_t regress_test_offt (off_t in); GI_TEST_EXTERN GType regress_test_gtype (GType in); /* utf8 */ GI_TEST_EXTERN const char *regress_test_utf8_const_return (void); GI_TEST_EXTERN char *regress_test_utf8_nonconst_return (void); GI_TEST_EXTERN void regress_test_utf8_const_in (const char *in); GI_TEST_EXTERN void regress_test_utf8_out (char **out); GI_TEST_EXTERN void regress_test_utf8_inout (char **inout); GI_TEST_EXTERN GSList *regress_test_filename_return (void); GI_TEST_EXTERN void regress_test_utf8_null_in (char *in); GI_TEST_EXTERN void regress_test_utf8_null_out (char **char_out); /* in arguments after out arguments */ GI_TEST_EXTERN void regress_test_int_out_utf8 (int *length, const char *in); /* multiple output arguments */ GI_TEST_EXTERN void regress_test_multi_double_args (gdouble in, gdouble *one, gdouble *two); GI_TEST_EXTERN void regress_test_utf8_out_out (char **out0, char **out1); GI_TEST_EXTERN char *regress_test_utf8_out_nonconst_return (char **out); /* non-basic-types */ /* array */ GI_TEST_EXTERN gboolean regress_test_strv_in (char **arr); GI_TEST_EXTERN int regress_test_array_int_in (int n_ints, int *ints); GI_TEST_EXTERN void regress_test_array_int_out (int *n_ints, int **ints); GI_TEST_EXTERN void regress_test_array_int_inout (int *n_ints, int **ints); GI_TEST_EXTERN int regress_test_array_gint8_in (int n_ints, gint8 *ints); GI_TEST_EXTERN int regress_test_array_gint16_in (int n_ints, gint16 *ints); GI_TEST_EXTERN gint32 regress_test_array_gint32_in (int n_ints, gint32 *ints); GI_TEST_EXTERN gint64 regress_test_array_gint64_in (int n_ints, gint64 *ints); GI_TEST_EXTERN char *regress_test_array_gtype_in (int n_types, GType *types); GI_TEST_EXTERN const char **regress_test_strv_out_container (void); GI_TEST_EXTERN char **regress_test_strv_out (void); GI_TEST_EXTERN const char *const *regress_test_strv_out_c (void); GI_TEST_EXTERN void regress_test_strv_outarg (const char ***retp); GI_TEST_EXTERN int regress_test_array_fixed_size_int_in (int *ints); GI_TEST_EXTERN void regress_test_array_fixed_size_int_out (int **ints); GI_TEST_EXTERN int *regress_test_array_fixed_size_int_return (void); /* transfer tests */ GI_TEST_EXTERN int *regress_test_array_int_full_out (int *len); GI_TEST_EXTERN int *regress_test_array_int_none_out (int *len); GI_TEST_EXTERN void regress_test_array_int_null_in (int *arr, int len); GI_TEST_EXTERN void regress_test_array_int_null_out (int **arr, int *len); /* interface */ /* GList */ GI_TEST_EXTERN const GList *regress_test_glist_nothing_return (void); GI_TEST_EXTERN GList *regress_test_glist_nothing_return2 (void); GI_TEST_EXTERN GList *regress_test_glist_container_return (void); GI_TEST_EXTERN GList *regress_test_glist_everything_return (void); GI_TEST_EXTERN void regress_test_glist_gtype_container_in (GList *in); GI_TEST_EXTERN void regress_test_glist_nothing_in (const GList *in); GI_TEST_EXTERN void regress_test_glist_nothing_in2 (GList *in); GI_TEST_EXTERN void regress_test_glist_null_in (GSList *in); GI_TEST_EXTERN void regress_test_glist_null_out (GSList **out_list); /* GSList */ GI_TEST_EXTERN const GSList *regress_test_gslist_nothing_return (void); GI_TEST_EXTERN GSList *regress_test_gslist_nothing_return2 (void); GI_TEST_EXTERN GSList *regress_test_gslist_container_return (void); GI_TEST_EXTERN GSList *regress_test_gslist_everything_return (void); GI_TEST_EXTERN void regress_test_gslist_nothing_in (const GSList *in); GI_TEST_EXTERN void regress_test_gslist_nothing_in2 (GSList *in); GI_TEST_EXTERN void regress_test_gslist_null_in (GSList *in); GI_TEST_EXTERN void regress_test_gslist_null_out (GSList **out_list); /* GHashTable */ GI_TEST_EXTERN const GHashTable *regress_test_ghash_null_return (void); GI_TEST_EXTERN const GHashTable *regress_test_ghash_nothing_return (void); GI_TEST_EXTERN GHashTable *regress_test_ghash_nothing_return2 (void); GI_TEST_EXTERN GHashTable *regress_test_ghash_gvalue_return (void); GI_TEST_EXTERN void regress_test_ghash_gvalue_in (GHashTable *hash); GI_TEST_EXTERN GHashTable *regress_test_ghash_container_return (void); GI_TEST_EXTERN GHashTable *regress_test_ghash_everything_return (void); GI_TEST_EXTERN void regress_test_ghash_null_in (const GHashTable *in); GI_TEST_EXTERN void regress_test_ghash_null_out (const GHashTable **out); GI_TEST_EXTERN void regress_test_ghash_nothing_in (const GHashTable *in); GI_TEST_EXTERN void regress_test_ghash_nothing_in2 (GHashTable *in); GI_TEST_EXTERN GHashTable *regress_test_ghash_nested_everything_return (void); GI_TEST_EXTERN GHashTable *regress_test_ghash_nested_everything_return2 (void); /* GPtrArray */ GI_TEST_EXTERN GPtrArray *regress_test_garray_container_return (void); GI_TEST_EXTERN GPtrArray *regress_test_garray_full_return (void); /* error? */ /* closure */ GI_TEST_EXTERN int regress_test_closure (GClosure *closure); GI_TEST_EXTERN int regress_test_closure_one_arg (GClosure *closure, int arg); GI_TEST_EXTERN GVariant *regress_test_closure_variant (GClosure *closure, GVariant *arg); /* value */ GI_TEST_EXTERN int regress_test_int_value_arg (const GValue *v); GI_TEST_EXTERN const GValue *regress_test_value_return (int i); /* foreign structs */ #ifndef GI_TEST_DISABLE_CAIRO GI_TEST_EXTERN cairo_t *regress_test_cairo_context_full_return (void); GI_TEST_EXTERN void regress_test_cairo_context_none_in (cairo_t *context); GI_TEST_EXTERN cairo_surface_t *regress_test_cairo_surface_none_return (void); GI_TEST_EXTERN cairo_surface_t *regress_test_cairo_surface_full_return (void); GI_TEST_EXTERN void regress_test_cairo_surface_none_in (cairo_surface_t *surface); GI_TEST_EXTERN void regress_test_cairo_surface_full_out (cairo_surface_t **surface); #endif /* GI_TEST_DISABLE_CAIRO */ /* versioning (deprecated, since, stability) */ GI_TEST_EXTERN void regress_test_versioning (void); GI_TEST_EXTERN GVariant *regress_test_gvariant_i (void); GI_TEST_EXTERN GVariant *regress_test_gvariant_s (void); GI_TEST_EXTERN GVariant *regress_test_gvariant_asv (void); GI_TEST_EXTERN GVariant *regress_test_gvariant_v (void); GI_TEST_EXTERN GVariant *regress_test_gvariant_as (void); /* enums / flags */ #define NUM_REGRESS_FOO /** * RegressTestEnum: * @REGRESS_TEST_VALUE1: value 1 * @REGRESS_TEST_VALUE2: value 2 * * By purpose, not all members have documentation */ typedef enum { REGRESS_TEST_VALUE1, REGRESS_TEST_VALUE2, REGRESS_TEST_VALUE3 = -1, REGRESS_TEST_VALUE4 = '0', REGRESS_TEST_VALUE5 } RegressTestEnum; typedef enum { REGRESS_TEST_UNSIGNED_VALUE1 = 1, REGRESS_TEST_UNSIGNED_VALUE2 = 0x80000000 } RegressTestEnumUnsigned; typedef enum { REGRESS_TEST_FLAG1 = 1 << 0, REGRESS_TEST_FLAG2 = 1 << 1, REGRESS_TEST_FLAG3 = 1 << 2, } RegressTestFlags; typedef enum { REGRESS_TEST_DISCONTINUOUS_FLAG1 = 1 << 9, REGRESS_TEST_DISCONTINUOUS_FLAG2 = 1 << 29 } RegressTestDiscontinuousFlags; GI_TEST_EXTERN GType regress_test_discontinuous_flags_get_type (void) G_GNUC_CONST; #define REGRESS_TEST_TYPE_DISCONTINUOUS_FLAGS (regress_test_discontinuous_flags_get_type ()) GI_TEST_EXTERN RegressTestDiscontinuousFlags regress_test_discontinuous_1_with_private_values (void); GI_TEST_EXTERN RegressTestDiscontinuousFlags regress_test_discontinuous_2_with_private_values (void); GI_TEST_EXTERN GType regress_test_enum_get_type (void) G_GNUC_CONST; #define REGRESS_TEST_TYPE_ENUM (regress_test_enum_get_type ()) GI_TEST_EXTERN GType regress_test_enum_unsigned_get_type (void) G_GNUC_CONST; #define REGRESS_TEST_TYPE_ENUM_UNSIGNED (regress_test_enum_unsigned_get_type ()) GI_TEST_EXTERN GType regress_test_flags_get_type (void) G_GNUC_CONST; #define REGRESS_TEST_TYPE_FLAGS (regress_test_flags_get_type ()) typedef enum { REGRESS_TEST_REFERENCE_ZERO = 2 + 2, REGRESS_TEST_REFERENCE_ONE = 1 + 1, REGRESS_TEST_REFERENCE_TWO = 6 * 9, REGRESS_TEST_REFERENCE_THREE = REGRESS_TEST_REFERENCE_ONE + REGRESS_TEST_REFERENCE_ONE, REGRESS_TEST_REFERENCE_FOUR = REGRESS_TEST_REFERENCE_TWO * REGRESS_TEST_REFERENCE_THREE, REGRESS_TEST_REFERENCE_FIVE = ~REGRESS_TEST_REFERENCE_FOUR, } RegressTestReferenceEnum; /* this is not registered with GType */ typedef enum { REGRESS_TEST_EVALUE1, REGRESS_TEST_EVALUE2 = 42, REGRESS_TEST_EVALUE3 = '0' } RegressTestEnumNoGEnum; /** * REGRESS_TEST_EVALUE_DEPRECATED: * * Scanner used to replace %REGRESS_TEST_EVALUE1 with %REGRESS_TEST_EVALUE_DEPRECATED. */ #define REGRESS_TEST_EVALUE_DEPRECATED REGRESS_TEST_EVALUE1 GI_TEST_EXTERN const gchar *regress_test_enum_param (RegressTestEnum e); GI_TEST_EXTERN const gchar *regress_test_unsigned_enum_param (RegressTestEnumUnsigned e); GI_TEST_EXTERN void regress_global_get_flags_out (RegressTestFlags *v); /* error domains */ typedef enum { REGRESS_TEST_ERROR_CODE1 = 1, REGRESS_TEST_ERROR_CODE2 = 2, REGRESS_TEST_ERROR_CODE3 = 3 } RegressTestError; GI_TEST_EXTERN GType regress_test_error_get_type (void); GI_TEST_EXTERN GQuark regress_test_error_quark (void); /* Test weird names, with and without c_symbol_prefix given by a GType */ typedef enum { REGRESS_TEST_ABC_ERROR_CODE1 = 1, REGRESS_TEST_ABC_ERROR_CODE2 = 2, REGRESS_TEST_ABC_ERROR_CODE3 = 3 } RegressTestABCError; GI_TEST_EXTERN GType regress_test_abc_error_get_type (void); GI_TEST_EXTERN GQuark regress_test_abc_error_quark (void); typedef enum { REGRESS_TEST_OTHER_ERROR_CODE1 = 1, REGRESS_TEST_OTHER_ERROR_CODE2 = 2, REGRESS_TEST_OTHER_ERROR_CODE3 = 3 } RegressTestOtherError; /* This returns a GType for RegressTestOtherError. The difference is intentional, although it is mainly meant for capitalization problems. */ GI_TEST_EXTERN GType regress_test_unconventional_error_get_type (void); GI_TEST_EXTERN GQuark regress_test_unconventional_error_quark (void); typedef enum { REGRESS_TEST_DEF_ERROR_CODE0 = 0, REGRESS_TEST_DEF_ERROR_CODE1 = 1, REGRESS_TEST_DEF_ERROR_CODE2 = 2 } RegressTestDEFError; GI_TEST_EXTERN GQuark regress_test_def_error_quark (void); /* the scanner used to have problem with two uppercase letter right after the identifier prefix, that's why we break the RegressTest convention */ typedef enum { REGRESS_ATEST_ERROR_CODE0 = 0, REGRESS_ATEST_ERROR_CODE1 = 1, REGRESS_ATEST_ERROR_CODE2 = 2 } RegressATestError; GI_TEST_EXTERN GQuark regress_atest_error_quark (void); /* constants */ #define REGRESS_NEGATIVE_INT_CONSTANT -42 #define REGRESS_INT_CONSTANT 4422 #define REGRESS_DOUBLE_CONSTANT 44.22 #define REGRESS_STRING_CONSTANT "Some String" #define REGRESS_Mixed_Case_Constant 4423 #define REGRESS_BOOL_CONSTANT TRUE #define REGRESS_G_GINT64_CONSTANT (G_GINT64_CONSTANT (1000)) #define REGRESS_GUINT64_CONSTANT ((guint64) - 1) #define REGRESS_GOOD_EXPR_CONSTANT (1 + 2 * (3 + 2) << 13 - 4 >> REGRESS_ATEST_ERROR_CODE2) #define REGRESS_BAD_EXPR_CONSTANT (1 + SOMETHING_UNDEFINED) typedef guint64 RegressTestTypeGUInt64; #define REGRESS_GUINT64_CONSTANTA ((RegressTestTypeGUInt64) - 1) /* structures */ typedef struct _RegressTestStructA RegressTestStructA; typedef struct _RegressTestStructB RegressTestStructB; typedef struct _RegressTestStructC RegressTestStructC; typedef struct _RegressTestStructD RegressTestStructD; typedef struct _RegressTestStructF RegressTestStructF; struct _RegressTestStructA { gint some_int; gint8 some_int8; gdouble some_double; RegressTestEnum some_enum; }; GI_TEST_EXTERN void regress_test_struct_a_clone (RegressTestStructA *a, RegressTestStructA *a_out); GI_TEST_EXTERN void regress_test_struct_a_parse (RegressTestStructA *a_out, const gchar *string); GI_TEST_EXTERN void regress_test_array_struct_out (RegressTestStructA **arr, int *len); struct _RegressTestStructB { gint8 some_int8; RegressTestStructA nested_a; }; GI_TEST_EXTERN void regress_test_struct_b_clone (RegressTestStructB *b, RegressTestStructB *b_out); /* This one has a non-basic member */ struct _RegressTestStructC { gint another_int; GObject *obj; }; /* This one has annotated fields */ /** * RegressTestStructD: * @array1: (array zero-terminated=1): * @array2: (array zero-terminated=1) (element-type RegressTestObj): * @field: (type RegressTestObj): * @list: (element-type RegressTestObj): * @garray: (element-type RegressTestObj): * @ref_count: */ struct _RegressTestStructD { RegressTestStructA **array1; gpointer *array2; gpointer field; GList *list; GPtrArray *garray; }; /* This one has an array of anonymous unions, inspired by GValue */ struct RegressTestStructE { GType some_type; union { gint v_int; guint v_uint; glong v_long; gulong v_ulong; gint64 v_int64; guint64 v_uint64; gfloat v_float; gdouble v_double; gpointer v_pointer; } some_union[2]; }; /* This one has members with const or volatile modifiers. */ struct _RegressTestStructF { volatile gint ref_count; const gint *data1; const gint *const data2; const gint *const *const data3; const gint **const *data4; volatile gint *const data5; const gint *volatile data6; volatile unsigned const char data7; }; /* plain-old-data boxed types */ typedef struct _RegressTestSimpleBoxedA RegressTestSimpleBoxedA; typedef struct _RegressTestSimpleBoxedB RegressTestSimpleBoxedB; /** * RegressTestSimpleBoxedA: (copy-func regress_test_simple_boxed_a_copy) * @some_int: * @some_int8: * @some_double: * @some_enum: * * ... */ struct _RegressTestSimpleBoxedA { gint some_int; gint8 some_int8; gdouble some_double; RegressTestEnum some_enum; }; /* Intentionally uses _get_gtype */ GI_TEST_EXTERN GType regress_test_simple_boxed_a_get_gtype (void); GI_TEST_EXTERN RegressTestSimpleBoxedA *regress_test_simple_boxed_a_copy (RegressTestSimpleBoxedA *a); GI_TEST_EXTERN gboolean regress_test_simple_boxed_a_equals (RegressTestSimpleBoxedA *a, RegressTestSimpleBoxedA *other_a); GI_TEST_EXTERN const RegressTestSimpleBoxedA *regress_test_simple_boxed_a_const_return (void); struct _RegressTestSimpleBoxedB { gint8 some_int8; RegressTestSimpleBoxedA nested_a; }; GI_TEST_EXTERN GType regress_test_simple_boxed_b_get_type (void); GI_TEST_EXTERN RegressTestSimpleBoxedB *regress_test_simple_boxed_b_copy (RegressTestSimpleBoxedB *b); /* opaque boxed */ #define REGRESS_TEST_TYPE_BOXED (regress_test_boxed_get_type ()) typedef struct _RegressTestBoxed RegressTestBoxed; typedef struct _RegressTestBoxedPrivate RegressTestBoxedPrivate; struct _RegressTestBoxed { gint8 some_int8; RegressTestSimpleBoxedA nested_a; RegressTestBoxedPrivate *priv; }; GI_TEST_EXTERN GType regress_test_boxed_get_type (void); GI_TEST_EXTERN RegressTestBoxed *regress_test_boxed_new (void); GI_TEST_EXTERN RegressTestBoxed *regress_test_boxed_new_alternative_constructor1 (int i); GI_TEST_EXTERN RegressTestBoxed *regress_test_boxed_new_alternative_constructor2 (int i, int j); GI_TEST_EXTERN RegressTestBoxed *regress_test_boxed_new_alternative_constructor3 (char *s); GI_TEST_EXTERN RegressTestBoxed *regress_test_boxed_copy (RegressTestBoxed *boxed); GI_TEST_EXTERN gboolean regress_test_boxed_equals (RegressTestBoxed *boxed, RegressTestBoxed *other); GI_TEST_EXTERN void regress_test_boxeds_not_a_method (RegressTestBoxed *boxed); GI_TEST_EXTERN void regress_test_boxeds_not_a_static (void); typedef struct _RegressTestBoxedB RegressTestBoxedB; struct _RegressTestBoxedB { gint8 some_int8; glong some_long; }; GI_TEST_EXTERN GType regress_test_boxed_b_get_type (void); GI_TEST_EXTERN RegressTestBoxedB *regress_test_boxed_b_new (gint8 some_int8, glong some_long); GI_TEST_EXTERN RegressTestBoxedB *regress_test_boxed_b_copy (RegressTestBoxedB *boxed); typedef struct _RegressTestBoxedC RegressTestBoxedC; struct _RegressTestBoxedC { guint refcount; guint another_thing; gboolean name_conflict; }; GI_TEST_EXTERN GType regress_test_boxed_c_get_type (void); GI_TEST_EXTERN RegressTestBoxedC *regress_test_boxed_c_new (void); GI_TEST_EXTERN gboolean regress_test_boxed_c_name_conflict (RegressTestBoxedC *boxed); /** * RegressTestBoxedD: (copy-func regress_test_boxed_d_copy) * (free-func regress_test_boxed_d_free) * */ typedef struct _RegressTestBoxedD RegressTestBoxedD; GI_TEST_EXTERN GType regress_test_boxed_d_get_type (void); GI_TEST_EXTERN RegressTestBoxedD *regress_test_boxed_d_new (const char *a_string, int a_int); GI_TEST_EXTERN RegressTestBoxedD *regress_test_boxed_d_copy (RegressTestBoxedD *boxed); GI_TEST_EXTERN void regress_test_boxed_d_free (RegressTestBoxedD *boxed); GI_TEST_EXTERN int regress_test_boxed_d_get_magic (RegressTestBoxedD *boxed); /* gobject */ #define REGRESS_TEST_TYPE_OBJ (regress_test_obj_get_type ()) #define REGRESS_TEST_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_TEST_TYPE_OBJ, RegressTestObj)) #define REGRESS_TEST_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_TEST_TYPE_OBJ)) #define REGRESS_TEST_OBJ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), REGRESS_TEST_TYPE_OBJ, RegressTestObjClass)) typedef struct _RegressTestObj RegressTestObj; typedef struct _RegressTestObjClass RegressTestObjClass; /** * RegressTestObj: * @bare: (allow-none): */ struct _RegressTestObj { GObject parent_instance; GObject *bare; RegressTestBoxed *boxed; GHashTable *hash_table; GList *list; gint8 some_int8; float some_float; double some_double; char *string; GType gtype; gint name_conflict; GByteArray *byte_array; /* < private > */ void (*function_ptr) (void); }; typedef void (*RegressTestExternallyDefinedCallback) (RegressTestObj *obj, int someint); struct _RegressTestObjClass { GObjectClass parent_class; int (*matrix) (RegressTestObj *obj, const char *somestr); /** * RegressTestObjClass::allow_none_vfunc: * @two: (allow-none): Another object */ void (*allow_none_vfunc) (RegressTestObj *obj, RegressTestObj *two); /** * RegressTestObjClass::static_vfunc: */ gboolean (*static_vfunc) (void); /** * RegressTestObjClass::static_vfunc_params: * @value: * @error: * * Return: (transfer none): */ RegressTestObj *(*static_vfunc_params) (gint value, GError **error); /** * RegressTestObjClass::static_vfunc_out: * @two: (out): */ void (*static_vfunc_out) (RegressTestObj **two); guint test_signal; guint test_signal_with_static_scope_arg; RegressTestExternallyDefinedCallback complex_vfunc; /* Should be replaced with simple "gpointer" and not be callback */ void (*_regress_reserved1) (void); void (*_regress_reserved2) (void); }; GI_TEST_EXTERN GType regress_test_obj_get_type (void); GI_TEST_EXTERN RegressTestObj *regress_test_obj_new (RegressTestObj *obj); GI_TEST_EXTERN RegressTestObj *regress_constructor (void); GI_TEST_EXTERN RegressTestObj *regress_test_obj_new_from_file (const char *x, GError **error); GI_TEST_EXTERN void regress_test_obj_set_bare (RegressTestObj *obj, GObject *bare); GI_TEST_EXTERN void regress_test_obj_set_string (RegressTestObj *obj, const char *str); GI_TEST_EXTERN const char *regress_test_obj_get_string (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_obj_emit_sig_with_obj (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_obj_emit_sig_with_obj_full (RegressTestObj *obj); #if GLIB_CHECK_VERSION(2, 68, 0) GI_TEST_EXTERN void regress_test_obj_emit_sig_with_gstrv_full (RegressTestObj *obj); #endif GI_TEST_EXTERN void regress_test_obj_emit_sig_with_foreign_struct (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_obj_emit_sig_with_int64 (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_obj_emit_sig_with_uint64 (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_obj_emit_sig_with_array_len_prop (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_obj_emit_sig_with_inout_int (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_obj_emit_sig_with_error (RegressTestObj *self); GI_TEST_EXTERN void regress_test_obj_emit_sig_with_null_error (RegressTestObj *self); GI_TEST_EXTERN int regress_test_obj_instance_method (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_obj_instance_method_full (RegressTestObj *obj); GI_TEST_EXTERN double regress_test_obj_static_method (int x); GI_TEST_EXTERN void regress_forced_method (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_array_fixed_out_objects (RegressTestObj ***objs); #if (defined(__GNUC__) || defined(__clang__)) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define G_GCC_STATIC static #else #define G_GCC_STATIC #endif GI_TEST_EXTERN void regress_test_array_static_in_int (int x[G_GCC_STATIC 10]); GI_TEST_EXTERN void regress_test_obj_torture_signature_0 (RegressTestObj *obj, int x, double *y, int *z, const char *foo, int *q, guint m); GI_TEST_EXTERN gboolean regress_test_obj_torture_signature_1 (RegressTestObj *obj, int x, double *y, int *z, const char *foo, int *q, guint m, GError **error); GI_TEST_EXTERN gboolean regress_test_obj_skip_return_val (RegressTestObj *obj, gint a, gint *out_b, gdouble c, gint *inout_d, gint *out_sum, gint num1, gint num2, GError **error); GI_TEST_EXTERN gboolean regress_test_obj_skip_return_val_no_out (RegressTestObj *obj, gint a, GError **error); GI_TEST_EXTERN gboolean regress_test_obj_skip_param (RegressTestObj *obj, gint a, gint *out_b, gdouble c, gint *inout_d, gint *out_sum, gint num1, gint num2, GError **error); GI_TEST_EXTERN gboolean regress_test_obj_skip_out_param (RegressTestObj *obj, gint a, gint *out_b, gdouble c, gint *inout_d, gint *out_sum, gint num1, gint num2, GError **error); GI_TEST_EXTERN gboolean regress_test_obj_skip_inout_param (RegressTestObj *obj, gint a, gint *out_b, gdouble c, gint *inout_d, gint *out_sum, gint num1, gint num2, GError **error); /* virtual */ GI_TEST_EXTERN int regress_test_obj_do_matrix (RegressTestObj *obj, const char *somestr); GI_TEST_EXTERN void regress_func_obj_null_in (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_obj_null_out (RegressTestObj **obj); GI_TEST_EXTERN void regress_func_obj_nullable_in (RegressTestObj *obj); GI_TEST_EXTERN void regress_test_obj_not_nullable_typed_gpointer_in (RegressTestObj *obj, gpointer input); GI_TEST_EXTERN void regress_test_obj_not_nullable_element_typed_gpointer_in (RegressTestObj *obj, gpointer input, guint count); GI_TEST_EXTERN void regress_test_obj_name_conflict (RegressTestObj *obj); /* inheritance */ #define REGRESS_TEST_TYPE_SUB_OBJ (regress_test_sub_obj_get_type ()) #define REGRESS_TEST_SUB_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_TEST_TYPE_SUB_OBJ, RegressTestSubObj)) #define REGRESS_TEST_IS_SUB_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_TEST_TYPE_SUB_OBJ)) #define REGRESS_TEST_SUB_OBJ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), REGRESS_TEST_TYPE_SUB_OBJ, RegressTestSubObjClass)) typedef struct _RegressTestSubObj RegressTestSubObj; typedef struct _RegressTestSubObjClass RegressTestSubObjClass; struct _RegressTestSubObj { RegressTestObj parent_instance; /*< private >*/ gint number; gboolean boolean; }; struct _RegressTestSubObjClass { RegressTestObjClass parent_class; }; GI_TEST_EXTERN GType regress_test_sub_obj_get_type (void); GI_TEST_EXTERN RegressTestObj *regress_test_sub_obj_new (void); GI_TEST_EXTERN void regress_test_sub_obj_unset_bare (RegressTestSubObj *obj); GI_TEST_EXTERN int regress_test_sub_obj_instance_method (RegressTestSubObj *obj); /* fundamental object */ #define REGRESS_TEST_TYPE_FUNDAMENTAL_OBJECT (regress_test_fundamental_object_get_type ()) #define REGRESS_TEST_IS_FUNDAMENTAL_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), REGRESS_TEST_TYPE_FUNDAMENTAL_OBJECT)) #define REGRESS_TEST_IS_FUNDAMENTAL_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), REGRESS_TEST_TYPE_FUNDAMENTAL_OBJECT)) #define REGRESS_TEST_FUNDAMENTAL_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), REGRESS_TEST_TYPE_FUNDAMENTAL_OBJECT, RegressTestFundamentalObjectClass)) #define REGRESS_TEST_FUNDAMENTAL_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), REGRESS_TEST_TYPE_FUNDAMENTAL_OBJECT, RegressTestFundamentalObject)) #define REGRESS_TEST_FUNDAMENTAL_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), REGRESS_TEST_TYPE_FUNDAMENTAL_OBJECT, RegressTestFundamentalObjectClass)) #define REGRESS_TEST_FUNDAMENTAL_OBJECT_CAST(obj) ((RegressTestFundamentalObject *) (obj)) typedef struct _RegressTestFundamentalObject RegressTestFundamentalObject; typedef struct _RegressTestFundamentalObjectClass RegressTestFundamentalObjectClass; /** * RegressTestFundamentalObjectCopyFunction: * * Returns: (transfer full): */ typedef RegressTestFundamentalObject *(*RegressTestFundamentalObjectCopyFunction) (const RegressTestFundamentalObject *obj); typedef void (*RegressTestFundamentalObjectFinalizeFunction) (RegressTestFundamentalObject *obj); struct _RegressTestFundamentalObject { GTypeInstance instance; gint refcount; guint flags; }; struct _RegressTestFundamentalObjectClass { GTypeClass type_class; RegressTestFundamentalObjectCopyFunction copy; RegressTestFundamentalObjectFinalizeFunction finalize; }; GI_TEST_EXTERN GType regress_test_fundamental_object_get_type (void); GI_TEST_EXTERN RegressTestFundamentalObject *regress_test_fundamental_object_ref (RegressTestFundamentalObject *fundamental_object); GI_TEST_EXTERN void regress_test_fundamental_object_unref (RegressTestFundamentalObject *fundamental_object); #define REGRESS_TEST_VALUE_HOLDS_FUNDAMENTAL_OBJECT(value) (G_VALUE_HOLDS (value, REGRESS_TEST_TYPE_FUNDAMENTAL_OBJECT)) GI_TEST_EXTERN void regress_test_value_set_fundamental_object (GValue *value, RegressTestFundamentalObject *fundamental_object); GI_TEST_EXTERN RegressTestFundamentalObject *regress_test_value_get_fundamental_object (const GValue *value); typedef struct _RegressTestFundamentalSubObject RegressTestFundamentalSubObject; typedef struct _RegressTestFundamentalSubObjectClass RegressTestFundamentalSubObjectClass; struct _RegressTestFundamentalSubObject { RegressTestFundamentalObject fundamental_object; char *data; }; struct _RegressTestFundamentalSubObjectClass { RegressTestFundamentalObjectClass fundamental_object_class; }; GI_TEST_EXTERN GType regress_test_fundamental_sub_object_get_type (void); struct _RegressTestFundamentalObjectNoGetSetFunc { /* This is not really an RegressTestFundamentalObject but we "inherit" * the structure from it */ /* < private > */ RegressTestFundamentalObject fundamental_object; /* < public > */ char *data; }; struct _RegressTestFundamentalObjectNoGetSetFuncClass { RegressTestFundamentalObjectClass fundamental_object_class; }; typedef struct _RegressTestFundamentalObjectNoGetSetFunc RegressTestFundamentalObjectNoGetSetFunc; typedef struct _RegressTestFundamentalObjectNoGetSetFuncClass RegressTestFundamentalObjectNoGetSetFuncClass; GI_TEST_EXTERN GType regress_test_fundamental_object_no_get_set_func_get_type (void); struct _RegressTestFundamentalSubObjectNoGetSetFunc { /* < private > */ RegressTestFundamentalObjectNoGetSetFunc fundamental_object; }; struct _RegressTestFundamentalSubObjectNoGetSetFuncClass { RegressTestFundamentalObjectNoGetSetFuncClass fundamental_object_class; }; typedef struct _RegressTestFundamentalSubObjectNoGetSetFunc RegressTestFundamentalSubObjectNoGetSetFunc; typedef struct _RegressTestFundamentalSubObjectNoGetSetFuncClass RegressTestFundamentalSubObjectNoGetSetFuncClass; GI_TEST_EXTERN GType regress_test_fundamental_sub_object_no_get_set_func_get_type (void); GI_TEST_EXTERN RegressTestFundamentalSubObject * regress_test_fundamental_sub_object_new (const char *data); GI_TEST_EXTERN RegressTestFundamentalObject * regress_test_create_fundamental_hidden_class_instance (void); GI_TEST_EXTERN RegressTestFundamentalObjectNoGetSetFunc * regress_test_fundamental_object_no_get_set_func_new (const char *data); GI_TEST_EXTERN const char * regress_test_fundamental_object_no_get_set_func_get_data (RegressTestFundamentalObjectNoGetSetFunc *fundamental); GI_TEST_EXTERN RegressTestFundamentalSubObjectNoGetSetFunc * regress_test_fundamental_sub_object_no_get_set_func_new (const char *data); GI_TEST_EXTERN void regress_test_fundamental_object_no_get_set_func_make_compatible_with_fundamental_sub_object (void); /* callback */ typedef void (*RegressTestSimpleCallback) (void); typedef void RegressTestNoPtrCallback (void); typedef int (*RegressTestCallback) (void); typedef int (*RegressTestCallbackUserData) (gpointer user_data); /** * RegressTestCallbackHashtable: * @data: (element-type utf8 gint): a hash table; will be modified */ typedef void (*RegressTestCallbackHashtable) (GHashTable *data); typedef void (*RegressTestCallbackGError) (const GError *error); /** * RegressTestCallbackOwnedGError: * @error: (transfer full): GError instance; must be freed by the callback */ typedef void (*RegressTestCallbackOwnedGError) (GError *error); /** * RegressTestCallbackFull: * @foo: the investment rate * @bar: how much money * @path: (type filename): Path to file */ typedef int (*RegressTestCallbackFull) (int foo, double bar, char *path); /** * RegressTestCallbackReturnFull: * Return value: (transfer full): */ typedef RegressTestObj *(*RegressTestCallbackReturnFull) (void); /** * RegressTestCallbackArray: * @one: (array length=one_length): * @one_length: * @two: (array length=two_length) (element-type utf8): * @two_length: */ typedef int (*RegressTestCallbackArray) (int *one, gsize one_length, const char **two, int two_length); /** * RegressTestCallbackArrayInOut: * @ints: (inout) (array length=length): * @length: (inout): */ typedef void (*RegressTestCallbackArrayInOut) (int **ints, int *length); GI_TEST_EXTERN void regress_test_simple_callback (RegressTestSimpleCallback callback); GI_TEST_EXTERN void regress_test_noptr_callback (RegressTestNoPtrCallback callback); GI_TEST_EXTERN int regress_test_callback (RegressTestCallback callback); GI_TEST_EXTERN int regress_test_multi_callback (RegressTestCallback callback); GI_TEST_EXTERN int regress_test_array_callback (RegressTestCallbackArray callback); GI_TEST_EXTERN int regress_test_array_inout_callback (RegressTestCallbackArrayInOut callback); GI_TEST_EXTERN int regress_test_callback_user_data (RegressTestCallbackUserData callback, gpointer user_data); GI_TEST_EXTERN void regress_test_callback_return_full (RegressTestCallbackReturnFull callback); GI_TEST_EXTERN int regress_test_callback_destroy_notify (RegressTestCallbackUserData callback, gpointer user_data, GDestroyNotify notify); GI_TEST_EXTERN int regress_test_callback_destroy_notify_no_user_data (RegressTestCallbackUserData callback, GDestroyNotify notify); GI_TEST_EXTERN int regress_test_callback_thaw_notifications (void); GI_TEST_EXTERN void regress_test_callback_async (RegressTestCallbackUserData callback, gpointer user_data); GI_TEST_EXTERN int regress_test_callback_thaw_async (void); GI_TEST_EXTERN void regress_test_async_ready_callback (GAsyncReadyCallback callback); GI_TEST_EXTERN void regress_test_function_async (int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GI_TEST_EXTERN int regress_test_function_thaw_async (void); GI_TEST_EXTERN gboolean regress_test_function_finish (GAsyncResult *res, GError **error); GI_TEST_EXTERN gboolean regress_test_function_sync (int io_priority); GI_TEST_EXTERN void regress_test_obj_instance_method_callback (RegressTestObj *obj, RegressTestCallback callback); GI_TEST_EXTERN void regress_test_obj_static_method_callback (RegressTestCallback callback); GI_TEST_EXTERN RegressTestObj *regress_test_obj_new_callback (RegressTestCallbackUserData callback, gpointer user_data, GDestroyNotify notify); GI_TEST_EXTERN void regress_test_obj_new_async (const char *x G_GNUC_UNUSED, GCancellable *cancellable G_GNUC_UNUSED, GAsyncReadyCallback callback G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED); GI_TEST_EXTERN int regress_test_obj_constructor_thaw_async (void); GI_TEST_EXTERN RegressTestObj *regress_test_obj_new_finish (GAsyncResult *res G_GNUC_UNUSED, GError **error G_GNUC_UNUSED); GI_TEST_EXTERN void regress_test_hash_table_callback (GHashTable *data, RegressTestCallbackHashtable callback); GI_TEST_EXTERN void regress_test_gerror_callback (RegressTestCallbackGError callback); GI_TEST_EXTERN void regress_test_null_gerror_callback (RegressTestCallbackGError callback); GI_TEST_EXTERN void regress_test_owned_gerror_callback (RegressTestCallbackOwnedGError callback); GI_TEST_EXTERN void regress_test_skip_unannotated_callback (RegressTestCallback callback); typedef struct _RegressTestInterface RegressTestInterface; /* interface */ #define REGRESS_TEST_TYPE_INTERFACE (regress_test_interface_get_type ()) #define REGRESS_TEST_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_TEST_TYPE_INTERFACE, RegressTestInterface)) #define REGRESS_TEST_IS_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_TEST_TYPE_INTERFACE)) #define REGRESS_TEST_INTERFACE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), REGRESS_TEST_TYPE_INTERFACE, RegressTestInterfaceIface)) typedef struct _RegressTestInterfaceIface RegressTestInterfaceIface; struct _RegressTestInterfaceIface { GTypeInterface base_iface; }; GI_TEST_EXTERN GType regress_test_interface_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN void regress_test_interface_emit_signal (RegressTestInterface *self); /* gobject with non-standard prefix */ #define REGRESS_TEST_TYPE_WI_802_1X (regress_test_wi_802_1x_get_type ()) #define REGRESS_TEST_WI_802_1X(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_TEST_TYPE_WI_802_1X, RegressTestWi8021x)) #define REGRESS_TEST_IS_WI_802_1X(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_TEST_TYPE_WI_802_1X)) #define REGRESS_TEST_WI_802_1X_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), REGRESS_TEST_TYPE_WI_802_1X, RegressTestWi8021xClass)) typedef struct { GObject parent_instance; gboolean testbool; } RegressTestWi8021x; typedef struct { GObjectClass parent_class; } RegressTestWi8021xClass; GI_TEST_EXTERN GType regress_test_wi_802_1x_get_type (void); GI_TEST_EXTERN RegressTestWi8021x *regress_test_wi_802_1x_new (void); GI_TEST_EXTERN gboolean regress_test_wi_802_1x_get_testbool (RegressTestWi8021x *obj); GI_TEST_EXTERN void regress_test_wi_802_1x_set_testbool (RegressTestWi8021x *obj, gboolean v); GI_TEST_EXTERN int regress_test_wi_802_1x_static_method (int x); /* floating gobject */ #define REGRESS_TEST_TYPE_FLOATING (regress_test_floating_get_type ()) #define REGRESS_TEST_FLOATING(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REGRESS_TEST_TYPE_FLOATING, RegressTestFloating)) #define REGRESS_TEST_IS_FLOATING(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REGRESS_TEST_TYPE_FLOATING)) #define REGRESS_TEST_FLOATING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), REGRESS_TEST_TYPE_FLOATING, RegressTestFloatingClass)) typedef struct { GInitiallyUnowned parent_instance; } RegressTestFloating; typedef struct { GInitiallyUnownedClass parent_class; } RegressTestFloatingClass; GI_TEST_EXTERN GType regress_test_floating_get_type (void); GI_TEST_EXTERN RegressTestFloating *regress_test_floating_new (void); /* Function signature torture tests */ GI_TEST_EXTERN void regress_test_torture_signature_0 (int x, double *y, int *z, const char *foo, int *q, guint m); GI_TEST_EXTERN gboolean regress_test_torture_signature_1 (int x, double *y, int *z, const char *foo, int *q, guint m, GError **error); GI_TEST_EXTERN void regress_test_torture_signature_2 (int x, RegressTestCallbackUserData callback, gpointer user_data, GDestroyNotify notify, double *y, int *z, const char *foo, int *q, guint m); GI_TEST_EXTERN GValue *regress_test_date_in_gvalue (void); GI_TEST_EXTERN GValue *regress_test_strv_in_gvalue (void); GI_TEST_EXTERN GValue *regress_test_null_strv_in_gvalue (void); GI_TEST_EXTERN GObject *_regress_this_is_a_private_symbol (void); GI_TEST_EXTERN void regress_test_multiline_doc_comments (void); GI_TEST_EXTERN void regress_test_nested_parameter (int a); /** * RegressSkippedStructure: (skip) * * This should be skipped, and moreover, all function which * use it should be. */ typedef struct { int x; double v; } RegressSkippedStructure; GI_TEST_EXTERN void regress_random_function_with_skipped_structure (int x, RegressSkippedStructure *foo, double v); /** * RegressIntset: * * Like telepathy-glib's TpIntset. * */ typedef struct _RegressIntset RegressIntset; /** * RegressIntsetAlias: (skip) * * Compatibility typedef, like telepathy-glib's TpIntSet * */ typedef RegressIntset RegressIntsetAlias; /** * RegressPtrArrayAlias: * * Typedef'd GPtrArray for some reason */ typedef GPtrArray RegressPtrArrayAlias; GI_TEST_EXTERN void regress_introspectable_via_alias (RegressPtrArrayAlias *data); /** * RegressVaListAlias: * * Typedef'd va_list for additional reasons */ typedef va_list RegressVaListAlias; GI_TEST_EXTERN void regress_not_introspectable_via_alias (RegressVaListAlias ok); /** * RegressAliasedTestBoxed: * * Typedef TestBoxed to test caller-allocates correctness */ typedef RegressTestBoxed RegressAliasedTestBoxed; GI_TEST_EXTERN void regress_aliased_caller_alloc (RegressAliasedTestBoxed *boxed); /* private testing */ typedef struct { gint this_is_public_before; /* < private > */ gint this_is_private; /* < public > */ gint this_is_public_after; } RegressTestPrivateStruct; typedef enum { REGRESS_TEST_PUBLIC_ENUM_BEFORE = 1 << 0, /* */ REGRESS_TEST_PRIVATE_ENUM = 1 << 1, /* */ REGRESS_TEST_PUBLIC_ENUM_AFTER = 1 << 2, } RegressTestPrivateEnum; typedef struct { gint just_int; gint array[10]; } RegressTestStructFixedArray; GI_TEST_EXTERN void regress_test_struct_fixed_array_frob (RegressTestStructFixedArray *str); typedef struct { gchar name[32]; } RegressLikeXklConfigItem; GI_TEST_EXTERN void regress_like_xkl_config_item_set_name (RegressLikeXklConfigItem *self, char const *name); #define REGRESS_UTF8_CONSTANT "const \xe2\x99\xa5 utf8" #ifdef __GNUC__ #define REGRESS_TEST_GNUC_EXTENSION_STMT(foo) (G_GNUC_EXTENSION ({ int x[10]; x[5] = 42; x[5]; })) #endif /* https://bugzilla.gnome.org/show_bug.cgi?id=662888 */ #define REGRESS_LONG_STRING_CONSTANT \ "TYPE,VALUE,ENCODING,CHARSET,LANGUAGE,DOM,INTL,POSTAL,PARCEL," \ "HOME,WORK,PREF,VOICE,FAX,MSG,CELL,PAGER,BBS,MODEM,CAR,ISDN,VIDEO," \ "AOL,APPLELINK,ATTMAIL,CIS,EWORLD,INTERNET,IBMMAIL,MCIMAIL," \ "POWERSHARE,PRODIGY,TLX,X400,GIF,CGM,WMF,BMP,MET,PMB,DIB,PICT,TIFF," \ "PDF,PS,JPEG,QTIME,MPEG,MPEG2,AVI,WAVE,AIFF,PCM,X509,PGP" GI_TEST_EXTERN void regress_has_parameter_named_attrs (int foo, gpointer attributes); typedef struct { int dummy; struct { const char *name; guint x; } attributes[32]; double dummy2; } RegressLikeGnomeKeyringPasswordSchema; /* Ensure we ignore symbols that start with _; in particular we don't * want to issue a namespace warning. */ #define _DONTSCANTHIS 1 /* https://bugzilla.gnome.org/show_bug.cgi?id=685022 */ #define REGRESS_MININT64 ((gint64) G_GINT64_CONSTANT (0x8000000000000000)) #define REGRESS_MAXUINT64 (G_GINT64_CONSTANT (0xffffffffffffffffU)) /* https://bugzilla.gnome.org/show_bug.cgi?id=698367 */ #ifndef __GI_SCANNER__ #define REGRESS_DONTSCANTHIS 1 #else #define REGRESS_GI_SCANNER_ELSE 3 #endif #ifndef BLAH #ifdef __GI_SCANNER__ #define REGRESS_GI_SCANNER_IFDEF 3 #endif #endif /* This struct is one pattern by which padding can be consumed, if * you're willing to take a hard dependency on anonymous unions. */ typedef struct { int x; union { RegressLikeGnomeKeyringPasswordSchema *a[2]; guint padding[4]; }; } RegressAnAnonymousUnion; typedef struct { int x; union { struct { RegressLikeGnomeKeyringPasswordSchema *a; RegressLikeXklConfigItem *b; }; guint padding[4]; }; } RegressAnonymousUnionAndStruct; GI_TEST_EXTERN GVariant *regress_get_variant (void); typedef struct _RegressTestReferenceCounters RegressTestReferenceCounters; struct _RegressTestReferenceCounters { grefcount refcount; gatomicrefcount atomicrefcount; }; GI_TEST_EXTERN void regress_test_array_struct_out_none (RegressTestStructA **arr, gsize *len); GI_TEST_EXTERN void regress_test_array_struct_out_container (RegressTestStructA **arr, gsize *len); GI_TEST_EXTERN void regress_test_array_struct_out_full_fixed (RegressTestStructA **arr); GI_TEST_EXTERN void regress_test_array_struct_out_caller_alloc (RegressTestStructA *arr, gsize len); GI_TEST_EXTERN void regress_test_array_struct_in_full (RegressTestStructA *arr, gsize len); GI_TEST_EXTERN void regress_test_array_struct_in_none (RegressTestStructA *arr, gsize len); GI_TEST_EXTERN void regress_test_obj_function_async (RegressTestObj *self, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GI_TEST_EXTERN void regress_test_obj_function2 (RegressTestObj *self, int io_priority, GCancellable *cancellable, RegressTestCallbackUserData test_cb, gpointer test_data, GDestroyNotify test_destroy, GAsyncReadyCallback callback, gpointer user_data); GI_TEST_EXTERN gboolean regress_test_obj_function2_finish (RegressTestObj *self, GAsyncResult *result, gboolean *match, GObject **some_obj, GError **error); GI_TEST_EXTERN gboolean regress_test_obj_function2_sync (RegressTestObj *self, int io_priority); GI_TEST_EXTERN int regress_test_obj_function_thaw_async (RegressTestObj *self); GI_TEST_EXTERN gboolean regress_test_obj_function_finish (RegressTestObj *self, GAsyncResult *res, GError **error); GI_TEST_EXTERN gboolean regress_test_obj_function_sync (RegressTestObj *self, int io_priority); static inline gboolean regress_test_inline_function (gboolean foo); /* * regress_test_inline_function: * * An inline function that should be exposed as such */ static inline gboolean regress_test_inline_function (gboolean foo) { return foo; } static inline gboolean regress_test_obj_inline_method (RegressTestObj *obj, gboolean foo); /* * regress_test_obj_inline_method: * * An inline function that should be exposed as such */ static inline gboolean regress_test_obj_inline_method (RegressTestObj *obj G_GNUC_UNUSED, gboolean foo) { return foo; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/regressextra.c0000664000000000000000000003233615056773103025254 0ustar00rootroot/* SPDX-License-Identifier: LGPL-2.1-or-later SPDX-FileCopyrightText: 2018 PyGObject contributors */ #include #ifndef GI_TEST_DISABLE_CAIRO #include #endif /* GI_TEST_DISABLE_CAIRO */ #include #include "regress.h" #include "regressextra.h" struct _RegressTestBoxedCWrapper { RegressTestBoxedC *cptr; }; RegressTestBoxedCWrapper * regress_test_boxed_c_wrapper_new (void) { RegressTestBoxedCWrapper *boxed; boxed = g_slice_new (RegressTestBoxedCWrapper); boxed->cptr = regress_test_boxed_c_new (); return boxed; } RegressTestBoxedCWrapper * regress_test_boxed_c_wrapper_copy (RegressTestBoxedCWrapper *self) { RegressTestBoxedCWrapper *ret_boxed; ret_boxed = g_slice_new (RegressTestBoxedCWrapper); ret_boxed->cptr = g_boxed_copy (regress_test_boxed_c_get_type (), self->cptr); return ret_boxed; } static void regress_test_boxed_c_wrapper_free (RegressTestBoxedCWrapper *boxed) { g_boxed_free (regress_test_boxed_c_get_type (), boxed->cptr); g_slice_free (RegressTestBoxedCWrapper, boxed); } G_DEFINE_BOXED_TYPE (RegressTestBoxedCWrapper, regress_test_boxed_c_wrapper, regress_test_boxed_c_wrapper_copy, regress_test_boxed_c_wrapper_free); /** * regress_test_boxed_c_wrapper_get * @self: a #RegressTestBoxedCWrapper objects * * Returns: (transfer none): associated #RegressTestBoxedC **/ RegressTestBoxedC * regress_test_boxed_c_wrapper_get (RegressTestBoxedCWrapper *self) { return self->cptr; } /** * regress_test_array_of_non_utf8_strings * Returns: (transfer full) (allow-none) (array zero-terminated=1): Array of strings */ gchar ** regress_test_array_of_non_utf8_strings (void) { char **ret = g_new (char *, 2); ret[0] = g_strdup ("Andr\351 Lur\347at"); ret[1] = NULL; return ret; } /** * regress_test_array_fixed_boxed_none_out * @objs: (out) (array fixed-size=2) (transfer none): An array of #RegressTestBoxedC **/ void regress_test_array_fixed_boxed_none_out (RegressTestBoxedC ***objs) { static RegressTestBoxedC **arr; if (arr == NULL) { arr = g_new0 (RegressTestBoxedC *, 3); arr[0] = regress_test_boxed_c_new (); arr[1] = regress_test_boxed_c_new (); } *objs = arr; } /** * regress_test_gvalue_out_boxed: * @value: (out) (transfer full): the output gvalue * @init: (in): the initialisation value **/ void regress_test_gvalue_out_boxed (GValue *value, int init) { RegressTestBoxed rtb; GValue v = G_VALUE_INIT; memset (&rtb, 0, sizeof (rtb)); rtb.some_int8 = init; g_value_init (&v, REGRESS_TEST_TYPE_BOXED); g_value_set_boxed (&v, &rtb); *value = v; } /** * regress_test_glist_boxed_none_return * Return value: (element-type RegressTestBoxedC) (transfer none): **/ GList * regress_test_glist_boxed_none_return (guint count) { static GList *list = NULL; if (!list) { while (count > 0) { list = g_list_prepend (list, regress_test_boxed_c_new ()); count--; } } return list; } /** * regress_test_glist_boxed_full_return * Return value: (element-type RegressTestBoxedC) (transfer full): **/ GList * regress_test_glist_boxed_full_return (guint count) { GList *list = NULL; while (count > 0) { list = g_list_prepend (list, regress_test_boxed_c_new ()); count--; } return list; } /** * regress_test_array_of_fundamental_objects_in * @list: (array length=len) (element-type RegressTestFundamentalObject): An array of #RegressTestFundamentalObject * @len: length of the list **/ gboolean regress_test_array_of_fundamental_objects_in (RegressTestFundamentalObject **list, gsize len) { gsize i; for (i = 0; i < len; i++) { if (!REGRESS_TEST_IS_FUNDAMENTAL_OBJECT (list[i])) { return FALSE; } } return TRUE; } /** * regress_test_array_of_fundamental_objects_out * @len: (out): length of the list * Returns: (array length=len) (transfer full): An array of #RegressTestFundamentalObject **/ RegressTestFundamentalObject ** regress_test_array_of_fundamental_objects_out (gsize *len) { RegressTestFundamentalObject **objs; int i; objs = g_new (RegressTestFundamentalObject *, 2); for (i = 0; i < 2; i++) { objs[i] = (RegressTestFundamentalObject *) regress_test_fundamental_sub_object_new ("foo"); } *len = 2; return objs; } /** * regress_test_fundamental_argument_in * @obj: (transfer full): A #RegressTestFundamentalObject **/ gboolean regress_test_fundamental_argument_in (RegressTestFundamentalObject *obj) { gboolean retval = REGRESS_TEST_IS_FUNDAMENTAL_OBJECT (obj); regress_test_fundamental_object_unref(obj); return retval; } /** * regress_test_fundamental_argument_out * @obj: (transfer none): A #RegressTestFundamentalObject * Returns: (transfer none): Same #RegressTestFundamentalObject **/ RegressTestFundamentalObject * regress_test_fundamental_argument_out (RegressTestFundamentalObject *obj) { return obj; } #ifndef GI_TEST_DISABLE_CAIRO /** * regress_test_cairo_context_none_return: * * Returns: (transfer none): */ cairo_t * regress_test_cairo_context_none_return (void) { static cairo_t *cr; if (cr == NULL) { cairo_surface_t *surface; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 10, 10); cr = cairo_create (surface); cairo_surface_destroy (surface); } return cr; } /** * regress_test_cairo_context_full_in: * @context: (transfer full): */ void regress_test_cairo_context_full_in (cairo_t *context) { cairo_destroy (context); } /** * regress_test_cairo_path_full_return: * * Returns: (transfer full): */ cairo_path_t * regress_test_cairo_path_full_return (void) { cairo_t *cr = regress_test_cairo_context_none_return (); return cairo_copy_path (cr); } /** * regress_test_cairo_path_none_in: * @path: (transfer none): */ void regress_test_cairo_path_none_in (cairo_path_t *path) { cairo_t *cr = regress_test_cairo_context_full_return (); cairo_append_path (cr, path); g_assert (cairo_status (cr) == CAIRO_STATUS_SUCCESS); cairo_destroy (cr); } /** * regress_test_cairo_path_full_in_full_return: * @path: (transfer full): * * Returns: (transfer full): */ cairo_path_t * regress_test_cairo_path_full_in_full_return (cairo_path_t *path) { return path; } /** * regress_test_cairo_pattern_full_in: * @pattern: (transfer full): */ void regress_test_cairo_pattern_full_in (cairo_pattern_t *pattern) { cairo_pattern_destroy (pattern); } /** * regress_test_cairo_pattern_none_in: * @pattern: (transfer none): */ void regress_test_cairo_pattern_none_in (cairo_pattern_t *pattern) { cairo_t *cr = regress_test_cairo_context_full_return (); cairo_set_source (cr, pattern); g_assert (cairo_status (cr) == CAIRO_STATUS_SUCCESS); cairo_destroy (cr); } /** * regress_test_cairo_pattern_none_return: * * Returns: (transfer none): */ cairo_pattern_t * regress_test_cairo_pattern_none_return (void) { static cairo_pattern_t *pattern; if (pattern == NULL) { pattern = cairo_pattern_create_rgb (0.1, 0.2, 0.3); } return pattern; } /** * regress_test_cairo_pattern_full_return: * * Returns: (transfer full): */ cairo_pattern_t * regress_test_cairo_pattern_full_return (void) { cairo_pattern_t *pattern = cairo_pattern_create_rgb (0.5, 0.6, 0.7); return pattern; } /** * regress_test_cairo_region_full_in: * @region: (transfer full): */ void regress_test_cairo_region_full_in (cairo_region_t *region) { cairo_region_destroy (region); } /** * regress_test_cairo_surface_full_in: * @surface: (transfer full): */ void regress_test_cairo_surface_full_in (cairo_surface_t *surface) { g_assert (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_ARGB32); g_assert (cairo_image_surface_get_width (surface) == 10); g_assert (cairo_image_surface_get_height (surface) == 10); cairo_surface_destroy (surface); } /** * regress_test_cairo_font_options_full_return: * * Returns: (transfer full): */ cairo_font_options_t * regress_test_cairo_font_options_full_return (void) { return cairo_font_options_create (); } /** * regress_test_cairo_font_options_none_return: * * Returns: (transfer none): */ cairo_font_options_t * regress_test_cairo_font_options_none_return (void) { static cairo_font_options_t *options; if (options == NULL) options = cairo_font_options_create (); return options; } /** * regress_test_cairo_font_options_full_in: * @options: (transfer full): */ void regress_test_cairo_font_options_full_in (cairo_font_options_t *options) { cairo_font_options_destroy (options); } /** * regress_test_cairo_font_options_none_in: * @options: (transfer none): */ void regress_test_cairo_font_options_none_in (cairo_font_options_t *options G_GNUC_UNUSED) { } /** * regress_test_cairo_font_face_full_return: * @cairo: (transfer none): * * Returns: (transfer full): */ cairo_font_face_t * regress_test_cairo_font_face_full_return (cairo_t *cairo) { cairo_font_face_t *font_face = cairo_get_font_face (cairo); return cairo_font_face_reference (font_face); } /** * regress_test_cairo_scaled_font_full_return: * @cairo: (transfer none): * * Returns: (transfer full): */ cairo_scaled_font_t * regress_test_cairo_scaled_font_full_return (cairo_t *cairo) { cairo_scaled_font_t *scaled_font = cairo_get_scaled_font (cairo); return cairo_scaled_font_reference (scaled_font); } /** * regress_test_cairo_matrix_none_in: * @matrix: (transfer none): */ void regress_test_cairo_matrix_none_in (const cairo_matrix_t *matrix) { cairo_matrix_t m = *matrix; g_assert (m.x0 == 0); g_assert (m.y0 == 0); g_assert (m.xx == 1); g_assert (m.xy == 0); g_assert (m.yy == 1); g_assert (m.yx == 0); } /** * regress_test_cairo_matrix_none_return: * Returns: (transfer none): */ cairo_matrix_t * regress_test_cairo_matrix_none_return (void) { static cairo_matrix_t matrix; cairo_matrix_init_identity (&matrix); return &matrix; } /** * regress_test_cairo_matrix_out_caller_allocates: * @matrix: (out): */ void regress_test_cairo_matrix_out_caller_allocates (cairo_matrix_t *matrix) { cairo_matrix_t m; cairo_matrix_init_identity (&m); *matrix = m; } #endif G_DEFINE_TYPE (RegressTestAction, regress_test_action, G_TYPE_INITIALLY_UNOWNED) enum { SIGNAL_0, ACTION_SIGNAL, ACTION2_SIGNAL, LAST_SIGNAL }; static guint regress_test_action_signals[LAST_SIGNAL] = { 0 }; static RegressTestAction * regress_test_action_do_action (RegressTestAction *self G_GNUC_UNUSED) { RegressTestAction *ret = g_object_new (regress_test_action_get_type (), NULL); return ret; } static RegressTestAction * regress_test_action_do_action2 (RegressTestAction *self G_GNUC_UNUSED) { return NULL; } static void regress_test_action_init (RegressTestAction *self G_GNUC_UNUSED) { } static void regress_test_action_class_init (RegressTestActionClass *klass) { /** * RegressTestAction::action: * * An action signal. * * Returns: (transfer full): another #RegressTestAction */ regress_test_action_signals[ACTION_SIGNAL] = g_signal_new_class_handler ("action", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_CALLBACK (regress_test_action_do_action), NULL, NULL, NULL, regress_test_action_get_type (), 0); /** * RegressTestAction::action2: * * Another action signal. * * Returns: (transfer full): another #RegressTestAction */ regress_test_action_signals[ACTION2_SIGNAL] = g_signal_new_class_handler ("action2", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_CALLBACK (regress_test_action_do_action2), NULL, NULL, NULL, regress_test_action_get_type (), 0); } /* * RegressBitmask * * Mimic a primitive, fundamental type. */ static void regress_value_init_bitmask (GValue *value) { value->data[0].v_uint64 = 0; } static void regress_value_copy_bitmask (const GValue *src_value, GValue *dest_value) { dest_value->data[0].v_uint64 = src_value->data[0].v_uint64; } static void _value_transform_uint64_bitmask (const GValue *src_value, GValue *dest_value) { dest_value->data[0].v_uint64 = src_value->data[0].v_uint64; } static void _value_transform_bitmask_uint64 (const GValue *src_value, GValue *dest_value) { dest_value->data[0].v_uint64 = src_value->data[0].v_uint64; } static const GTypeValueTable _regress_bitmask_value_table = { regress_value_init_bitmask, NULL, regress_value_copy_bitmask, NULL, (char *) NULL, NULL, (char *) NULL, NULL }; GType regress_bitmask_get_type (void) { static GType regress_bitmask_type = 0; if (g_once_init_enter (®ress_bitmask_type)) { GTypeInfo _info = { 0, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, &_regress_bitmask_value_table }; GTypeFundamentalInfo _finfo = { 0 }; GType _type = g_type_register_fundamental ( g_type_fundamental_next (), "RegressBitmask", &_info, &_finfo, 0); g_once_init_leave (®ress_bitmask_type, _type); g_value_register_transform_func ( REGRESS_TYPE_BITMASK, G_TYPE_UINT64, _value_transform_bitmask_uint64); g_value_register_transform_func ( G_TYPE_UINT64, REGRESS_TYPE_BITMASK, _value_transform_uint64_bitmask); } return regress_bitmask_type; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/regressextra.h0000664000000000000000000000752615056773103025264 0ustar00rootroot/* SPDX-License-Identifier: LGPL-2.1-or-later SPDX-FileCopyrightText: 2018 PyGObject contributors */ #pragma once #ifndef GI_TEST_DISABLE_CAIRO #include #endif /* GI_TEST_DISABLE_CAIRO */ #include #include #include "gitestmacros.h" #include "regress.h" typedef struct _RegressTestBoxedCWrapper RegressTestBoxedCWrapper; GI_TEST_EXTERN GType regress_test_boxed_c_wrapper_get_type (void); GI_TEST_EXTERN RegressTestBoxedCWrapper *regress_test_boxed_c_wrapper_new (void); GI_TEST_EXTERN RegressTestBoxedCWrapper *regress_test_boxed_c_wrapper_copy (RegressTestBoxedCWrapper *self); GI_TEST_EXTERN RegressTestBoxedC *regress_test_boxed_c_wrapper_get (RegressTestBoxedCWrapper *self); GI_TEST_EXTERN gchar **regress_test_array_of_non_utf8_strings (void); GI_TEST_EXTERN void regress_test_array_fixed_boxed_none_out (RegressTestBoxedC ***objs); GI_TEST_EXTERN void regress_test_gvalue_out_boxed (GValue *value, int init); GI_TEST_EXTERN GList *regress_test_glist_boxed_none_return (guint count); GI_TEST_EXTERN GList *regress_test_glist_boxed_full_return (guint count); GI_TEST_EXTERN gboolean regress_test_array_of_fundamental_objects_in (RegressTestFundamentalObject **list, gsize len); GI_TEST_EXTERN RegressTestFundamentalObject **regress_test_array_of_fundamental_objects_out (gsize *len); GI_TEST_EXTERN gboolean regress_test_fundamental_argument_in (RegressTestFundamentalObject *obj); GI_TEST_EXTERN RegressTestFundamentalObject *regress_test_fundamental_argument_out (RegressTestFundamentalObject *obj); #ifndef GI_TEST_DISABLE_CAIRO GI_TEST_EXTERN cairo_t *regress_test_cairo_context_none_return (void); GI_TEST_EXTERN void regress_test_cairo_context_full_in (cairo_t *context); GI_TEST_EXTERN cairo_path_t *regress_test_cairo_path_full_return (void); GI_TEST_EXTERN void regress_test_cairo_path_none_in (cairo_path_t *path); GI_TEST_EXTERN cairo_path_t *regress_test_cairo_path_full_in_full_return (cairo_path_t *path); GI_TEST_EXTERN void regress_test_cairo_pattern_full_in (cairo_pattern_t *pattern); GI_TEST_EXTERN void regress_test_cairo_pattern_none_in (cairo_pattern_t *pattern); GI_TEST_EXTERN cairo_pattern_t *regress_test_cairo_pattern_none_return (void); GI_TEST_EXTERN cairo_pattern_t *regress_test_cairo_pattern_full_return (void); GI_TEST_EXTERN cairo_font_options_t *regress_test_cairo_font_options_full_return (void); GI_TEST_EXTERN cairo_font_options_t *regress_test_cairo_font_options_none_return (void); GI_TEST_EXTERN void regress_test_cairo_font_options_full_in (cairo_font_options_t *options); GI_TEST_EXTERN void regress_test_cairo_font_options_none_in (cairo_font_options_t *options); GI_TEST_EXTERN cairo_font_face_t *regress_test_cairo_font_face_full_return (cairo_t *cairo); GI_TEST_EXTERN cairo_scaled_font_t *regress_test_cairo_scaled_font_full_return (cairo_t *cairo); GI_TEST_EXTERN void regress_test_cairo_region_full_in (cairo_region_t *region); GI_TEST_EXTERN void regress_test_cairo_surface_full_in (cairo_surface_t *surface); GI_TEST_EXTERN void regress_test_cairo_matrix_none_in (const cairo_matrix_t *matrix); GI_TEST_EXTERN cairo_matrix_t *regress_test_cairo_matrix_none_return (void); GI_TEST_EXTERN void regress_test_cairo_matrix_out_caller_allocates (cairo_matrix_t *matrix); #endif /* RegressTestAction */ typedef struct { GInitiallyUnowned parent; } RegressTestAction; typedef struct { GInitiallyUnownedClass parent_class; } RegressTestActionClass; GI_TEST_EXTERN GType regress_test_action_get_type (void); /** * RegressBitmask: * * A fundamental type that describes a 64-bit bitmask. * * This type resembles GStreamer's Bitmask type. */ /** * REGRESS_TYPE_BITMASK: * * a #GValue type that represents a 64-bit bitmask. * * Returns: the #GType of RegressBitmask (which is not explicitly typed) */ #define REGRESS_TYPE_BITMASK (regress_bitmask_get_type ()) GI_TEST_EXTERN GType regress_bitmask_get_type (void); ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/tools/iwyu.imp0000664000000000000000000000065715056773103025237 0ustar00rootroot# SPDX-License-Identifier: MIT # SPDX-FileCopyrightText: 2024 Philip Chimento [ {"include": ["", "private", "", "public"]}, {"include": ["\"gobject/gclosure.h\"", "private", "", "public"]}, {"include": ["\"gobject/glib-types.h\"", "private", "", "public"]}, {"include": ["\"gobject/gmarshal.h\"", "private", "", "public"]}, ] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/tools/run_clang_format.sh0000775000000000000000000000033115056773103027377 0ustar00rootroot#!/bin/bash # SPDX-License-Identifier: MIT # SPDX-FileCopyrightText: 2024 Philip Chimento CLANG_FORMAT=${CLANG_FORMAT:-clang-format} for file in *.c *.h; do $CLANG_FORMAT -i $file done ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/tools/run_iwyu.sh0000775000000000000000000000047415056773103025750 0ustar00rootroot#!/bin/bash # SPDX-License-Identifier: MIT # SPDX-FileCopyrightText: 2024 Philip Chimento IWYU=${IWYU:-include-what-you-use} CFLAGS=$(pkg-config --cflags glib-2.0 gobject-2.0 gio-2.0 cairo-gobject) for file in *.c; do $IWYU -Xiwyu --mapping_file=tools/iwyu.imp -xc $CFLAGS $file done ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/utility.c0000664000000000000000000000275315056773103024241 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2008 Johan Dahlin SPDX-FileCopyrightText: 2009 Andreas Rottmann */ #include "utility.h" G_DEFINE_TYPE (UtilityObject, utility_object, G_TYPE_OBJECT); /** * UtilityBuffer: * @data: (type gpointer): the data * **/ static void utility_object_finalize (GObject *gobj) { UtilityObject *self = UTILITY_OBJECT(gobj); if (self->destroy_notify) self->destroy_notify(self->user_data); G_OBJECT_CLASS(utility_object_parent_class)->finalize(gobj); } static void utility_object_class_init (UtilityObjectClass *klass G_GNUC_UNUSED) { G_OBJECT_CLASS(klass)->finalize = utility_object_finalize; } static void utility_object_init (UtilityObject *object G_GNUC_UNUSED) { } /** * utility_object_watch_dir: * @object: * @path: * @func: (destroy destroy): * @user_data: * @destroy: */ void utility_object_watch_dir (UtilityObject *object, const char *path G_GNUC_UNUSED, UtilityFileFunc func G_GNUC_UNUSED, gpointer user_data, GDestroyNotify destroy) { object->user_data = user_data; object->destroy_notify = destroy; } /** * utility_dir_foreach: * @path: * @func: (scope call): * @user_data: * */ void utility_dir_foreach (const char *path G_GNUC_UNUSED, UtilityFileFunc func G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) { } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/utility.h0000664000000000000000000000441215056773103024240 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2008 Colin Walters SPDX-FileCopyrightText: 2008 Johan Dahlin SPDX-FileCopyrightText: 2008-2009 Andreas Rottmann */ #pragma once #include #include #include "gitestmacros.h" #define UTILITY_TYPE_OBJECT (utility_object_get_type ()) #define UTILITY_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), UTILITY_TYPE_OBJECT, UtilityObject)) #define UTILITY_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), UTILITY_TYPE_OBJECT)) typedef struct _UtilityObject UtilityObject; typedef struct _UtilityObjectClass UtilityObjectClass; struct _UtilityObject { GObject parent_instance; /*< private >*/ void *user_data; GDestroyNotify destroy_notify; }; struct _UtilityObjectClass { GObjectClass parent_class; }; /* This one is similar to Pango.Glyph */ typedef guint32 UtilityGlyph; typedef struct { int tag; union { gpointer v_pointer; double v_real; long v_integer; } value; } UtilityTaggedValue; typedef union { guint8 value; struct { guint8 first_nibble : 4; guint8 second_nibble : 4; } parts; } UtilityByte; /* This one is similiar to Soup.Buffer */ typedef struct { const char *data; gsize length; } UtilityBuffer; typedef void (*UtilityFileFunc) (const char *path, gpointer user_data); GI_TEST_EXTERN GType utility_object_get_type (void) G_GNUC_CONST; GI_TEST_EXTERN void utility_object_watch_dir (UtilityObject *object, const char *path, UtilityFileFunc func, gpointer user_data, GDestroyNotify destroy); typedef enum { UTILITY_ENUM_A, UTILITY_ENUM_B, UTILITY_ENUM_C } UtilityEnumType; /* The shift operators here should imply bitfield */ typedef enum { UTILITY_FLAG_A = 1 << 0, UTILITY_FLAG_B = 1 << 1, UTILITY_FLAG_C = 1 << 2 } UtilityFlagType; typedef struct { int field; guint bitfield1 : 3; guint bitfield2 : 2; guint8 data[16]; } UtilityStruct; typedef union { char *pointer; glong integer; double real; } UtilityUnion; GI_TEST_EXTERN void utility_dir_foreach (const char *path, UtilityFileFunc func, gpointer user_data); ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/warnlib.c0000664000000000000000000000212215056773103024162 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2012 Colin Walters SPDX-FileCopyrightText: 2013 Dieter Verfaillie */ #include "warnlib.h" GQuark warnlib_unpaired_error_quark (void) { return g_quark_from_static_string ("warnlib-unpaired-error"); } gboolean warnlib_throw_unpaired (GError **error) { g_set_error_literal (error, warnlib_unpaired_error_quark (), 0, "Unpaired error"); return FALSE; } typedef WarnLibWhateverIface WarnLibWhateverInterface; G_DEFINE_INTERFACE (WarnLibWhatever, warnlib_whatever, G_TYPE_OBJECT) static void warnlib_whatever_default_init (WarnLibWhateverIface *iface G_GNUC_UNUSED) { } void warnlib_whatever_do_moo (WarnLibWhatever *self, int x, gpointer y) { WARNLIB_WHATEVER_GET_IFACE (self)->do_moo (self, x, y); } /** * warnlib_whatever_do_boo: * @self: a WarnLibWhatever * @x: x parameter * @y: y parameter * * Does boo. */ void warnlib_whatever_do_boo (WarnLibWhatever *self, int x, gpointer y) { WARNLIB_WHATEVER_GET_IFACE (self)->do_boo (self, x, y); } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1757148739.0 pygobject-3.54.5/subprojects/gobject-introspection-tests/warnlib.h0000664000000000000000000000300115056773103024164 0ustar00rootroot/* SPDX-License-Identifier: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT SPDX-FileCopyrightText: 2012 Colin Walters SPDX-FileCopyrightText: 2013 Dieter Verfaillie */ #pragma once #include #include #include "gitestmacros.h" #define WARNLIB_UNPAIRED_ERROR (warnlib_unpaired_error_quark ()) GI_TEST_EXTERN GQuark warnlib_unpaired_error_quark (void); GI_TEST_EXTERN gboolean warnlib_throw_unpaired (GError **error); /* interface */ #define WARNLIB_TYPE_WHATEVER (warnlib_whatever_get_type ()) #define WARNLIB_WHATEVER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), WARNLIB_TYPE_WHATEVER, WarnLibWhatever)) #define WARNLIB_IS_WHATEVER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), WARNLIB_TYPE_WHATEVER)) #define WARNLIB_WHATEVER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), WARNLIB_TYPE_WHATEVER, WarnLibWhateverIface)) typedef struct _WarnLibWhateverIface WarnLibWhateverIface; typedef struct _WarnLibWhatever WarnLibWhatever; struct _WarnLibWhateverIface { GTypeInterface parent_iface; /* virtual table */ /* explicitly test un-named parameters */ void (*do_moo) (WarnLibWhatever *self, int, gpointer); void (*do_boo) (WarnLibWhatever *self, int x, gpointer y); }; GI_TEST_EXTERN void warnlib_whatever_do_moo (WarnLibWhatever *self, int, gpointer); GI_TEST_EXTERN void warnlib_whatever_do_boo (WarnLibWhatever *self, int, gpointer); GI_TEST_EXTERN GType warnlib_whatever_get_type (void) G_GNUC_CONST; typedef enum { WARNLIB_1ST = 1, } WarnLibNumericEnum; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/subprojects/gobject-introspection-tests.wrap0000664000000000000000000000036215074673150023260 0ustar00rootroot[wrap-git] directory=gobject-introspection-tests url=https://gitlab.gnome.org/GNOME/gobject-introspection-tests.git push-url=git@gitlab.gnome.org:GNOME/gobject-introspection-tests.git revision=ddd662bb9cdc29f047b239789fb7e56e68fa66bb depth=1 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/subprojects/gobject-introspection.wrap0000664000000000000000000000032015074673150022112 0ustar00rootroot[wrap-git] directory=gobject-introspection url=https://gitlab.gnome.org/GNOME/gobject-introspection.git push-url=git@gitlab.gnome.org:GNOME/gobject-introspection.git revision=main depth=1 clone-recursive=true././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/subprojects/libffi.wrap0000664000000000000000000000022315074673150017034 0ustar00rootroot[wrap-git] directory=libffi url=https://gitlab.freedesktop.org/gstreamer/meson-ports/libffi.git revision=meson depth=1 [provide] libffi = ffi_dep ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/subprojects/packagefiles/pythoncapi-compat-dist.py0000664000000000000000000000040715074673150024302 0ustar00rootroot# Remove the .git folder from pythoncapi-compat # Workaround for https://github.com/mesonbuild/meson/issues/11750 import shutil import os from pathlib import Path shutil.rmtree(Path(os.environ["MESON_DIST_ROOT"]) / "subprojects" / "pythoncapi-compat" / ".git") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/subprojects/packagefiles/pythoncapi-compat-meson.diff0000664000000000000000000000032415074673150024736 0ustar00rootrootdiff --git a/meson.build b/meson.build new file mode 100644 index 0000000..7c5f9fc --- /dev/null +++ b/meson.build @@ -0,0 +1,6 @@ +project( + 'pythoncapi-compat', + 'c' +) + +incdir = include_directories('.') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/subprojects/pycairo.wrap0000664000000000000000000000014015074673150017245 0ustar00rootroot[wrap-git] directory=pycairo url=https://github.com/pygobject/pycairo.git revision=main depth=1 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3638036 pygobject-3.54.5/subprojects/pythoncapi-compat/.github/workflows/build.yml0000644000000000000000000000720315074677100025566 0ustar00rootrootname: Build on: push: branches: [main] pull_request: branches: [main] jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: # Available OS Images: # https://github.com/actions/runner-images/#available-images # # Allow Python pre-releases: # https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md#allow-pre-releases # See "allow-prereleases: true" below. os: [ubuntu-latest] python: # Python versions (CPython): # https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" - "3.13" # CPython 3.14 final is scheduled for October 2025: # https://peps.python.org/pep-0719/ - "3.14" # PyPy versions: # - https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md # - https://downloads.python.org/pypy/ # - Only versions listed in this JSON are supported: # https://downloads.python.org/pypy/versions.json - "pypy2.7" - "pypy3.6" - "pypy3.7" - "pypy3.8" - "pypy3.9" - "pypy3.10" # Old PyPy versions # See https://foss.heptapod.net/pypy/pypy/-/issues/3991 - "pypy2.7-v7.3.2" - "pypy3.6-v7.3.2" - "pypy3.7-v7.3.2" include: # Windows - os: windows-latest python: "3.6" - os: windows-latest python: "3.7" - os: windows-latest python: "3.8" - os: windows-latest python: "3.9" - os: windows-latest python: "3.10" - os: windows-latest python: "3.11" - os: windows-latest python: "3.12" - os: windows-latest python: "3.13" # macOS # Python 3.8 is the oldest version available on macOS/arm64. - os: macos-latest python: "3.8" - os: macos-latest python: "3.9" - os: macos-latest python: "3.10" - os: macos-latest python: "3.11" - os: macos-latest python: "3.12" - os: macos-latest python: "3.13" # Ubuntu: test deadsnakes Python versions which are not supported by # GHA python-versions. - os: ubuntu-20.04 python: "3.6" - os: ubuntu-22.04 python: "3.7" steps: # https://github.com/actions/checkout - uses: actions/checkout@v4 - name: Setup Python # https://github.com/actions/setup-python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} allow-prereleases: true - name: Install setuptools run: python -m pip install setuptools - name: Display the Python version run: python -VV - name: Run tests run: python runtests.py --current --verbose test_python27: # Get Python 2.7 from Ubuntu 22.04. # # Python 2.7 was removed from GHA setup-python in June 2023: # https://github.com/actions/setup-python/issues/672 name: 'Test Python 2.7' runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: Install Python 2.7 run: | sudo apt-get update sudo apt-get -yq install python2.7 python2.7-dev - name: Display the Python version run: python2.7 -VV - name: Run tests run: python2.7 runtests.py --current --verbose ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3638036 pygobject-3.54.5/subprojects/pythoncapi-compat/.gitignore0000644000000000000000000000005715074677100022337 0ustar00rootrootbuild *.swp tests/build/ *.py[cod] __pycache__ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3705726 pygobject-3.54.5/subprojects/pythoncapi-compat/.meson-subproject-wrap-hash.txt0000644000000000000000000000010115074677100026343 0ustar00rootroot302da2eeacc8c8994aa599981ffa9faadf03ddcb8b323d1291898fd4ed10b2fc ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3638036 pygobject-3.54.5/subprojects/pythoncapi-compat/.readthedocs.yaml0000644000000000000000000000033215074677100023572 0ustar00rootroot# Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details version: 2 build: os: ubuntu-22.04 tools: python: "3.12" sphinx: configuration: docs/conf.py ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3638036 pygobject-3.54.5/subprojects/pythoncapi-compat/CODE_OF_CONDUCT.md0000644000000000000000000000116515074677100023147 0ustar00rootroot# Code of Conduct Please note that all interactions on [Python Software Foundation](https://www.python.org/psf-landing/)-supported infrastructure is [covered](https://www.python.org/psf/records/board/minutes/2014-01-06/#management-of-the-psfs-web-properties) by the [PSF Code of Conduct](https://www.python.org/psf/codeofconduct/), which includes all the infrastructure used in the development of Python itself (e.g. mailing lists, issue trackers, GitHub, etc.). In general, this means that everyone is expected to be **open**, **considerate**, and **respectful** of others no matter what their position is within the project. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3638036 pygobject-3.54.5/subprojects/pythoncapi-compat/COPYING0000644000000000000000000000126215074677100021401 0ustar00rootrootBSD Zero Clause License Copyright Contributors to the pythoncapi_compat project. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3638036 pygobject-3.54.5/subprojects/pythoncapi-compat/README.rst0000644000000000000000000000324115074677100022034 0ustar00rootroot++++++++++++++++++++++++++ Python C API compatibility ++++++++++++++++++++++++++ .. image:: https://github.com/python/pythoncapi-compat/actions/workflows/build.yml/badge.svg :alt: Build status of pythoncapi-compat on GitHub Actions :target: https://github.com/python/pythoncapi-compat/actions The ``pythoncapi-compat`` project can be used to write a C or C++ extension supporting a wide range of Python versions with a single code base. It is made of the ``pythoncapi_compat.h`` header file and the ``upgrade_pythoncapi.py`` script. ``upgrade_pythoncapi.py`` requires Python 3.6 or newer. See the `documentation at ReadTheDocs `_ for more details. Getting started =============== To upgrade a specific file:: python3 upgrade_pythoncapi.py module.c To upgrade all C/C++ files in a directory:: python3 upgrade_pythoncapi.py src/ Select operations ----------------- To only replace ``op->ob_type`` with ``Py_TYPE(op)``, select the ``Py_TYPE`` operation with:: python3 upgrade_pythoncapi.py -o Py_TYPE module.c Or the opposite, to apply all operations but leave ``op->ob_type`` unchanged, deselect the ``Py_TYPE`` operation with:: python3 upgrade_pythoncapi.py -o all,-Py_TYPE module.c Download pythoncapi_compat.h ---------------------------- If you want to ``pythoncapi_compat.h`` to your code base, use the ``upgrade_pythoncapi.py`` tool to fetch it:: python3 upgrade_pythoncapi.py --download PATH This project is distributed under the `Zero Clause BSD (0BSD) license `_ and is covered by the `PSF Code of Conduct `_. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3638036 pygobject-3.54.5/subprojects/pythoncapi-compat/docs/Makefile0000644000000000000000000000117115074677100022735 0ustar00rootroot# Minimal makefile for Sphinx documentation # # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760788032.364281 pygobject-3.54.5/subprojects/pythoncapi-compat/docs/api.rst0000644000000000000000000006726615074677100022621 0ustar00rootroot+++++++++++++++++++++++ pythoncapi_compat.h API +++++++++++++++++++++++ The ``pythoncapi_compat.h`` header file provides implementations of recent functions for old Python versions. Supported Python versions: * Python 3.6 - 3.14 * PyPy 2.7 and PyPy 3.6 - 3.10 Python 2.7 and Python 3.5 are no longer officially supported since GitHub Actions doesn't support them anymore: only best effort support is provided. C++03 and C++11 are supported on Python 3.6 and newer. A C11 subset (without optional features) is required, like ``static inline`` functions: see `PEP 7 `_. ISO C90 is partially supported for Python 2.7. Some functions related to frame objects and ``PyThreadState`` are not available on PyPy. Latest version of the header file: `pythoncapi_compat.h `_. Python 3.14 ----------- .. c:struct:: PyLongLayout See `PyLongLayout documentation `__. .. c:function:: const PyLongLayout* PyLong_GetNativeLayout(void) See `PyLong_GetNativeLayout() documentation `__. .. c:struct:: PyLongExport See `PyLongExport documentation `__. .. c:function:: int PyLong_Export(PyObject *obj, PyLongExport *export_long) See `PyLong_Export() documentation `__. .. c:function:: void PyLong_FreeExport(PyLongExport *export_long) See `PyLong_FreeExport() documentation `__. .. c:struct:: PyLongWriter See `PyLongWriter documentation `__. .. c:function:: PyLongWriter* PyLongWriter_Create(int negative, Py_ssize_t ndigits, void **digits) See `PyLongWriter_Create() documentation `__. .. c:function:: PyObject* PyLongWriter_Finish(PyLongWriter *writer) See `PyLongWriter_Finish() documentation `__. .. c:function:: void PyLongWriter_Discard(PyLongWriter *writer) See `PyLongWriter_Discard() documentation `__. .. c:function:: int PyLong_IsPositive(PyObject *obj) See `PyLong_IsPositive() documentation `__. .. c:function:: int PyLong_IsNegative(PyObject *obj) See `PyLong_IsNegative() documentation `__. .. c:function:: int PyLong_IsZero(PyObject *obj) See `PyLong_IsZero() documentation `__. .. c:function:: int PyLong_GetSign(PyObject *obj, int *sign) See `PyLong_GetSign() documentation `__. .. c:function:: PyObject* PyIter_NextItem(PyObject *sep, PyObject *iterable) See `PyIter_NextItem() documentation `__. .. c:function:: PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable) See `PyBytes_Join() documentation `__. .. c:function:: Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len) See `Py_HashBuffer() documentation `__. .. c:function:: int PyUnicode_Equal(PyObject *str1, PyObject *str2) See `PyUnicode_Equal() documentation `__. .. c:function:: PyUnicodeWriter* PyUnicodeWriter_Create(Py_ssize_t length) See `PyUnicodeWriter_Create() documentation `__. .. c:function:: PyObject* PyUnicodeWriter_Finish(PyUnicodeWriter *writer) See `PyUnicodeWriter_Finish() documentation `__. .. c:function:: void PyUnicodeWriter_Discard(PyUnicodeWriter *writer) See `PyUnicodeWriter_Discard() documentation `__. .. c:function:: int PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch) See `PyUnicodeWriter_WriteChar() documentation `__. .. c:function:: int PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer, const char *str, Py_ssize_t size) See `PyUnicodeWriter_WriteUTF8() documentation `__. .. c:function:: int PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer, const wchar_t *str, Py_ssize_t size) See `PyUnicodeWriter_WriteWideChar() documentation `__. .. c:function:: int PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj) See `PyUnicodeWriter_WriteStr() documentation `__. .. c:function:: int PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj) See `PyUnicodeWriter_WriteRepr() documentation `__. .. c:function:: int PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str, Py_ssize_t start, Py_ssize_t end) See `PyUnicodeWriter_WriteSubstring() documentation `__. .. c:function:: int PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...) See `PyUnicodeWriter_Format() documentation `__. .. c:function:: int PyLong_AsInt32(PyObject *obj, int32_t *pvalue) See `PyLong_AsInt32() documentation `__. .. c:function:: int PyLong_AsInt64(PyObject *obj, int64_t *pvalue) See `PyLong_AsInt64() documentation `__. .. c:function:: int PyLong_AsUInt32(PyObject *obj, uint32_t *pvalue) See `PyLong_AsUInt32() documentation `__. .. c:function:: int PyLong_AsUInt64(PyObject *obj, uint64_t *pvalue) See `PyLong_AsUInt64() documentation `__. .. c:function:: PyObject* PyLong_FromInt32(int32_t value) See `PyLong_FromInt32() documentation `__. .. c:function:: PyObject* PyLong_FromInt64(int64_t value) See `PyLong_FromInt64() documentation `__. .. c:function:: PyObject* PyLong_FromUInt32(uint32_t value) See `PyLong_FromUInt32() documentation `__. .. c:function:: PyObject* PyLong_FromUInt64(uint64_t value) See `PyLong_FromUInt64() documentation `__. .. c:function:: FILE* Py_fopen(PyObject *path, const char *mode) See `Py_fopen() documentation `__. .. c:function:: int Py_fclose(FILE *file) See `Py_fclose() documentation `__. .. c:function:: PyObject* PyConfig_Get(const char *name) See `PyConfig_Get() documentation `__. .. c:function:: int PyConfig_GetInt(const char *name, int *value) See `PyConfig_GetInt() documentation `__. Not supported: * ``PyConfig_Names()`` * ``PyConfig_Set()`` * ``PyInitConfig_AddModule()`` * ``PyInitConfig_Create()`` * ``PyInitConfig_Free()`` * ``PyInitConfig_FreeStrList()`` * ``PyInitConfig_GetError()`` * ``PyInitConfig_GetExitCode()`` * ``PyInitConfig_GetInt()`` * ``PyInitConfig_GetStr()`` * ``PyInitConfig_GetStrList()`` * ``PyInitConfig_HasOption()`` * ``PyInitConfig_SetInt()`` * ``PyInitConfig_SetStr()`` * ``PyInitConfig_SetStrList()`` * ``PyType_GetBaseByToken()`` * ``PyUnicodeWriter_DecodeUTF8Stateful()`` * ``Py_InitializeFromInitConfig()`` Python 3.13 ----------- .. c:function:: int PyDict_GetItemRef(PyObject *p, PyObject *key, PyObject **result) See `PyDict_GetItemRef() documentation `__. .. c:function:: int PyDict_GetItemStringRef(PyObject *p, const char *key, PyObject **result) See `PyDict_GetItemStringRef() documentation `__. .. c:function:: PyObject* PyImport_AddModuleRef(const char *name) See `PyImport_AddModuleRef() documentation `__. .. c:function:: int PyObject_GetOptionalAttr(PyObject *obj, PyObject *attr_name, PyObject **result) See `PyObject_GetOptionalAttr() documentation `__. .. c:function:: int PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result) See `PyObject_GetOptionalAttrString() documentation `__. .. c:function:: int PyObject_HasAttrWithError(PyObject *obj, PyObject *attr_name) See `PyObject_HasAttrWithError() documentation `__. .. c:function:: int PyObject_HasAttrStringWithError(PyObject *obj, const char *attr_name) See `PyObject_HasAttrStringWithError() documentation `__. .. c:function:: int PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result) See `PyMapping_GetOptionalItem() documentation `__. .. c:function:: int PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result) See `PyMapping_GetOptionalItemString() documentation `__. .. c:function:: int PyMapping_HasKeyWithError(PyObject *obj, PyObject *key) See `PyMapping_HasKeyWithError() documentation `__. .. c:function:: int PyMapping_HasKeyStringWithError(PyObject *obj, const char *key) See `PyMapping_HasKeyStringWithError() documentation `__. .. c:function:: int PyModule_Add(PyObject *module, const char *name, PyObject *value) See `PyModule_Add() documentation `__. .. c:function:: int PyWeakref_GetRef(PyObject *ref, PyObject **pobj) See `PyWeakref_GetRef() documentation `__. .. c:function:: int Py_IsFinalizing() Return non-zero if the Python interpreter is shutting down, return 0 otherwise. Availability: Python 3.3 and newer, PyPy 7.3 and newer. See `Py_IsFinalizing() documentation `__. .. c:function:: int PyDict_ContainsString(PyObject *p, const char *key) See `PyDict_ContainsString() documentation `__. .. c:function:: int PyLong_AsInt(PyObject *obj) See `PyLong_AsInt() documentation `__. .. c:function:: int PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) See `PyObject_VisitManagedDict() documentation `__. .. c:function:: void PyObject_ClearManagedDict(PyObject *obj) See `PyObject_ClearManagedDict() documentation `__. .. c:function:: PyThreadState* PyThreadState_GetUnchecked(void) See `PyThreadState_GetUnchecked() documentation `__. Available on Python 3.5.2 and newer. .. c:function:: int PyUnicode_EqualToUTF8(PyObject *unicode, const char *str) See `PyUnicode_EqualToUTF8() documentation `__. .. c:function:: int PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t size) See `PyUnicode_EqualToUTF8AndSize() documentation `__. .. c:function:: int PyList_Extend(PyObject *list, PyObject *iterable) See `PyList_Extend() documentation `__. .. c:function:: int PyList_Clear(PyObject *list) See `PyList_Clear() documentation `__. .. c:function:: int PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result) See `PyDict_Pop() documentation `__. .. c:function:: int PyDict_PopString(PyObject *dict, const char *key, PyObject **result) See `PyDict_PopString() documentation `__. .. c:function:: Py_hash_t Py_HashPointer(const void *ptr) See `Py_HashPointer() documentation `__. .. c:type:: PyTime_t A timestamp or duration in nanoseconds, represented as a signed 64-bit integer. .. c:var:: PyTime_t PyTime_MIN Minimum value of :c:type:`PyTime_t`. .. c:var:: PyTime_t PyTime_MAX Maximum value of :c:type:`PyTime_t`. .. c:function:: double PyTime_AsSecondsDouble(PyTime_t t) See `PyTime_AsSecondsDouble() documentation `__. .. c:function:: int PyTime_Monotonic(PyTime_t *result) See `PyTime_Monotonic() documentation `__. .. c:function:: int PyTime_Time(PyTime_t *result) See `PyTime_Time() documentation `__. .. c:function:: int PyTime_PerfCounter(PyTime_t *result) See `PyTime_PerfCounter() documentation `__. .. c:function:: PyObject* PyList_GetItemRef(PyObject *op, Py_ssize_t index) See `PyList_GetItemRef() documentation `__. .. c:function:: int PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value, PyObject **result) See `PyDict_SetDefaultRef() documentation `__. Not supported: * ``PyErr_FormatUnraisable()``. * ``PyLong_AsNativeBytes()`` * ``PyLong_FromNativeBytes()`` * ``PyLong_FromUnsignedNativeBytes()`` * ``PyObject_GenericHash()``. * ``PySys_Audit()``. * ``PySys_AuditTuple()``. * ``PyType_GetFullyQualifiedName()`` * ``PyType_GetModuleName()`` Python 3.12 ----------- .. c:function:: PyObject* PyFrame_GetVar(PyFrameObject *frame, PyObject *name) See `PyFrame_GetVar() documentation `__. Not available on PyPy. .. c:function:: PyObject* PyFrame_GetVarString(PyFrameObject *frame, const char *name) See `PyFrame_GetVarString() documentation `__. Not available on PyPy. .. c:function:: PyObject* Py_GetConstant(unsigned int constant_id) See `Py_GetConstant() documentation `__. .. c:function:: PyObject* Py_GetConstantBorrowed(unsigned int constant_id) See `Py_GetConstantBorrowed() documentation `__. Not supported: * ``PyDict_AddWatcher()``, ``PyDict_Watch()``. * ``PyCode_AddWatcher()``, ``PyCode_ClearWatcher()``. * ``PyErr_GetRaisedException()``, ``PyErr_SetRaisedException()``. * ``_PyErr_ChainExceptions1()``. * ``PyErr_DisplayException()``. * ``_Py_IsImmortal()``. * ``Py_NewInterpreterFromConfig()``. * ``PyException_GetArgs()``, ``PyException_SetArgs()``. * ``PyEval_SetProfileAllThreads()``, ``PyEval_SetTraceAllThreads()``. * ``PyFunction_SetVectorcall()``. * ``PyType_FromMetaclass()``: implementation too big to be backported. * ``PyVectorcall_Call()``. Python 3.11 ----------- .. c:function:: PyObject* PyCode_GetCellvars(PyCodeObject *code) See `PyCode_GetCellvars() documentation `__. Not available on PyPy. .. c:function:: PyObject* PyCode_GetCode(PyCodeObject *code) See `PyCode_GetCode() documentation `__. Not available on PyPy. .. c:function:: PyObject* PyCode_GetFreevars(PyCodeObject *code) See `PyCode_GetFreevars() documentation `__. Not available on PyPy. .. c:function:: PyObject* PyCode_GetVarnames(PyCodeObject *code) See `PyCode_GetVarnames() documentation `__. Not available on PyPy. .. c:function:: PyObject* PyFrame_GetBuiltins(PyFrameObject *frame) See `PyFrame_GetBuiltins() documentation `__. Not available on PyPy. .. c:function:: PyObject* PyFrame_GetGlobals(PyFrameObject *frame) See `PyFrame_GetGlobals() documentation `__. Not available on PyPy. .. c:function:: int PyFrame_GetLasti(PyFrameObject *frame) See `PyFrame_GetLasti() documentation `__. Not available on PyPy. .. c:function:: PyObject* PyFrame_GetLocals(PyFrameObject *frame) See `PyFrame_GetLocals() documentation `__. Not available on PyPy. .. c:function:: void PyThreadState_EnterTracing(PyThreadState *tstate) See `PyThreadState_EnterTracing() documentation `__. Not available on PyPy. .. c:function:: void PyThreadState_LeaveTracing(PyThreadState *tstate) See `PyThreadState_LeaveTracing() documentation `__. Not available on PyPy .. c:function:: int PyFloat_Pack2(double x, unsigned char *p, int le) Pack a C double as the IEEE 754 binary16 half-precision format. Availability: Python 3.6 and newer. Not available on PyPy .. c:function:: int PyFloat_Pack4(double x, unsigned char *p, int le) Pack a C double as the IEEE 754 binary32 single precision format. Not available on PyPy .. c:function:: int PyFloat_Pack8(double x, unsigned char *p, int le) Pack a C double as the IEEE 754 binary64 double precision format. Not available on PyPy .. c:function:: double PyFloat_Unpack2(const unsigned char *p, int le) Unpack the IEEE 754 binary16 half-precision format as a C double. Availability: Python 3.6 and newer. Not available on PyPy .. c:function:: double PyFloat_Unpack4(const unsigned char *p, int le) Unpack the IEEE 754 binary32 single precision format as a C double. Not available on PyPy .. c:function:: double PyFloat_Unpack8(const unsigned char *p, int le) Unpack the IEEE 754 binary64 double precision format as a C double. Not available on PyPy Not supported: * ``PyType_GetModuleByDef()``. * ``PyType_GetName()``. * ``PyType_GetQualName()``. * ``Py_Version`` constant. * ``PyErr_GetHandledException()``, ``PyErr_SetHandledException()``. * ``PyFrame_GetGenerator()``. Python 3.10 ----------- .. c:function:: PyObject* Py_NewRef(PyObject *obj) See `Py_NewRef() documentation `__. .. c:function:: PyObject* Py_XNewRef(PyObject *obj) See `Py_XNewRef() documentation `__. .. c:function:: int Py_Is(PyObject *x, PyObject *y) See `Py_Is() documentation `__. .. c:function:: int Py_IsNone(PyObject *x) See `Py_IsNone() documentation `__. .. c:function:: int Py_IsTrue(PyObject *x) See `Py_IsTrue() documentation `__. .. c:function:: int Py_IsFalse(PyObject *x) See `Py_IsFalse() documentation `__. .. c:function:: int PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) See `PyModule_AddObjectRef() documentation `__. Not supported: * ``PyCodec_Unregister()``. * ``PyDateTime_DATE_GET_TZINFO()``, ``PyDateTime_TIME_GET_TZINFO()``. * ``PyErr_SetInterruptEx()``. * ``PyGC_Enable()``, ``PyGC_Disable()`` and ``PyGC_IsEnabled()``. * ``PyIter_Send()``. * ``PySet_CheckExact()``. * ``Py_TPFLAGS_DISALLOW_INSTANTIATION`` constant. * ``Py_TPFLAGS_IMMUTABLETYPE`` constant. Python 3.9 ---------- PyObject ^^^^^^^^ .. c:function:: void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) See `Py_SET_REFCNT() documentation `__. .. c:function:: void Py_SET_TYPE(PyObject *ob, PyTypeObject *type) See `Py_SET_TYPE() documentation `__. .. c:function:: void Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) See `Py_SET_SIZE() documentation `__. .. c:function:: int Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) See `Py_IS_TYPE() documentation `__. .. c:function:: PyObject* PyObject_CallNoArgs(PyObject *func) See `PyObject_CallNoArgs() documentation `__. .. c:function:: PyObject* PyObject_CallOneArg(PyObject *func, PyObject *arg) See `PyObject_CallOneArg() documentation `__. .. c:function:: PyObject* PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames) See `PyObject_Vectorcall() documentation `__. .. c:function:: Py_ssize_t PyVectorcall_NARGS(size_t nargsf) See `PyVectorcall_NARGS() documentation `__. .. c:macro:: PY_VECTORCALL_ARGUMENTS_OFFSET See `PY_VECTORCALL_ARGUMENTS_OFFSET documentation `__. Not supported: * ``PyVectorcall_CallMethod()``. * ``PyType_FromModuleAndSpec()`` PyFrameObject ^^^^^^^^^^^^^ .. c:function:: PyCodeObject* PyFrame_GetCode(PyFrameObject *frame) See `PyFrame_GetCode() documentation `__. .. c:function:: PyFrameObject* PyFrame_GetBack(PyFrameObject *frame) See `PyFrame_GetBack() documentation `__. Not available on PyPy PyThreadState ^^^^^^^^^^^^^ .. c:function:: PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate) See `PyThreadState_GetFrame() documentation `__. Not available on PyPy .. c:function:: PyInterpreterState* PyThreadState_GetInterpreter(PyThreadState *tstate) See `PyThreadState_GetInterpreter() documentation `__. .. c:function:: uint64_t PyThreadState_GetID(PyThreadState *tstate) See `PyThreadState_GetID() documentation `__. Availability: Python 3.7. Not available on PyPy. PyInterpreterState ^^^^^^^^^^^^^^^^^^ .. c:function:: PyInterpreterState* PyInterpreterState_Get(void) See `PyInterpreterState_Get() documentation `__. GC protocol ^^^^^^^^^^^ .. c:function:: int PyObject_GC_IsTracked(PyObject* obj) See `PyObject_GC_IsTracked() documentation `__. Not available on PyPy. .. c:function:: int PyObject_GC_IsFinalized(PyObject *obj) See `PyObject_GC_IsFinalized() documentation `__. Availability: Python 3.4. Not available on PyPy. Module helper ^^^^^^^^^^^^^ .. c:function:: int PyModule_AddType(PyObject *module, PyTypeObject *type) See `PyModule_AddType() documentation `__. Python 3.8 ---------- Not supported: * ``PyCode_NewWithPosOnlyArgs()``. Python 3.7 ---------- Not supported: * ``PyImport_GetModule()``. * ``PyInterpreterState_GetID()``. * ``PySlice_Unpack()``, ``PySlice_AdjustIndices()``. * ``PyTimeZone_FromOffset()``, ``PyTimeZone_FromOffsetAndName()``. * ``Py_RETURN_RICHCOMPARE()``. * ``Py_UNREACHABLE`` macro. Python 3.6 ---------- Not supported: * ``PyErr_ResourceWarning()``. * ``PyErr_SetImportErrorSubclass()``. * ``PyOS_FSPath()``. * ``Py_FinalizeEx()``. Python 3.5.2 ------------ .. c:macro:: Py_SETREF(op, op2) .. c:macro:: Py_XSETREF(op, op2) Not supported: * ``PyCodec_NameReplaceErrors()``. * ``PyErr_FormatV()``. * ``PyExc_RecursionError``. * ``PyModule_FromDefAndSpec()``, ``PyModule_FromDefAndSpec2()``, and ``PyModule_ExecDef()``. * ``PyNumber_MatrixMultiply()`` and ``PyNumber_InPlaceMatrixMultiply()``. Python 3.4 ---------- .. c:macro:: Py_UNUSED(name) See `Py_UNUSED() documentation `__. Python 3.2 ---------- Not supported: * ``Py_VA_COPY``. * ``PySys_SetArgvEx()``. * ``PyLong_AsLongLongAndOverflow()``. * ``PyErr_NewExceptionWithDoc()``. Python 3.1 ---------- Not supported: * ``PyOS_string_to_double()``. * ``PyCapsule`` API. Borrow variant -------------- To ease migration of C extensions to the new C API, a variant is provided to return borrowed references rather than strong references. These functions are only available in ``pythoncapi_compat.h`` and are not part of the Python C API. .. c:function:: PyObject* _Py_StealRef(PyObject *ob) Similar to ``Py_DECREF(ob); return ob;``. .. c:function:: PyObject* _Py_XStealRef(PyObject *ob) Similar to ``Py_XDECREF(ob); return ob;``. .. c:function:: PyFrameObject* _PyThreadState_GetFrameBorrow(PyThreadState *tstate) :c:func:`PyThreadState_GetFrame` variant. Not available on PyPy. .. c:function:: PyCodeObject* _PyFrame_GetCodeBorrow(PyFrameObject *frame) :c:func:`PyFrame_GetCode` variant. .. c:function:: PyFrameObject* _PyFrame_GetBackBorrow(PyFrameObject *frame) :c:func:`PyFrame_GetBack` variant Not available on PyPy. For example, ``tstate->frame`` can be replaced with ``_PyThreadState_GetFrameBorrow(tstate)`` to avoid accessing directly ``PyThreadState.frame`` member. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760788032.364281 pygobject-3.54.5/subprojects/pythoncapi-compat/docs/changelog.rst0000644000000000000000000001311315074677100023755 0ustar00rootrootChangelog ========= * 2025-01-19: Add ``PyConfig_Get()`` functions. * 2025-01-06: Add ``Py_fopen()`` and ``Py_fclose()`` functions. * 2024-12-16: Add ``structmember.h`` constants: * ``Py_T_BOOL`` * ``Py_T_BYTE`` * ``Py_T_CHAR`` * ``Py_T_DOUBLE`` * ``Py_T_FLOAT`` * ``Py_T_INT`` * ``Py_T_LONGLONG`` * ``Py_T_LONG`` * ``Py_T_OBJECT_EX`` * ``Py_T_PYSSIZET`` * ``Py_T_SHORT`` * ``Py_T_STRING_INPLACE`` * ``Py_T_STRING`` * ``Py_T_UBYTE`` * ``Py_T_UINT`` * ``Py_T_ULONGLONG`` * ``Py_T_ULONG`` * ``Py_T_USHORT`` * ``_Py_T_NONE`` * ``_Py_T_OBJECT`` * ``Py_AUDIT_READ`` * ``Py_READONLY`` * ``_Py_WRITE_RESTRICTED`` * 2024-12-13: Add functions and structs: * ``PyLongLayout`` * ``PyLong_GetNativeLayout()`` * ``PyLongExport`` * ``PyLong_Export()`` * ``PyLong_FreeExport()`` * ``PyLongWriter`` * ``PyLongWriter_Create()`` * ``PyLongWriter_Finish()`` * ``PyLongWriter_Discard()`` * 2024-11-12: Add functions: * ``PyLong_IsPositive()`` * ``PyLong_IsNegative()`` * ``PyLong_IsZero()`` * 2024-10-09: Add functions: * ``PyBytes_Join()`` * ``PyIter_NextItem()`` * ``PyLong_AsInt32()`` * ``PyLong_AsInt64()`` * ``PyLong_AsUInt32()`` * ``PyLong_AsUInt64()`` * ``PyLong_FromInt32()`` * ``PyLong_FromInt64()`` * ``PyLong_FromUInt32()`` * ``PyLong_FromUInt64()`` * ``PyUnicode_Equal()`` * ``Py_HashBuffer()`` * 2024-07-18: Add functions: * ``PyUnicodeWriter_Create()`` * ``PyUnicodeWriter_Discard()`` * ``PyUnicodeWriter_Finish()`` * ``PyUnicodeWriter_WriteChar()`` * ``PyUnicodeWriter_WriteUTF8()`` * ``PyUnicodeWriter_WriteStr()`` * ``PyUnicodeWriter_WriteRepr()`` * ``PyUnicodeWriter_WriteSubstring()`` * ``PyUnicodeWriter_WriteWideChar()`` * ``PyUnicodeWriter_Format()`` * 2024-06-03: Add ``PyLong_GetSign()``. * 2024-04-23: Drop Python 3.5 support. It cannot be tested anymore (pip fails). * 2024-04-02: Add ``PyDict_SetDefaultRef()`` function. * 2024-03-29: Add ``PyList_GetItemRef()`` function. * 2024-03-21: Add functions: * ``Py_GetConstant()`` * ``Py_GetConstantBorrowed()`` * 2024-03-09: Add hash constants: * ``PyHASH_BITS`` * ``PyHASH_IMAG`` * ``PyHASH_INF`` * ``PyHASH_MODULUS`` * 2024-02-20: Add PyTime API: * ``PyTime_t`` type * ``PyTime_MIN`` and ``PyTime_MAX`` constants * ``PyTime_AsSecondsDouble()`` * ``PyTime_Monotonic()`` * ``PyTime_PerfCounter()`` * ``PyTime_Time()`` * 2023-12-15: Add function ``Py_HashPointer()``. * 2023-11-14: Add functions: * ``PyDict_Pop()`` * ``PyDict_PopString()`` * 2023-11-13: Add functions: * ``PyList_Extend()`` * ``PyList_Clear()`` * 2023-10-04: Add functions: * ``PyUnicode_EqualToUTF8()`` * ``PyUnicode_EqualToUTF8AndSize()`` * 2023-10-03: Add functions: * ``PyObject_VisitManagedDict()`` * ``PyObject_ClearManagedDict()`` * ``PyThreadState_GetUnchecked()`` * 2023-09-29: Add functions: * ``PyMapping_HasKeyWithError()`` * ``PyMapping_HasKeyStringWithError()`` * ``PyObject_HasAttrWithError()`` * ``PyObject_HasAttrStringWithError()`` * 2023-08-25: Add ``PyDict_ContainsString()`` and ``PyLong_AsInt()`` functions. * 2023-08-21: Remove support for Python 2.7, Python 3.4 and older. * 2023-08-16: Add ``Py_IsFinalizing()`` function. * 2023-07-21: Add ``PyDict_GetItemRef()`` function. * 2023-07-18: Add ``PyModule_Add()`` function. * 2023-07-12: Add functions: * ``PyObject_GetOptionalAttr()`` * ``PyObject_GetOptionalAttrString()`` * ``PyMapping_GetOptionalItem()`` * ``PyMapping_GetOptionalItemString()`` * 2023-07-05: Add ``PyObject_Vectorcall()`` function. * 2023-06-21: Add ``PyWeakref_GetRef()`` function. * 2023-06-20: Add ``PyImport_AddModuleRef()`` function. * 2022-11-15: Add experimental operations to the ``upgrade_pythoncapi.py`` script: ``Py_NewRef``, ``Py_CLEAR`` and ``Py_SETREF``. * 2022-11-09: Fix ``Py_SETREF()`` and ``Py_XSETREF()`` macros for `gh-98724 `_. * 2022-11-04: Add ``PyFrame_GetVar()`` and ``PyFrame_GetVarString()`` functions. * 2022-08-04: Add ``PyCode_GetVarnames()``, ``PyCode_GetFreevars()`` and ``PyCode_GetCellvars()`` functions. * 2022-06-14: Fix compatibility with C++ older than C++11. * 2022-05-03: Add ``PyCode_GetCode()`` function. * 2022-04-26: Rename the project from ``pythoncapi_compat`` to ``pythoncapi-compat``: replace the underscore separator with a dash. * 2022-04-08: Add functions ``PyFrame_GetLocals()``, ``PyFrame_GetGlobals()`` ``PyFrame_GetBuiltins()``, and ``PyFrame_GetLasti()``. * 2022-03-12: Add functions ``PyFloat_Pack2()``, ``PyFloat_Pack4()``, ``PyFloat_Pack8()``, ``PyFloat_Unpack2()``, ``PyFloat_Unpack4()`` and ``PyFloat_Unpack8()``. * 2022-03-03: The project moved to https://github.com/python/pythoncapi-compat * 2022-02-11: The project license changes from the MIT license to the Zero Clause BSD (0BSD) license. Projects copying ``pythoncapi_compat.h`` no longer have to include the MIT license and the copyright notice. * 2022-02-08: Add documentation. * 2022-02-09: ``pythoncapi_compat.h`` now supports C++ on Python 3.6 and newer: use ``nullptr`` and ``reinterpret_cast`` cast on C++, and use ``NULL`` and ``(type)`` cast on C. * 2021-10-15: Add ``PyThreadState_EnterTracing()`` and ``PyThreadState_LeaveTracing()``. * 2021-04-09: Add ``Py_Is()``, ``Py_IsNone()``, ``Py_IsTrue()``, ``Py_IsFalse()`` functions. * 2021-04-01: * Add ``Py_SETREF()``, ``Py_XSETREF()`` and ``Py_UNUSED()``. * Add PyPy support. * 2021-01-27: Fix compatibility with Visual Studio 2008 for Python 2.7. * 2020-11-30: Creation of the ``upgrade_pythoncapi.py`` script. * 2020-06-04: Creation of the ``pythoncapi_compat.h`` header file. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760788032.364281 pygobject-3.54.5/subprojects/pythoncapi-compat/docs/conf.py0000644000000000000000000000353315074677100022600 0ustar00rootroot# Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) # -- Project information ----------------------------------------------------- project = 'pythoncapi_compat' copyright = '2022, Victor Stinner' author = 'Victor Stinner' language = "en" # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ ] # Add any paths that contain templates here, relative to this directory. templates_path = ['templates'] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'default' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['static'] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760788032.364281 pygobject-3.54.5/subprojects/pythoncapi-compat/docs/index.rst0000644000000000000000000000144315074677100023140 0ustar00rootroot++++++++++++++++++++++++++ Python C API compatibility ++++++++++++++++++++++++++ The ``pythoncapi-compat`` project can be used to write a C or C++ extension supporting a wide range of Python versions with a single code base. It is made of the ``pythoncapi_compat.h`` header file and the ``upgrade_pythoncapi.py`` script. * Homepage: `GitHub pythoncapi-compat project `_. * `Documentation `_ Documentation: .. toctree:: :maxdepth: 2 upgrade api users tests changelog links This project is distributed under the `Zero Clause BSD (0BSD) license `_ and is covered by the `PSF Code of Conduct `_. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760788032.364281 pygobject-3.54.5/subprojects/pythoncapi-compat/docs/links.rst0000644000000000000000000000240115074677100023144 0ustar00rootrootLinks ===== * `Python/C API Reference Manual `_ * `HPy: a better API for Python `_ * `Cython: C-extensions for Python `_ * `Old 2to3c project `_ by David Malcolm which uses `Coccinelle `_ to ease migration of C extensions from Python 2 to Python 3. See also `2to3c: an implementation of Python's 2to3 for C code `_ article (2009). * PEPs related to the C API: * `PEP 620 -- Hide implementation details from the C API `_ * `PEP 670 -- Convert macros to functions in the Python C API `_ * `PEP 674 -- Disallow using macros as l-values `_ * Make structures opaque * `bpo-39573: PyObject `_ * `bpo-40170: PyTypeObject `_ * `bpo-39947: PyThreadState `_ * `bpo-40421: PyFrameObject `_ * `bpo-47241: PyCodeObject `_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760788032.364281 pygobject-3.54.5/subprojects/pythoncapi-compat/docs/make.bat0000644000000000000000000000143715074677100022707 0ustar00rootroot@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=. set BUILDDIR=build if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.https://www.sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% :end popd ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760788032.364281 pygobject-3.54.5/subprojects/pythoncapi-compat/docs/tests.rst0000644000000000000000000000050515074677100023171 0ustar00rootrootRun tests ========= To run pythoncapi-compat tests, type:: python3 runtests.py To only test the current Python version, use the ``-c`` or the ``--current`` option:: python3 runtests.py --current Verbose mode (``-v``, ``--verbose``):: python3 runtests.py --verbose See tests in the ``tests/`` subdirectory. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760788032.364281 pygobject-3.54.5/subprojects/pythoncapi-compat/docs/upgrade.rst0000644000000000000000000001071315074677100023460 0ustar00rootroot++++++++++++++++++++++++++++ upgrade_pythoncapi.py script ++++++++++++++++++++++++++++ ``upgrade_pythoncapi.py`` requires Python 3.6 or newer. Usage ===== Run the with no arguments to display command line options and list available operations:: python3 upgrade_pythoncapi.py Select files and directories ---------------------------- To upgrade ``module.c`` file, type:: python3 upgrade_pythoncapi.py module.c To upgrade all C and C++ files (``.c``, ``.h``, ``.cc``, ``.cpp``, ``.cxx`` and ``.hpp`` files) in the ``directory/`` directory, type:: python3 upgrade_pythoncapi.py directory/ Multiple filenames an directories can be specified on the command line. Files are modified in-place! If a file is modified, a copy of the original file is created with the ``.old`` suffix. Select operations ----------------- To only replace ``op->ob_type`` with ``Py_TYPE(op)``, select the ``Py_TYPE`` operation with:: python3 upgrade_pythoncapi.py -o Py_TYPE module.c Or the opposite, to apply all operations but leave ``op->ob_type`` unchanged, deselect the ``Py_TYPE`` operation with:: python3 upgrade_pythoncapi.py -o all,-Py_TYPE module.c Download pythoncapi_compat.h ---------------------------- Most ``upgrade_pythoncapi.py`` operations add ``#include "pythoncapi_compat.h"``. You may have to download the ``pythoncapi_compat.h`` header file to your project. It can be downloaded with:: python3 upgrade_pythoncapi.py --download PATH Upgrade Operations ================== ``upgrade_pythoncapi.py`` implements the following operations: Py_TYPE ------- * Replace ``op->ob_type`` with ``Py_TYPE(op)``. Py_SIZE ------- * Replace ``op->ob_size`` with ``Py_SIZE(op)``. Py_REFCNT --------- * Replace ``op->ob_refcnt`` with ``Py_REFCNT(op)``. Py_SET_TYPE ----------- * Replace ``obj->ob_type = type;`` with ``Py_SET_TYPE(obj, type);``. * Replace ``Py_TYPE(obj) = type;`` with ``Py_SET_TYPE(obj, type);``. Py_SET_SIZE ----------- * Replace ``obj->ob_size = size;`` with ``Py_SET_SIZE(obj, size);``. * Replace ``Py_SIZE(obj) = size;`` with ``Py_SET_SIZE(obj, size);``. Py_SET_REFCNT ------------- * Replace ``obj->ob_refcnt = refcnt;`` with ``Py_SET_REFCNT(obj, refcnt);``. * Replace ``Py_REFCNT(obj) = refcnt;`` with ``Py_SET_REFCNT(obj, refcnt);``. Py_Is ----- * Replace ``x == Py_None`` with ``Py_IsNone(x)``. * Replace ``x == Py_True`` with ``Py_IsTrue(x)``. * Replace ``x == Py_False`` with ``Py_IsFalse(x)``. * Replace ``x != Py_None`` with ``!Py_IsNone(x)``. * Replace ``x != Py_True`` with ``!Py_IsTrue(x)``. * Replace ``x != Py_False`` with ``!Py_IsFalse(x)``. PyObject_NEW ------------ * Replace ``PyObject_NEW(...)`` with ``PyObject_New(...)``. * Replace ``PyObject_NEW_VAR(...)`` with ``PyObject_NewVar(...)``. PyMem_MALLOC ------------ * Replace ``PyMem_MALLOC(n)`` with ``PyMem_Malloc(n)``. * Replace ``PyMem_REALLOC(ptr, n)`` with ``PyMem_Realloc(ptr, n)``. * Replace ``PyMem_FREE(ptr)``, ``PyMem_DEL(ptr)`` and ``PyMem_Del(ptr)`` . with ``PyMem_Free(n)``. PyObject_MALLOC --------------- * Replace ``PyObject_MALLOC(n)`` with ``PyObject_Malloc(n)``. * Replace ``PyObject_REALLOC(ptr, n)`` with ``PyObject_Realloc(ptr, n)``. * Replace ``PyObject_FREE(ptr)``, ``PyObject_DEL(ptr)`` and ``PyObject_Del(ptr)`` . with ``PyObject_Free(n)``. PyFrame_GetBack --------------- * Replace ``frame->f_back`` with ``_PyFrame_GetBackBorrow(frame)``. PyFrame_GetCode --------------- * Replace ``frame->f_code`` with ``_PyFrame_GetCodeBorrow(frame)``. PyThreadState_GetInterpreter ---------------------------- * Replace ``tstate->interp`` with ``PyThreadState_GetInterpreter(tstate)``. PyThreadState_GetFrame ---------------------- * Replace ``tstate->frame`` with ``_PyThreadState_GetFrameBorrow(tstate)``. Experimental operations ----------------------- The following operations are experimental (ex: can introduce compiler warnings) and so not included in the ``all`` group, they have to be selected explicitly. Example: ``-o all,Py_SETREF``. Experimental operations: * ``Py_NewRef``: * Replace ``Py_INCREF(res); return res;`` with ``return Py_NewRef(res);`` * Replace ``x = y; Py_INCREF(x);`` with ``x = Py_NewRef(y);`` * Replace ``x = y; Py_INCREF(y);`` with ``x = Py_NewRef(y);`` * Replace ``Py_INCREF(y); x = y;`` with ``x = Py_NewRef(y);`` * ``Py_CLEAR``: * Replace ``Py_XDECREF(var); var = NULL;`` with ``Py_CLEAR(var);`` * ``Py_SETREF``: * Replace ``Py_DECREF(x); x = y;`` with ``Py_SETREF(x, y);`` * Replace ``Py_XDECREF(x); x = y;`` with ``Py_XSETREF(x, y);`` ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760788032.364281 pygobject-3.54.5/subprojects/pythoncapi-compat/docs/users.rst0000644000000000000000000000747015074677100023200 0ustar00rootroot+++++++++++++++++++++++ pythoncapi-compat users +++++++++++++++++++++++ Examples of projects using pythoncapi_compat.h ============================================== * `bitarray `_: ``bitarray/_bitarray.c`` uses ``Py_SET_SIZE()`` (`pythoncapi_compat.h copy `__) * `datatable `_ (`commit `__) * `guppy3 `_ (`commit `__) * `immutables `_: ``immutables/_map.c`` uses ``Py_SET_SIZE()`` (`pythoncapi_compat.h copy `__) * `Mercurial (hg) `_ uses ``Py_SET_TYPE()`` (`commit `__, `pythoncapi_compat.h copy `__) * `mypy `_ (mypyc, `commit `__) * `numpy `_: `pythoncapi-compat Git submodule `_ * `pybluez `_ (`commit `__) * `python-snappy `_ (`commit `__) * `python-zstandard `_ uses ``Py_SET_TYPE()`` and ``Py_SET_SIZE()`` (`commit `__): Mercurial extension. * `python-zstd `_ (`commit `__) * `hollerith `_ ``src/writer.c`` uses ``PyObject_CallOneArg() and other Python 3.9 apis`` (`pythoncapi_compat.h copy `__) * `PyTorch `_ (`pythoncapi_compat.h copy `__) * `PyGObject `_ (`commit `__, `pythoncapi-compat Meson subproject `__) Projects not using pythoncapi_compat.h ====================================== Projects not using ``pythoncapi_compat.h``: * numpy has its own compatibility layer, ``npy_pycompat.h`` and ``npy_3kcompat.h`` header files. It supports more C compilers than pythoncapi_compat.h: it supports ``__STRICT_ANSI__`` (ISO C90) for example. Rejected `PR 18713: MAINT: Use pythoncapi_compat.h in npy_3kcompat.h `_ (when it was rejected, numpy still had code for compatibility with Python 2.7). * Cython doesn't use pythoncapi_compat.h: `see Cython issue #3934 `_. For example, `ModuleSetupCode.c `_ provides functions like ``__Pyx_SET_REFCNT()``. Project with a strict contributor agreement: * `zodbpickle `_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3699112 pygobject-3.54.5/subprojects/pythoncapi-compat/meson.build0000644000000000000000000000011315074677100022502 0ustar00rootrootproject( 'pythoncapi-compat', 'c' ) incdir = include_directories('.') ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3646092 pygobject-3.54.5/subprojects/pythoncapi-compat/pythoncapi_compat.h0000644000000000000000000016733115074677100024252 0ustar00rootroot// Header file providing new C API functions to old Python versions. // // File distributed under the Zero Clause BSD (0BSD) license. // Copyright Contributors to the pythoncapi_compat project. // // Homepage: // https://github.com/python/pythoncapi_compat // // Latest version: // https://raw.githubusercontent.com/python/pythoncapi-compat/main/pythoncapi_compat.h // // SPDX-License-Identifier: 0BSD #ifndef PYTHONCAPI_COMPAT #define PYTHONCAPI_COMPAT #ifdef __cplusplus extern "C" { #endif #include #include // offsetof() // Python 3.11.0b4 added PyFrame_Back() to Python.h #if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION) # include "frameobject.h" // PyFrameObject, PyFrame_GetBack() #endif #if PY_VERSION_HEX < 0x030C00A3 # include // T_SHORT, READONLY #endif #ifndef _Py_CAST # define _Py_CAST(type, expr) ((type)(expr)) #endif // Static inline functions should use _Py_NULL rather than using directly NULL // to prevent C++ compiler warnings. On C23 and newer and on C++11 and newer, // _Py_NULL is defined as nullptr. #ifndef _Py_NULL # if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L) \ || (defined(__cplusplus) && __cplusplus >= 201103) # define _Py_NULL nullptr # else # define _Py_NULL NULL # endif #endif // Cast argument to PyObject* type. #ifndef _PyObject_CAST # define _PyObject_CAST(op) _Py_CAST(PyObject*, op) #endif #ifndef Py_BUILD_ASSERT # define Py_BUILD_ASSERT(cond) \ do { \ (void)sizeof(char [1 - 2 * !(cond)]); \ } while(0) #endif // bpo-42262 added Py_NewRef() to Python 3.10.0a3 #if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef) static inline PyObject* _Py_NewRef(PyObject *obj) { Py_INCREF(obj); return obj; } #define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj)) #endif // bpo-42262 added Py_XNewRef() to Python 3.10.0a3 #if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef) static inline PyObject* _Py_XNewRef(PyObject *obj) { Py_XINCREF(obj); return obj; } #define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj)) #endif // bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT) static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { ob->ob_refcnt = refcnt; } #define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) #endif // Py_SETREF() and Py_XSETREF() were added to Python 3.5.2. // It is excluded from the limited C API. #if (PY_VERSION_HEX < 0x03050200 && !defined(Py_SETREF)) && !defined(Py_LIMITED_API) #define Py_SETREF(dst, src) \ do { \ PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \ PyObject *_tmp_dst = (*_tmp_dst_ptr); \ *_tmp_dst_ptr = _PyObject_CAST(src); \ Py_DECREF(_tmp_dst); \ } while (0) #define Py_XSETREF(dst, src) \ do { \ PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \ PyObject *_tmp_dst = (*_tmp_dst_ptr); \ *_tmp_dst_ptr = _PyObject_CAST(src); \ Py_XDECREF(_tmp_dst); \ } while (0) #endif // bpo-43753 added Py_Is(), Py_IsNone(), Py_IsTrue() and Py_IsFalse() // to Python 3.10.0b1. #if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_Is) # define Py_Is(x, y) ((x) == (y)) #endif #if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsNone) # define Py_IsNone(x) Py_Is(x, Py_None) #endif #if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsTrue) # define Py_IsTrue(x) Py_Is(x, Py_True) #endif #if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsFalse) # define Py_IsFalse(x) Py_Is(x, Py_False) #endif // bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) { ob->ob_type = type; } #define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type) #endif // bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE) static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) { ob->ob_size = size; } #define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size) #endif // bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 #if PY_VERSION_HEX < 0x030900B1 || defined(PYPY_VERSION) static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame) { assert(frame != _Py_NULL); assert(frame->f_code != _Py_NULL); return _Py_CAST(PyCodeObject*, Py_NewRef(frame->f_code)); } #endif static inline PyCodeObject* _PyFrame_GetCodeBorrow(PyFrameObject *frame) { PyCodeObject *code = PyFrame_GetCode(frame); Py_DECREF(code); return code; } // bpo-40421 added PyFrame_GetBack() to Python 3.9.0b1 #if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) static inline PyFrameObject* PyFrame_GetBack(PyFrameObject *frame) { assert(frame != _Py_NULL); return _Py_CAST(PyFrameObject*, Py_XNewRef(frame->f_back)); } #endif #if !defined(PYPY_VERSION) static inline PyFrameObject* _PyFrame_GetBackBorrow(PyFrameObject *frame) { PyFrameObject *back = PyFrame_GetBack(frame); Py_XDECREF(back); return back; } #endif // bpo-40421 added PyFrame_GetLocals() to Python 3.11.0a7 #if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) static inline PyObject* PyFrame_GetLocals(PyFrameObject *frame) { #if PY_VERSION_HEX >= 0x030400B1 if (PyFrame_FastToLocalsWithError(frame) < 0) { return NULL; } #else PyFrame_FastToLocals(frame); #endif return Py_NewRef(frame->f_locals); } #endif // bpo-40421 added PyFrame_GetGlobals() to Python 3.11.0a7 #if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) static inline PyObject* PyFrame_GetGlobals(PyFrameObject *frame) { return Py_NewRef(frame->f_globals); } #endif // bpo-40421 added PyFrame_GetBuiltins() to Python 3.11.0a7 #if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) static inline PyObject* PyFrame_GetBuiltins(PyFrameObject *frame) { return Py_NewRef(frame->f_builtins); } #endif // bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1 #if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION) static inline int PyFrame_GetLasti(PyFrameObject *frame) { #if PY_VERSION_HEX >= 0x030A00A7 // bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset, // not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes) // instructions. if (frame->f_lasti < 0) { return -1; } return frame->f_lasti * 2; #else return frame->f_lasti; #endif } #endif // gh-91248 added PyFrame_GetVar() to Python 3.12.0a2 #if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION) static inline PyObject* PyFrame_GetVar(PyFrameObject *frame, PyObject *name) { PyObject *locals, *value; locals = PyFrame_GetLocals(frame); if (locals == NULL) { return NULL; } #if PY_VERSION_HEX >= 0x03000000 value = PyDict_GetItemWithError(locals, name); #else value = _PyDict_GetItemWithError(locals, name); #endif Py_DECREF(locals); if (value == NULL) { if (PyErr_Occurred()) { return NULL; } #if PY_VERSION_HEX >= 0x03000000 PyErr_Format(PyExc_NameError, "variable %R does not exist", name); #else PyErr_SetString(PyExc_NameError, "variable does not exist"); #endif return NULL; } return Py_NewRef(value); } #endif // gh-91248 added PyFrame_GetVarString() to Python 3.12.0a2 #if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION) static inline PyObject* PyFrame_GetVarString(PyFrameObject *frame, const char *name) { PyObject *name_obj, *value; #if PY_VERSION_HEX >= 0x03000000 name_obj = PyUnicode_FromString(name); #else name_obj = PyString_FromString(name); #endif if (name_obj == NULL) { return NULL; } value = PyFrame_GetVar(frame, name_obj); Py_DECREF(name_obj); return value; } #endif // bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5 #if PY_VERSION_HEX < 0x030900A5 || (defined(PYPY_VERSION) && PY_VERSION_HEX < 0x030B0000) static inline PyInterpreterState * PyThreadState_GetInterpreter(PyThreadState *tstate) { assert(tstate != _Py_NULL); return tstate->interp; } #endif // bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1 #if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) static inline PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate) { assert(tstate != _Py_NULL); return _Py_CAST(PyFrameObject *, Py_XNewRef(tstate->frame)); } #endif #if !defined(PYPY_VERSION) static inline PyFrameObject* _PyThreadState_GetFrameBorrow(PyThreadState *tstate) { PyFrameObject *frame = PyThreadState_GetFrame(tstate); Py_XDECREF(frame); return frame; } #endif // bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5 #if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION) static inline PyInterpreterState* PyInterpreterState_Get(void) { PyThreadState *tstate; PyInterpreterState *interp; tstate = PyThreadState_GET(); if (tstate == _Py_NULL) { Py_FatalError("GIL released (tstate is NULL)"); } interp = tstate->interp; if (interp == _Py_NULL) { Py_FatalError("no current interpreter"); } return interp; } #endif // bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6 #if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) static inline uint64_t PyThreadState_GetID(PyThreadState *tstate) { assert(tstate != _Py_NULL); return tstate->id; } #endif // bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2 #if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION) static inline void PyThreadState_EnterTracing(PyThreadState *tstate) { tstate->tracing++; #if PY_VERSION_HEX >= 0x030A00A1 tstate->cframe->use_tracing = 0; #else tstate->use_tracing = 0; #endif } #endif // bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2 #if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION) static inline void PyThreadState_LeaveTracing(PyThreadState *tstate) { int use_tracing = (tstate->c_tracefunc != _Py_NULL || tstate->c_profilefunc != _Py_NULL); tstate->tracing--; #if PY_VERSION_HEX >= 0x030A00A1 tstate->cframe->use_tracing = use_tracing; #else tstate->use_tracing = use_tracing; #endif } #endif // bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1 // PyObject_CallNoArgs() added to PyPy 3.9.16-v7.3.11 #if !defined(PyObject_CallNoArgs) && PY_VERSION_HEX < 0x030900A1 static inline PyObject* PyObject_CallNoArgs(PyObject *func) { return PyObject_CallFunctionObjArgs(func, NULL); } #endif // bpo-39245 made PyObject_CallOneArg() public (previously called // _PyObject_CallOneArg) in Python 3.9.0a4 // PyObject_CallOneArg() added to PyPy 3.9.16-v7.3.11 #if !defined(PyObject_CallOneArg) && PY_VERSION_HEX < 0x030900A4 static inline PyObject* PyObject_CallOneArg(PyObject *func, PyObject *arg) { return PyObject_CallFunctionObjArgs(func, arg, NULL); } #endif // bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3 #if PY_VERSION_HEX < 0x030A00A3 static inline int PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) { int res; if (!value && !PyErr_Occurred()) { // PyModule_AddObject() raises TypeError in this case PyErr_SetString(PyExc_SystemError, "PyModule_AddObjectRef() must be called " "with an exception raised if value is NULL"); return -1; } Py_XINCREF(value); res = PyModule_AddObject(module, name, value); if (res < 0) { Py_XDECREF(value); } return res; } #endif // bpo-40024 added PyModule_AddType() to Python 3.9.0a5 #if PY_VERSION_HEX < 0x030900A5 static inline int PyModule_AddType(PyObject *module, PyTypeObject *type) { const char *name, *dot; if (PyType_Ready(type) < 0) { return -1; } // inline _PyType_Name() name = type->tp_name; assert(name != _Py_NULL); dot = strrchr(name, '.'); if (dot != _Py_NULL) { name = dot + 1; } return PyModule_AddObjectRef(module, name, _PyObject_CAST(type)); } #endif // bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6. // bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2. #if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) static inline int PyObject_GC_IsTracked(PyObject* obj) { return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)); } #endif // bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6. // bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final. #if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION) static inline int PyObject_GC_IsFinalized(PyObject *obj) { PyGC_Head *gc = _Py_CAST(PyGC_Head*, obj) - 1; return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc)); } #endif // bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE) static inline int _Py_IS_TYPE(PyObject *ob, PyTypeObject *type) { return Py_TYPE(ob) == type; } #define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type) #endif // bpo-46906 added PyFloat_Pack2() and PyFloat_Unpack2() to Python 3.11a7. // bpo-11734 added _PyFloat_Pack2() and _PyFloat_Unpack2() to Python 3.6.0b1. // Python 3.11a2 moved _PyFloat_Pack2() and _PyFloat_Unpack2() to the internal // C API: Python 3.11a2-3.11a6 versions are not supported. #if 0x030600B1 <= PY_VERSION_HEX && PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION) static inline int PyFloat_Pack2(double x, char *p, int le) { return _PyFloat_Pack2(x, (unsigned char*)p, le); } static inline double PyFloat_Unpack2(const char *p, int le) { return _PyFloat_Unpack2((const unsigned char *)p, le); } #endif // bpo-46906 added PyFloat_Pack4(), PyFloat_Pack8(), PyFloat_Unpack4() and // PyFloat_Unpack8() to Python 3.11a7. // Python 3.11a2 moved _PyFloat_Pack4(), _PyFloat_Pack8(), _PyFloat_Unpack4() // and _PyFloat_Unpack8() to the internal C API: Python 3.11a2-3.11a6 versions // are not supported. #if PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION) static inline int PyFloat_Pack4(double x, char *p, int le) { return _PyFloat_Pack4(x, (unsigned char*)p, le); } static inline int PyFloat_Pack8(double x, char *p, int le) { return _PyFloat_Pack8(x, (unsigned char*)p, le); } static inline double PyFloat_Unpack4(const char *p, int le) { return _PyFloat_Unpack4((const unsigned char *)p, le); } static inline double PyFloat_Unpack8(const char *p, int le) { return _PyFloat_Unpack8((const unsigned char *)p, le); } #endif // gh-92154 added PyCode_GetCode() to Python 3.11.0b1 #if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION) static inline PyObject* PyCode_GetCode(PyCodeObject *code) { return Py_NewRef(code->co_code); } #endif // gh-95008 added PyCode_GetVarnames() to Python 3.11.0rc1 #if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION) static inline PyObject* PyCode_GetVarnames(PyCodeObject *code) { return Py_NewRef(code->co_varnames); } #endif // gh-95008 added PyCode_GetFreevars() to Python 3.11.0rc1 #if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION) static inline PyObject* PyCode_GetFreevars(PyCodeObject *code) { return Py_NewRef(code->co_freevars); } #endif // gh-95008 added PyCode_GetCellvars() to Python 3.11.0rc1 #if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION) static inline PyObject* PyCode_GetCellvars(PyCodeObject *code) { return Py_NewRef(code->co_cellvars); } #endif // Py_UNUSED() was added to Python 3.4.0b2. #if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED) # if defined(__GNUC__) || defined(__clang__) # define Py_UNUSED(name) _unused_ ## name __attribute__((unused)) # else # define Py_UNUSED(name) _unused_ ## name # endif #endif // gh-105922 added PyImport_AddModuleRef() to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A0 static inline PyObject* PyImport_AddModuleRef(const char *name) { return Py_XNewRef(PyImport_AddModule(name)); } #endif // gh-105927 added PyWeakref_GetRef() to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D0000 static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj) { PyObject *obj; if (ref != NULL && !PyWeakref_Check(ref)) { *pobj = NULL; PyErr_SetString(PyExc_TypeError, "expected a weakref"); return -1; } obj = PyWeakref_GetObject(ref); if (obj == NULL) { // SystemError if ref is NULL *pobj = NULL; return -1; } if (obj == Py_None) { *pobj = NULL; return 0; } *pobj = Py_NewRef(obj); return 1; } #endif // bpo-36974 added PY_VECTORCALL_ARGUMENTS_OFFSET to Python 3.8b1 #ifndef PY_VECTORCALL_ARGUMENTS_OFFSET # define PY_VECTORCALL_ARGUMENTS_OFFSET (_Py_CAST(size_t, 1) << (8 * sizeof(size_t) - 1)) #endif // bpo-36974 added PyVectorcall_NARGS() to Python 3.8b1 #if PY_VERSION_HEX < 0x030800B1 static inline Py_ssize_t PyVectorcall_NARGS(size_t n) { return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET; } #endif // gh-105922 added PyObject_Vectorcall() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 static inline PyObject* PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames) { #if PY_VERSION_HEX >= 0x030800B1 && !defined(PYPY_VERSION) // bpo-36974 added _PyObject_Vectorcall() to Python 3.8.0b1 return _PyObject_Vectorcall(callable, args, nargsf, kwnames); #else PyObject *posargs = NULL, *kwargs = NULL; PyObject *res; Py_ssize_t nposargs, nkwargs, i; if (nargsf != 0 && args == NULL) { PyErr_BadInternalCall(); goto error; } if (kwnames != NULL && !PyTuple_Check(kwnames)) { PyErr_BadInternalCall(); goto error; } nposargs = (Py_ssize_t)PyVectorcall_NARGS(nargsf); if (kwnames) { nkwargs = PyTuple_GET_SIZE(kwnames); } else { nkwargs = 0; } posargs = PyTuple_New(nposargs); if (posargs == NULL) { goto error; } if (nposargs) { for (i=0; i < nposargs; i++) { PyTuple_SET_ITEM(posargs, i, Py_NewRef(*args)); args++; } } if (nkwargs) { kwargs = PyDict_New(); if (kwargs == NULL) { goto error; } for (i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kwnames, i); PyObject *value = *args; args++; if (PyDict_SetItem(kwargs, key, value) < 0) { goto error; } } } else { kwargs = NULL; } res = PyObject_Call(callable, posargs, kwargs); Py_DECREF(posargs); Py_XDECREF(kwargs); return res; error: Py_DECREF(posargs); Py_XDECREF(kwargs); return NULL; #endif } #endif // gh-106521 added PyObject_GetOptionalAttr() and // PyObject_GetOptionalAttrString() to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A1 static inline int PyObject_GetOptionalAttr(PyObject *obj, PyObject *attr_name, PyObject **result) { // bpo-32571 added _PyObject_LookupAttr() to Python 3.7.0b1 #if PY_VERSION_HEX >= 0x030700B1 && !defined(PYPY_VERSION) return _PyObject_LookupAttr(obj, attr_name, result); #else *result = PyObject_GetAttr(obj, attr_name); if (*result != NULL) { return 1; } if (!PyErr_Occurred()) { return 0; } if (PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); return 0; } return -1; #endif } static inline int PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result) { PyObject *name_obj; int rc; #if PY_VERSION_HEX >= 0x03000000 name_obj = PyUnicode_FromString(attr_name); #else name_obj = PyString_FromString(attr_name); #endif if (name_obj == NULL) { *result = NULL; return -1; } rc = PyObject_GetOptionalAttr(obj, name_obj, result); Py_DECREF(name_obj); return rc; } #endif // gh-106307 added PyObject_GetOptionalAttr() and // PyMapping_GetOptionalItemString() to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A1 static inline int PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result) { *result = PyObject_GetItem(obj, key); if (*result) { return 1; } if (!PyErr_ExceptionMatches(PyExc_KeyError)) { return -1; } PyErr_Clear(); return 0; } static inline int PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result) { PyObject *key_obj; int rc; #if PY_VERSION_HEX >= 0x03000000 key_obj = PyUnicode_FromString(key); #else key_obj = PyString_FromString(key); #endif if (key_obj == NULL) { *result = NULL; return -1; } rc = PyMapping_GetOptionalItem(obj, key_obj, result); Py_DECREF(key_obj); return rc; } #endif // gh-108511 added PyMapping_HasKeyWithError() and // PyMapping_HasKeyStringWithError() to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A1 static inline int PyMapping_HasKeyWithError(PyObject *obj, PyObject *key) { PyObject *res; int rc = PyMapping_GetOptionalItem(obj, key, &res); Py_XDECREF(res); return rc; } static inline int PyMapping_HasKeyStringWithError(PyObject *obj, const char *key) { PyObject *res; int rc = PyMapping_GetOptionalItemString(obj, key, &res); Py_XDECREF(res); return rc; } #endif // gh-108511 added PyObject_HasAttrWithError() and // PyObject_HasAttrStringWithError() to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A1 static inline int PyObject_HasAttrWithError(PyObject *obj, PyObject *attr) { PyObject *res; int rc = PyObject_GetOptionalAttr(obj, attr, &res); Py_XDECREF(res); return rc; } static inline int PyObject_HasAttrStringWithError(PyObject *obj, const char *attr) { PyObject *res; int rc = PyObject_GetOptionalAttrString(obj, attr, &res); Py_XDECREF(res); return rc; } #endif // gh-106004 added PyDict_GetItemRef() and PyDict_GetItemStringRef() // to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A1 static inline int PyDict_GetItemRef(PyObject *mp, PyObject *key, PyObject **result) { #if PY_VERSION_HEX >= 0x03000000 PyObject *item = PyDict_GetItemWithError(mp, key); #else PyObject *item = _PyDict_GetItemWithError(mp, key); #endif if (item != NULL) { *result = Py_NewRef(item); return 1; // found } if (!PyErr_Occurred()) { *result = NULL; return 0; // not found } *result = NULL; return -1; } static inline int PyDict_GetItemStringRef(PyObject *mp, const char *key, PyObject **result) { int res; #if PY_VERSION_HEX >= 0x03000000 PyObject *key_obj = PyUnicode_FromString(key); #else PyObject *key_obj = PyString_FromString(key); #endif if (key_obj == NULL) { *result = NULL; return -1; } res = PyDict_GetItemRef(mp, key_obj, result); Py_DECREF(key_obj); return res; } #endif // gh-106307 added PyModule_Add() to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A1 static inline int PyModule_Add(PyObject *mod, const char *name, PyObject *value) { int res = PyModule_AddObjectRef(mod, name, value); Py_XDECREF(value); return res; } #endif // gh-108014 added Py_IsFinalizing() to Python 3.13.0a1 // bpo-1856 added _Py_Finalizing to Python 3.2.1b1. // _Py_IsFinalizing() was added to PyPy 7.3.0. #if (0x030201B1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030D00A1) \ && (!defined(PYPY_VERSION_NUM) || PYPY_VERSION_NUM >= 0x7030000) static inline int Py_IsFinalizing(void) { #if PY_VERSION_HEX >= 0x030700A1 // _Py_IsFinalizing() was added to Python 3.7.0a1. return _Py_IsFinalizing(); #else return (_Py_Finalizing != NULL); #endif } #endif // gh-108323 added PyDict_ContainsString() to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A1 static inline int PyDict_ContainsString(PyObject *op, const char *key) { PyObject *key_obj = PyUnicode_FromString(key); if (key_obj == NULL) { return -1; } int res = PyDict_Contains(op, key_obj); Py_DECREF(key_obj); return res; } #endif // gh-108445 added PyLong_AsInt() to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A1 static inline int PyLong_AsInt(PyObject *obj) { #ifdef PYPY_VERSION long value = PyLong_AsLong(obj); if (value == -1 && PyErr_Occurred()) { return -1; } if (value < (long)INT_MIN || (long)INT_MAX < value) { PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C int"); return -1; } return (int)value; #else return _PyLong_AsInt(obj); #endif } #endif // gh-107073 added PyObject_VisitManagedDict() to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A1 static inline int PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) { PyObject **dict = _PyObject_GetDictPtr(obj); if (dict == NULL || *dict == NULL) { return -1; } Py_VISIT(*dict); return 0; } static inline void PyObject_ClearManagedDict(PyObject *obj) { PyObject **dict = _PyObject_GetDictPtr(obj); if (dict == NULL || *dict == NULL) { return; } Py_CLEAR(*dict); } #endif // gh-108867 added PyThreadState_GetUnchecked() to Python 3.13.0a1 // Python 3.5.2 added _PyThreadState_UncheckedGet(). #if PY_VERSION_HEX >= 0x03050200 && PY_VERSION_HEX < 0x030D00A1 static inline PyThreadState* PyThreadState_GetUnchecked(void) { return _PyThreadState_UncheckedGet(); } #endif // gh-110289 added PyUnicode_EqualToUTF8() and PyUnicode_EqualToUTF8AndSize() // to Python 3.13.0a1 #if PY_VERSION_HEX < 0x030D00A1 static inline int PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t str_len) { Py_ssize_t len; const void *utf8; PyObject *exc_type, *exc_value, *exc_tb; int res; // API cannot report errors so save/restore the exception PyErr_Fetch(&exc_type, &exc_value, &exc_tb); // Python 3.3.0a1 added PyUnicode_AsUTF8AndSize() #if PY_VERSION_HEX >= 0x030300A1 if (PyUnicode_IS_ASCII(unicode)) { utf8 = PyUnicode_DATA(unicode); len = PyUnicode_GET_LENGTH(unicode); } else { utf8 = PyUnicode_AsUTF8AndSize(unicode, &len); if (utf8 == NULL) { // Memory allocation failure. The API cannot report error, // so ignore the exception and return 0. res = 0; goto done; } } if (len != str_len) { res = 0; goto done; } res = (memcmp(utf8, str, (size_t)len) == 0); #else PyObject *bytes = PyUnicode_AsUTF8String(unicode); if (bytes == NULL) { // Memory allocation failure. The API cannot report error, // so ignore the exception and return 0. res = 0; goto done; } #if PY_VERSION_HEX >= 0x03000000 len = PyBytes_GET_SIZE(bytes); utf8 = PyBytes_AS_STRING(bytes); #else len = PyString_GET_SIZE(bytes); utf8 = PyString_AS_STRING(bytes); #endif if (len != str_len) { Py_DECREF(bytes); res = 0; goto done; } res = (memcmp(utf8, str, (size_t)len) == 0); Py_DECREF(bytes); #endif done: PyErr_Restore(exc_type, exc_value, exc_tb); return res; } static inline int PyUnicode_EqualToUTF8(PyObject *unicode, const char *str) { return PyUnicode_EqualToUTF8AndSize(unicode, str, (Py_ssize_t)strlen(str)); } #endif // gh-111138 added PyList_Extend() and PyList_Clear() to Python 3.13.0a2 #if PY_VERSION_HEX < 0x030D00A2 static inline int PyList_Extend(PyObject *list, PyObject *iterable) { return PyList_SetSlice(list, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, iterable); } static inline int PyList_Clear(PyObject *list) { return PyList_SetSlice(list, 0, PY_SSIZE_T_MAX, NULL); } #endif // gh-111262 added PyDict_Pop() and PyDict_PopString() to Python 3.13.0a2 #if PY_VERSION_HEX < 0x030D00A2 static inline int PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result) { PyObject *value; if (!PyDict_Check(dict)) { PyErr_BadInternalCall(); if (result) { *result = NULL; } return -1; } // bpo-16991 added _PyDict_Pop() to Python 3.5.0b2. // Python 3.6.0b3 changed _PyDict_Pop() first argument type to PyObject*. // Python 3.13.0a1 removed _PyDict_Pop(). #if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030500b2 || PY_VERSION_HEX >= 0x030D0000 value = PyObject_CallMethod(dict, "pop", "O", key); #elif PY_VERSION_HEX < 0x030600b3 value = _PyDict_Pop(_Py_CAST(PyDictObject*, dict), key, NULL); #else value = _PyDict_Pop(dict, key, NULL); #endif if (value == NULL) { if (result) { *result = NULL; } if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_KeyError)) { return -1; } PyErr_Clear(); return 0; } if (result) { *result = value; } else { Py_DECREF(value); } return 1; } static inline int PyDict_PopString(PyObject *dict, const char *key, PyObject **result) { PyObject *key_obj = PyUnicode_FromString(key); if (key_obj == NULL) { if (result != NULL) { *result = NULL; } return -1; } int res = PyDict_Pop(dict, key_obj, result); Py_DECREF(key_obj); return res; } #endif #if PY_VERSION_HEX < 0x030200A4 // Python 3.2.0a4 added Py_hash_t type typedef Py_ssize_t Py_hash_t; #endif // gh-111545 added Py_HashPointer() to Python 3.13.0a3 #if PY_VERSION_HEX < 0x030D00A3 static inline Py_hash_t Py_HashPointer(const void *ptr) { #if PY_VERSION_HEX >= 0x030900A4 && !defined(PYPY_VERSION) return _Py_HashPointer(ptr); #else return _Py_HashPointer(_Py_CAST(void*, ptr)); #endif } #endif // Python 3.13a4 added a PyTime API. // Use the private API added to Python 3.5. #if PY_VERSION_HEX < 0x030D00A4 && PY_VERSION_HEX >= 0x03050000 typedef _PyTime_t PyTime_t; #define PyTime_MIN _PyTime_MIN #define PyTime_MAX _PyTime_MAX static inline double PyTime_AsSecondsDouble(PyTime_t t) { return _PyTime_AsSecondsDouble(t); } static inline int PyTime_Monotonic(PyTime_t *result) { return _PyTime_GetMonotonicClockWithInfo(result, NULL); } static inline int PyTime_Time(PyTime_t *result) { return _PyTime_GetSystemClockWithInfo(result, NULL); } static inline int PyTime_PerfCounter(PyTime_t *result) { #if PY_VERSION_HEX >= 0x03070000 && !defined(PYPY_VERSION) return _PyTime_GetPerfCounterWithInfo(result, NULL); #elif PY_VERSION_HEX >= 0x03070000 // Call time.perf_counter_ns() and convert Python int object to PyTime_t. // Cache time.perf_counter_ns() function for best performance. static PyObject *func = NULL; if (func == NULL) { PyObject *mod = PyImport_ImportModule("time"); if (mod == NULL) { return -1; } func = PyObject_GetAttrString(mod, "perf_counter_ns"); Py_DECREF(mod); if (func == NULL) { return -1; } } PyObject *res = PyObject_CallNoArgs(func); if (res == NULL) { return -1; } long long value = PyLong_AsLongLong(res); Py_DECREF(res); if (value == -1 && PyErr_Occurred()) { return -1; } Py_BUILD_ASSERT(sizeof(value) >= sizeof(PyTime_t)); *result = (PyTime_t)value; return 0; #else // Call time.perf_counter() and convert C double to PyTime_t. // Cache time.perf_counter() function for best performance. static PyObject *func = NULL; if (func == NULL) { PyObject *mod = PyImport_ImportModule("time"); if (mod == NULL) { return -1; } func = PyObject_GetAttrString(mod, "perf_counter"); Py_DECREF(mod); if (func == NULL) { return -1; } } PyObject *res = PyObject_CallNoArgs(func); if (res == NULL) { return -1; } double d = PyFloat_AsDouble(res); Py_DECREF(res); if (d == -1.0 && PyErr_Occurred()) { return -1; } // Avoid floor() to avoid having to link to libm *result = (PyTime_t)(d * 1e9); return 0; #endif } #endif // gh-111389 added hash constants to Python 3.13.0a5. These constants were // added first as private macros to Python 3.4.0b1 and PyPy 7.3.8. #if (!defined(PyHASH_BITS) \ && ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \ || (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \ && PYPY_VERSION_NUM >= 0x07030800))) # define PyHASH_BITS _PyHASH_BITS # define PyHASH_MODULUS _PyHASH_MODULUS # define PyHASH_INF _PyHASH_INF # define PyHASH_IMAG _PyHASH_IMAG #endif // gh-111545 added Py_GetConstant() and Py_GetConstantBorrowed() // to Python 3.13.0a6 #if PY_VERSION_HEX < 0x030D00A6 && !defined(Py_CONSTANT_NONE) #define Py_CONSTANT_NONE 0 #define Py_CONSTANT_FALSE 1 #define Py_CONSTANT_TRUE 2 #define Py_CONSTANT_ELLIPSIS 3 #define Py_CONSTANT_NOT_IMPLEMENTED 4 #define Py_CONSTANT_ZERO 5 #define Py_CONSTANT_ONE 6 #define Py_CONSTANT_EMPTY_STR 7 #define Py_CONSTANT_EMPTY_BYTES 8 #define Py_CONSTANT_EMPTY_TUPLE 9 static inline PyObject* Py_GetConstant(unsigned int constant_id) { static PyObject* constants[Py_CONSTANT_EMPTY_TUPLE + 1] = {NULL}; if (constants[Py_CONSTANT_NONE] == NULL) { constants[Py_CONSTANT_NONE] = Py_None; constants[Py_CONSTANT_FALSE] = Py_False; constants[Py_CONSTANT_TRUE] = Py_True; constants[Py_CONSTANT_ELLIPSIS] = Py_Ellipsis; constants[Py_CONSTANT_NOT_IMPLEMENTED] = Py_NotImplemented; constants[Py_CONSTANT_ZERO] = PyLong_FromLong(0); if (constants[Py_CONSTANT_ZERO] == NULL) { goto fatal_error; } constants[Py_CONSTANT_ONE] = PyLong_FromLong(1); if (constants[Py_CONSTANT_ONE] == NULL) { goto fatal_error; } constants[Py_CONSTANT_EMPTY_STR] = PyUnicode_FromStringAndSize("", 0); if (constants[Py_CONSTANT_EMPTY_STR] == NULL) { goto fatal_error; } constants[Py_CONSTANT_EMPTY_BYTES] = PyBytes_FromStringAndSize("", 0); if (constants[Py_CONSTANT_EMPTY_BYTES] == NULL) { goto fatal_error; } constants[Py_CONSTANT_EMPTY_TUPLE] = PyTuple_New(0); if (constants[Py_CONSTANT_EMPTY_TUPLE] == NULL) { goto fatal_error; } // goto dance to avoid compiler warnings about Py_FatalError() goto init_done; fatal_error: // This case should never happen Py_FatalError("Py_GetConstant() failed to get constants"); } init_done: if (constant_id <= Py_CONSTANT_EMPTY_TUPLE) { return Py_NewRef(constants[constant_id]); } else { PyErr_BadInternalCall(); return NULL; } } static inline PyObject* Py_GetConstantBorrowed(unsigned int constant_id) { PyObject *obj = Py_GetConstant(constant_id); Py_XDECREF(obj); return obj; } #endif // gh-114329 added PyList_GetItemRef() to Python 3.13.0a4 #if PY_VERSION_HEX < 0x030D00A4 static inline PyObject * PyList_GetItemRef(PyObject *op, Py_ssize_t index) { PyObject *item = PyList_GetItem(op, index); Py_XINCREF(item); return item; } #endif // gh-114329 added PyList_GetItemRef() to Python 3.13.0a4 #if PY_VERSION_HEX < 0x030D00A4 static inline int PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value, PyObject **result) { PyObject *value; if (PyDict_GetItemRef(d, key, &value) < 0) { // get error if (result) { *result = NULL; } return -1; } if (value != NULL) { // present if (result) { *result = value; } else { Py_DECREF(value); } return 1; } // missing: set the item if (PyDict_SetItem(d, key, default_value) < 0) { // set error if (result) { *result = NULL; } return -1; } if (result) { *result = Py_NewRef(default_value); } return 0; } #endif #if PY_VERSION_HEX < 0x030D00B3 # define Py_BEGIN_CRITICAL_SECTION(op) { # define Py_END_CRITICAL_SECTION() } # define Py_BEGIN_CRITICAL_SECTION2(a, b) { # define Py_END_CRITICAL_SECTION2() } #endif #if PY_VERSION_HEX < 0x030E0000 && PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION) typedef struct PyUnicodeWriter PyUnicodeWriter; static inline void PyUnicodeWriter_Discard(PyUnicodeWriter *writer) { _PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer); PyMem_Free(writer); } static inline PyUnicodeWriter* PyUnicodeWriter_Create(Py_ssize_t length) { if (length < 0) { PyErr_SetString(PyExc_ValueError, "length must be positive"); return NULL; } const size_t size = sizeof(_PyUnicodeWriter); PyUnicodeWriter *pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size); if (pub_writer == _Py_NULL) { PyErr_NoMemory(); return _Py_NULL; } _PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer; _PyUnicodeWriter_Init(writer); if (_PyUnicodeWriter_Prepare(writer, length, 127) < 0) { PyUnicodeWriter_Discard(pub_writer); return NULL; } writer->overallocate = 1; return pub_writer; } static inline PyObject* PyUnicodeWriter_Finish(PyUnicodeWriter *writer) { PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer); assert(((_PyUnicodeWriter*)writer)->buffer == NULL); PyMem_Free(writer); return str; } static inline int PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch) { if (ch > 0x10ffff) { PyErr_SetString(PyExc_ValueError, "character must be in range(0x110000)"); return -1; } return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch); } static inline int PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj) { PyObject *str = PyObject_Str(obj); if (str == NULL) { return -1; } int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str); Py_DECREF(str); return res; } static inline int PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj) { PyObject *str = PyObject_Repr(obj); if (str == NULL) { return -1; } int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str); Py_DECREF(str); return res; } static inline int PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer, const char *str, Py_ssize_t size) { if (size < 0) { size = (Py_ssize_t)strlen(str); } PyObject *str_obj = PyUnicode_FromStringAndSize(str, size); if (str_obj == _Py_NULL) { return -1; } int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj); Py_DECREF(str_obj); return res; } static inline int PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer, const wchar_t *str, Py_ssize_t size) { if (size < 0) { size = (Py_ssize_t)wcslen(str); } PyObject *str_obj = PyUnicode_FromWideChar(str, size); if (str_obj == _Py_NULL) { return -1; } int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj); Py_DECREF(str_obj); return res; } static inline int PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str, Py_ssize_t start, Py_ssize_t end) { if (!PyUnicode_Check(str)) { PyErr_Format(PyExc_TypeError, "expect str, not %T", str); return -1; } if (start < 0 || start > end) { PyErr_Format(PyExc_ValueError, "invalid start argument"); return -1; } if (end > PyUnicode_GET_LENGTH(str)) { PyErr_Format(PyExc_ValueError, "invalid end argument"); return -1; } return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str, start, end); } static inline int PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...) { va_list vargs; va_start(vargs, format); PyObject *str = PyUnicode_FromFormatV(format, vargs); va_end(vargs); if (str == _Py_NULL) { return -1; } int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str); Py_DECREF(str); return res; } #endif // PY_VERSION_HEX < 0x030E0000 // gh-116560 added PyLong_GetSign() to Python 3.14.0a0 #if PY_VERSION_HEX < 0x030E00A0 static inline int PyLong_GetSign(PyObject *obj, int *sign) { if (!PyLong_Check(obj)) { PyErr_Format(PyExc_TypeError, "expect int, got %s", Py_TYPE(obj)->tp_name); return -1; } *sign = _PyLong_Sign(obj); return 0; } #endif // gh-126061 added PyLong_IsPositive/Negative/Zero() to Python in 3.14.0a2 #if PY_VERSION_HEX < 0x030E00A2 static inline int PyLong_IsPositive(PyObject *obj) { if (!PyLong_Check(obj)) { PyErr_Format(PyExc_TypeError, "expected int, got %s", Py_TYPE(obj)->tp_name); return -1; } return _PyLong_Sign(obj) == 1; } static inline int PyLong_IsNegative(PyObject *obj) { if (!PyLong_Check(obj)) { PyErr_Format(PyExc_TypeError, "expected int, got %s", Py_TYPE(obj)->tp_name); return -1; } return _PyLong_Sign(obj) == -1; } static inline int PyLong_IsZero(PyObject *obj) { if (!PyLong_Check(obj)) { PyErr_Format(PyExc_TypeError, "expected int, got %s", Py_TYPE(obj)->tp_name); return -1; } return _PyLong_Sign(obj) == 0; } #endif // gh-124502 added PyUnicode_Equal() to Python 3.14.0a0 #if PY_VERSION_HEX < 0x030E00A0 static inline int PyUnicode_Equal(PyObject *str1, PyObject *str2) { if (!PyUnicode_Check(str1)) { PyErr_Format(PyExc_TypeError, "first argument must be str, not %s", Py_TYPE(str1)->tp_name); return -1; } if (!PyUnicode_Check(str2)) { PyErr_Format(PyExc_TypeError, "second argument must be str, not %s", Py_TYPE(str2)->tp_name); return -1; } #if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION) PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *str1, PyObject *str2); return _PyUnicode_Equal(str1, str2); #elif PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION) return _PyUnicode_EQ(str1, str2); #elif PY_VERSION_HEX >= 0x03090000 && defined(PYPY_VERSION) return _PyUnicode_EQ(str1, str2); #else return (PyUnicode_Compare(str1, str2) == 0); #endif } #endif // gh-121645 added PyBytes_Join() to Python 3.14.0a0 #if PY_VERSION_HEX < 0x030E00A0 static inline PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable) { return _PyBytes_Join(sep, iterable); } #endif #if PY_VERSION_HEX < 0x030E00A0 static inline Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len) { #if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION) PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void *src, Py_ssize_t len); return _Py_HashBytes(ptr, len); #else Py_hash_t hash; PyObject *bytes = PyBytes_FromStringAndSize((const char*)ptr, len); if (bytes == NULL) { return -1; } hash = PyObject_Hash(bytes); Py_DECREF(bytes); return hash; #endif } #endif #if PY_VERSION_HEX < 0x030E00A0 static inline int PyIter_NextItem(PyObject *iter, PyObject **item) { iternextfunc tp_iternext; assert(iter != NULL); assert(item != NULL); tp_iternext = Py_TYPE(iter)->tp_iternext; if (tp_iternext == NULL) { *item = NULL; PyErr_Format(PyExc_TypeError, "expected an iterator, got '%s'", Py_TYPE(iter)->tp_name); return -1; } if ((*item = tp_iternext(iter))) { return 1; } if (!PyErr_Occurred()) { return 0; } if (PyErr_ExceptionMatches(PyExc_StopIteration)) { PyErr_Clear(); return 0; } return -1; } #endif #if PY_VERSION_HEX < 0x030E00A0 static inline PyObject* PyLong_FromInt32(int32_t value) { Py_BUILD_ASSERT(sizeof(long) >= 4); return PyLong_FromLong(value); } static inline PyObject* PyLong_FromInt64(int64_t value) { Py_BUILD_ASSERT(sizeof(long long) >= 8); return PyLong_FromLongLong(value); } static inline PyObject* PyLong_FromUInt32(uint32_t value) { Py_BUILD_ASSERT(sizeof(unsigned long) >= 4); return PyLong_FromUnsignedLong(value); } static inline PyObject* PyLong_FromUInt64(uint64_t value) { Py_BUILD_ASSERT(sizeof(unsigned long long) >= 8); return PyLong_FromUnsignedLongLong(value); } static inline int PyLong_AsInt32(PyObject *obj, int32_t *pvalue) { Py_BUILD_ASSERT(sizeof(int) == 4); int value = PyLong_AsInt(obj); if (value == -1 && PyErr_Occurred()) { return -1; } *pvalue = (int32_t)value; return 0; } static inline int PyLong_AsInt64(PyObject *obj, int64_t *pvalue) { Py_BUILD_ASSERT(sizeof(long long) == 8); long long value = PyLong_AsLongLong(obj); if (value == -1 && PyErr_Occurred()) { return -1; } *pvalue = (int64_t)value; return 0; } static inline int PyLong_AsUInt32(PyObject *obj, uint32_t *pvalue) { Py_BUILD_ASSERT(sizeof(long) >= 4); unsigned long value = PyLong_AsUnsignedLong(obj); if (value == (unsigned long)-1 && PyErr_Occurred()) { return -1; } #if SIZEOF_LONG > 4 if ((unsigned long)UINT32_MAX < value) { PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C uint32_t"); return -1; } #endif *pvalue = (uint32_t)value; return 0; } static inline int PyLong_AsUInt64(PyObject *obj, uint64_t *pvalue) { Py_BUILD_ASSERT(sizeof(long long) == 8); unsigned long long value = PyLong_AsUnsignedLongLong(obj); if (value == (unsigned long long)-1 && PyErr_Occurred()) { return -1; } *pvalue = (uint64_t)value; return 0; } #endif // gh-102471 added import and export API for integers to 3.14.0a2. #if PY_VERSION_HEX < 0x030E00A2 && PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION) // Helpers to access PyLongObject internals. static inline void _PyLong_SetSignAndDigitCount(PyLongObject *op, int sign, Py_ssize_t size) { #if PY_VERSION_HEX >= 0x030C0000 op->long_value.lv_tag = (uintptr_t)(1 - sign) | ((uintptr_t)(size) << 3); #elif PY_VERSION_HEX >= 0x030900A4 Py_SET_SIZE(op, sign * size); #else Py_SIZE(op) = sign * size; #endif } static inline Py_ssize_t _PyLong_DigitCount(const PyLongObject *op) { #if PY_VERSION_HEX >= 0x030C0000 return (Py_ssize_t)(op->long_value.lv_tag >> 3); #else return _PyLong_Sign((PyObject*)op) < 0 ? -Py_SIZE(op) : Py_SIZE(op); #endif } static inline digit* _PyLong_GetDigits(const PyLongObject *op) { #if PY_VERSION_HEX >= 0x030C0000 return (digit*)(op->long_value.ob_digit); #else return (digit*)(op->ob_digit); #endif } typedef struct PyLongLayout { uint8_t bits_per_digit; uint8_t digit_size; int8_t digits_order; int8_t digit_endianness; } PyLongLayout; typedef struct PyLongExport { int64_t value; uint8_t negative; Py_ssize_t ndigits; const void *digits; Py_uintptr_t _reserved; } PyLongExport; typedef struct PyLongWriter PyLongWriter; static inline const PyLongLayout* PyLong_GetNativeLayout(void) { static const PyLongLayout PyLong_LAYOUT = { PyLong_SHIFT, sizeof(digit), -1, // least significant first PY_LITTLE_ENDIAN ? -1 : 1, }; return &PyLong_LAYOUT; } static inline int PyLong_Export(PyObject *obj, PyLongExport *export_long) { if (!PyLong_Check(obj)) { memset(export_long, 0, sizeof(*export_long)); PyErr_Format(PyExc_TypeError, "expected int, got %s", Py_TYPE(obj)->tp_name); return -1; } // Fast-path: try to convert to a int64_t PyLongObject *self = (PyLongObject*)obj; int overflow; #if SIZEOF_LONG == 8 long value = PyLong_AsLongAndOverflow(obj, &overflow); #else // Windows has 32-bit long, so use 64-bit long long instead long long value = PyLong_AsLongLongAndOverflow(obj, &overflow); #endif Py_BUILD_ASSERT(sizeof(value) == sizeof(int64_t)); // the function cannot fail since obj is a PyLongObject assert(!(value == -1 && PyErr_Occurred())); if (!overflow) { export_long->value = value; export_long->negative = 0; export_long->ndigits = 0; export_long->digits = 0; export_long->_reserved = 0; } else { export_long->value = 0; export_long->negative = _PyLong_Sign(obj) < 0; export_long->ndigits = _PyLong_DigitCount(self); if (export_long->ndigits == 0) { export_long->ndigits = 1; } export_long->digits = _PyLong_GetDigits(self); export_long->_reserved = (Py_uintptr_t)Py_NewRef(obj); } return 0; } static inline void PyLong_FreeExport(PyLongExport *export_long) { PyObject *obj = (PyObject*)export_long->_reserved; if (obj) { export_long->_reserved = 0; Py_DECREF(obj); } } static inline PyLongWriter* PyLongWriter_Create(int negative, Py_ssize_t ndigits, void **digits) { if (ndigits <= 0) { PyErr_SetString(PyExc_ValueError, "ndigits must be positive"); return NULL; } assert(digits != NULL); PyLongObject *obj = _PyLong_New(ndigits); if (obj == NULL) { return NULL; } _PyLong_SetSignAndDigitCount(obj, negative?-1:1, ndigits); *digits = _PyLong_GetDigits(obj); return (PyLongWriter*)obj; } static inline void PyLongWriter_Discard(PyLongWriter *writer) { PyLongObject *obj = (PyLongObject *)writer; assert(Py_REFCNT(obj) == 1); Py_DECREF(obj); } static inline PyObject* PyLongWriter_Finish(PyLongWriter *writer) { PyObject *obj = (PyObject *)writer; PyLongObject *self = (PyLongObject*)obj; Py_ssize_t j = _PyLong_DigitCount(self); Py_ssize_t i = j; int sign = _PyLong_Sign(obj); assert(Py_REFCNT(obj) == 1); // Normalize and get singleton if possible while (i > 0 && _PyLong_GetDigits(self)[i-1] == 0) { --i; } if (i != j) { if (i == 0) { sign = 0; } _PyLong_SetSignAndDigitCount(self, sign, i); } if (i <= 1) { long val = sign * (long)(_PyLong_GetDigits(self)[0]); Py_DECREF(obj); return PyLong_FromLong(val); } return obj; } #endif #if PY_VERSION_HEX < 0x030C00A3 # define Py_T_SHORT T_SHORT # define Py_T_INT T_INT # define Py_T_LONG T_LONG # define Py_T_FLOAT T_FLOAT # define Py_T_DOUBLE T_DOUBLE # define Py_T_STRING T_STRING # define _Py_T_OBJECT T_OBJECT # define Py_T_CHAR T_CHAR # define Py_T_BYTE T_BYTE # define Py_T_UBYTE T_UBYTE # define Py_T_USHORT T_USHORT # define Py_T_UINT T_UINT # define Py_T_ULONG T_ULONG # define Py_T_STRING_INPLACE T_STRING_INPLACE # define Py_T_BOOL T_BOOL # define Py_T_OBJECT_EX T_OBJECT_EX # define Py_T_LONGLONG T_LONGLONG # define Py_T_ULONGLONG T_ULONGLONG # define Py_T_PYSSIZET T_PYSSIZET # if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION) # define _Py_T_NONE T_NONE # endif # define Py_READONLY READONLY # define Py_AUDIT_READ READ_RESTRICTED # define _Py_WRITE_RESTRICTED PY_WRITE_RESTRICTED #endif // gh-127350 added Py_fopen() and Py_fclose() to Python 3.14a4 #if PY_VERSION_HEX < 0x030E00A4 static inline FILE* Py_fopen(PyObject *path, const char *mode) { #if 0x030400A2 <= PY_VERSION_HEX && !defined(PYPY_VERSION) PyAPI_FUNC(FILE*) _Py_fopen_obj(PyObject *path, const char *mode); return _Py_fopen_obj(path, mode); #else FILE *f; PyObject *bytes; #if PY_VERSION_HEX >= 0x03000000 if (!PyUnicode_FSConverter(path, &bytes)) { return NULL; } #else if (!PyString_Check(path)) { PyErr_SetString(PyExc_TypeError, "except str"); return NULL; } bytes = Py_NewRef(path); #endif const char *path_bytes = PyBytes_AS_STRING(bytes); f = fopen(path_bytes, mode); Py_DECREF(bytes); if (f == NULL) { PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path); return NULL; } return f; #endif } static inline int Py_fclose(FILE *file) { return fclose(file); } #endif #if 0x03090000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030E0000 && !defined(PYPY_VERSION) static inline PyObject* PyConfig_Get(const char *name) { typedef enum { _PyConfig_MEMBER_INT, _PyConfig_MEMBER_UINT, _PyConfig_MEMBER_ULONG, _PyConfig_MEMBER_BOOL, _PyConfig_MEMBER_WSTR, _PyConfig_MEMBER_WSTR_OPT, _PyConfig_MEMBER_WSTR_LIST, } PyConfigMemberType; typedef struct { const char *name; size_t offset; PyConfigMemberType type; const char *sys_attr; } PyConfigSpec; #define PYTHONCAPI_COMPAT_SPEC(MEMBER, TYPE, sys_attr) \ {#MEMBER, offsetof(PyConfig, MEMBER), \ _PyConfig_MEMBER_##TYPE, sys_attr} static const PyConfigSpec config_spec[] = { PYTHONCAPI_COMPAT_SPEC(argv, WSTR_LIST, "argv"), PYTHONCAPI_COMPAT_SPEC(base_exec_prefix, WSTR_OPT, "base_exec_prefix"), PYTHONCAPI_COMPAT_SPEC(base_executable, WSTR_OPT, "_base_executable"), PYTHONCAPI_COMPAT_SPEC(base_prefix, WSTR_OPT, "base_prefix"), PYTHONCAPI_COMPAT_SPEC(bytes_warning, UINT, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(exec_prefix, WSTR_OPT, "exec_prefix"), PYTHONCAPI_COMPAT_SPEC(executable, WSTR_OPT, "executable"), PYTHONCAPI_COMPAT_SPEC(inspect, BOOL, _Py_NULL), #if 0x030C0000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(int_max_str_digits, UINT, _Py_NULL), #endif PYTHONCAPI_COMPAT_SPEC(interactive, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(module_search_paths, WSTR_LIST, "path"), PYTHONCAPI_COMPAT_SPEC(optimization_level, UINT, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(parser_debug, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(platlibdir, WSTR, "platlibdir"), PYTHONCAPI_COMPAT_SPEC(prefix, WSTR_OPT, "prefix"), PYTHONCAPI_COMPAT_SPEC(pycache_prefix, WSTR_OPT, "pycache_prefix"), PYTHONCAPI_COMPAT_SPEC(quiet, BOOL, _Py_NULL), #if 0x030B0000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(stdlib_dir, WSTR_OPT, "_stdlib_dir"), #endif PYTHONCAPI_COMPAT_SPEC(use_environment, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(verbose, UINT, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(warnoptions, WSTR_LIST, "warnoptions"), PYTHONCAPI_COMPAT_SPEC(write_bytecode, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(xoptions, WSTR_LIST, "_xoptions"), PYTHONCAPI_COMPAT_SPEC(buffered_stdio, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(check_hash_pycs_mode, WSTR, _Py_NULL), #if 0x030B0000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(code_debug_ranges, BOOL, _Py_NULL), #endif PYTHONCAPI_COMPAT_SPEC(configure_c_stdio, BOOL, _Py_NULL), #if 0x030D0000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(cpu_count, INT, _Py_NULL), #endif PYTHONCAPI_COMPAT_SPEC(dev_mode, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(dump_refs, BOOL, _Py_NULL), #if 0x030B0000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(dump_refs_file, WSTR_OPT, _Py_NULL), #endif #ifdef Py_GIL_DISABLED PYTHONCAPI_COMPAT_SPEC(enable_gil, INT, _Py_NULL), #endif PYTHONCAPI_COMPAT_SPEC(faulthandler, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(filesystem_encoding, WSTR, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(filesystem_errors, WSTR, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(hash_seed, ULONG, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(home, WSTR_OPT, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(import_time, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(install_signal_handlers, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(isolated, BOOL, _Py_NULL), #ifdef MS_WINDOWS PYTHONCAPI_COMPAT_SPEC(legacy_windows_stdio, BOOL, _Py_NULL), #endif PYTHONCAPI_COMPAT_SPEC(malloc_stats, BOOL, _Py_NULL), #if 0x030A0000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(orig_argv, WSTR_LIST, "orig_argv"), #endif PYTHONCAPI_COMPAT_SPEC(parse_argv, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(pathconfig_warnings, BOOL, _Py_NULL), #if 0x030C0000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(perf_profiling, UINT, _Py_NULL), #endif PYTHONCAPI_COMPAT_SPEC(program_name, WSTR, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(run_command, WSTR_OPT, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(run_filename, WSTR_OPT, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(run_module, WSTR_OPT, _Py_NULL), #if 0x030B0000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(safe_path, BOOL, _Py_NULL), #endif PYTHONCAPI_COMPAT_SPEC(show_ref_count, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(site_import, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(skip_source_first_line, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(stdio_encoding, WSTR, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(stdio_errors, WSTR, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(tracemalloc, UINT, _Py_NULL), #if 0x030B0000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(use_frozen_modules, BOOL, _Py_NULL), #endif PYTHONCAPI_COMPAT_SPEC(use_hash_seed, BOOL, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(user_site_directory, BOOL, _Py_NULL), #if 0x030A0000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(warn_default_encoding, BOOL, _Py_NULL), #endif }; #undef PYTHONCAPI_COMPAT_SPEC const PyConfigSpec *spec; int found = 0; for (size_t i=0; i < sizeof(config_spec) / sizeof(config_spec[0]); i++) { spec = &config_spec[i]; if (strcmp(spec->name, name) == 0) { found = 1; break; } } if (found) { if (spec->sys_attr != NULL) { PyObject *value = PySys_GetObject(spec->sys_attr); if (value == NULL) { PyErr_Format(PyExc_RuntimeError, "lost sys.%s", spec->sys_attr); return NULL; } return Py_NewRef(value); } PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void); const PyConfig *config = _Py_GetConfig(); void *member = (char *)config + spec->offset; switch (spec->type) { case _PyConfig_MEMBER_INT: case _PyConfig_MEMBER_UINT: { int value = *(int *)member; return PyLong_FromLong(value); } case _PyConfig_MEMBER_BOOL: { int value = *(int *)member; return PyBool_FromLong(value != 0); } case _PyConfig_MEMBER_ULONG: { unsigned long value = *(unsigned long *)member; return PyLong_FromUnsignedLong(value); } case _PyConfig_MEMBER_WSTR: case _PyConfig_MEMBER_WSTR_OPT: { wchar_t *wstr = *(wchar_t **)member; if (wstr != NULL) { return PyUnicode_FromWideChar(wstr, -1); } else { return Py_NewRef(Py_None); } } case _PyConfig_MEMBER_WSTR_LIST: { const PyWideStringList *list = (const PyWideStringList *)member; PyObject *tuple = PyTuple_New(list->length); if (tuple == NULL) { return NULL; } for (Py_ssize_t i = 0; i < list->length; i++) { PyObject *item = PyUnicode_FromWideChar(list->items[i], -1); if (item == NULL) { Py_DECREF(tuple); return NULL; } PyTuple_SET_ITEM(tuple, i, item); } return tuple; } default: Py_UNREACHABLE(); } } PyErr_Format(PyExc_ValueError, "unknown config option name: %s", name); return NULL; } static inline int PyConfig_GetInt(const char *name, int *value) { PyObject *obj = PyConfig_Get(name); if (obj == NULL) { return -1; } if (!PyLong_Check(obj)) { Py_DECREF(obj); PyErr_Format(PyExc_TypeError, "config option %s is not an int", name); return -1; } int as_int = PyLong_AsInt(obj); Py_DECREF(obj); if (as_int == -1 && PyErr_Occurred()) { PyErr_Format(PyExc_OverflowError, "config option %s value does not fit into a C int", name); return -1; } *value = as_int; return 0; } #endif // PY_VERSION_HEX > 0x03090000 && !defined(PYPY_VERSION) #ifdef __cplusplus } #endif #endif // PYTHONCAPI_COMPAT ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3646092 pygobject-3.54.5/subprojects/pythoncapi-compat/runtests.py0000755000000000000000000000551715074677100022621 0ustar00rootroot#!/usr/bin/python3 -u """ Run the test suite on multiple Python versions. Usage:: python3 runtests.py python3 runtests.py --verbose python3 runtests.py --current --verbose """ from __future__ import absolute_import from __future__ import print_function import argparse import os.path import shutil import sys try: from shutil import which except ImportError: # Python 2 from distutils.spawn import find_executable as which from tests.utils import run_command TEST_DIR = os.path.join(os.path.dirname(__file__), 'tests') TEST_COMPAT = os.path.join(TEST_DIR, "test_pythoncapi_compat.py") TEST_UPGRADE = os.path.join(TEST_DIR, "test_upgrade_pythoncapi.py") PYTHONS = ( # CPython "python3-debug", "python3", "python2.7", "python3.6", "python3.7", "python3.8", "python3.9", "python3.10", "python3.11", "python3.12", "python3.13", # PyPy "pypy", "pypy2", "pypy2.7", "pypy3", "pypy3.6", "pypy3.7", "pypy3.8", "pypy3.9", "pypy3.10", ) def run_tests_exe(executable, verbose, tested): tested_key = os.path.realpath(executable) if tested_key in tested: return # Don't use realpath() for the executed command to support virtual # environments cmd = [executable, TEST_COMPAT] if verbose: cmd.append('-v') run_command(cmd) tested.add(tested_key) def run_tests(python, verbose, tested): executable = which(python) if not executable: print("Ignore missing Python executable: %s" % python) return run_tests_exe(executable, verbose, tested) def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('-v', '--verbose', action="store_true", help='Verbose mode') parser.add_argument('-c', '--current', action="store_true", help="Only test the current Python executable " "(don't test multiple Python versions)") return parser.parse_args() def main(): args = parse_args() path = os.path.join(TEST_DIR, 'build') if os.path.exists(path): shutil.rmtree(path) # upgrade_pythoncapi.py requires Python 3.6 or newer if sys.version_info >= (3, 6): print("Run %s" % TEST_UPGRADE) cmd = [sys.executable, TEST_UPGRADE] if args.verbose: cmd.append('-v') run_command(cmd) else: print("Don't test upgrade_pythoncapi.py: it requires Python 3.6") print() tested = set() if not args.current: for python in PYTHONS: run_tests(python, args.verbose, tested) run_tests_exe(sys.executable, args.verbose, tested) print() print("Tested: %s Python executables" % len(tested)) else: run_tests_exe(sys.executable, args.verbose, tested) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3646092 pygobject-3.54.5/subprojects/pythoncapi-compat/tests/__init__.py0000644000000000000000000000000015074677100023606 0ustar00rootroot././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3653042 pygobject-3.54.5/subprojects/pythoncapi-compat/tests/setup.py0000755000000000000000000000627715074677100023240 0ustar00rootroot#!/usr/bin/env python3 import os.path import shlex import sys try: from setuptools import setup, Extension except ImportError: from distutils.core import setup, Extension try: from distutils import sysconfig except ImportError: import sysconfig # C++ is only supported on Python 3.6 and newer TEST_CXX = (sys.version_info >= (3, 6)) SRC_DIR = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) # Windows uses MSVC compiler MSVC = (os.name == "nt") COMMON_FLAGS = [ '-I' + SRC_DIR, ] if not MSVC: # C compiler flags for GCC and clang COMMON_FLAGS.extend(( # Treat warnings as error '-Werror', # Enable all warnings '-Wall', '-Wextra', # Extra warnings '-Wconversion', # /usr/lib64/pypy3.7/include/pyport.h:68:20: error: redefinition of typedef # 'Py_hash_t' is a C11 feature "-Wno-typedef-redefinition", )) CFLAGS = COMMON_FLAGS + [ # Use C99 for pythoncapi_compat.c which initializes PyModuleDef with a # mixture of designated and non-designated initializers '-std=c99', ] else: # C compiler flags for MSVC COMMON_FLAGS.extend(( # Treat all compiler warnings as compiler errors '/WX', )) CFLAGS = list(COMMON_FLAGS) CXXFLAGS = list(COMMON_FLAGS) def main(): # gh-105776: When "gcc -std=11" is used as the C++ compiler, -std=c11 # option emits a C++ compiler warning. Remove "-std11" option from the # CC command. cmd = (sysconfig.get_config_var('CC') or '') if cmd: cmd = shlex.split(cmd) cmd = [arg for arg in cmd if not arg.startswith('-std=')] if (sys.version_info >= (3, 8)): cmd = shlex.join(cmd) elif (sys.version_info >= (3, 3)): cmd = ' '.join(shlex.quote(arg) for arg in cmd) else: # Python 2.7 import pipes cmd = ' '.join(pipes.quote(arg) for arg in cmd) # CC env var overrides sysconfig CC variable in setuptools os.environ['CC'] = cmd # C extension c_ext = Extension( 'test_pythoncapi_compat_cext', sources=['test_pythoncapi_compat_cext.c'], extra_compile_args=CFLAGS) extensions = [c_ext] if TEST_CXX: # C++ extension # MSVC has /std flag but doesn't support /std:c++11 if not MSVC: versions = [ ('test_pythoncapi_compat_cpp03ext', ['-std=c++03']), ('test_pythoncapi_compat_cpp11ext', ['-std=c++11']), ] else: versions = [ ('test_pythoncapi_compat_cppext', None), ('test_pythoncapi_compat_cpp14ext', ['/std:c++14', '/Zc:__cplusplus']), ] for name, std_flags in versions: flags = list(CXXFLAGS) if std_flags is not None: flags.extend(std_flags) cpp_ext = Extension( name, sources=['test_pythoncapi_compat_cppext.cpp'], extra_compile_args=flags, language='c++') extensions.append(cpp_ext) setup(name="test_pythoncapi_compat", ext_modules=extensions) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3653042 pygobject-3.54.5/subprojects/pythoncapi-compat/tests/test_pythoncapi_compat.py0000644000000000000000000001215115074677100026641 0ustar00rootroot#!/usr/bin/python3 """ Run the test suite. Usage:: python3 run_tests.py python3 run_tests.py -v # verbose mode """ from __future__ import absolute_import from __future__ import print_function import gc import os.path import shutil import subprocess import sys try: import faulthandler except ImportError: # Python 2 faulthandler = None # test.utils from utils import run_command, command_stdout # Windows uses MSVC compiler MSVC = (os.name == "nt") TESTS = [ ("test_pythoncapi_compat_cext", "C"), ] if not MSVC: TESTS.extend(( ("test_pythoncapi_compat_cpp03ext", "C++03"), ("test_pythoncapi_compat_cpp11ext", "C++11"), )) else: TESTS.extend(( ("test_pythoncapi_compat_cppext", "C++"), ("test_pythoncapi_compat_cpp14ext", "C++14"), )) VERBOSE = False def display_title(title): if not VERBOSE: return ver = sys.version_info title = "Python %s.%s: %s" % (ver.major, ver.minor, title) print(title) print("=" * len(title)) print() sys.stdout.flush() def build_ext(): display_title("Build test extensions") if os.path.exists("build"): shutil.rmtree("build") cmd = [sys.executable, "setup.py", "build"] if VERBOSE: run_command(cmd) print() else: exitcode, stdout = command_stdout(cmd, stderr=subprocess.STDOUT) if exitcode: print(stdout.rstrip()) sys.exit(exitcode) def import_tests(module_name): pythonpath = None for name in os.listdir("build"): if name.startswith('lib.'): pythonpath = os.path.join("build", name) if not pythonpath: raise Exception("Failed to find the build directory") sys.path.append(pythonpath) return __import__(module_name) def _run_tests(tests, verbose): for name, test_func in tests: if verbose: print("%s()" % name) sys.stdout.flush() test_func() _HAS_CLEAR_TYPE_CACHE = hasattr(sys, '_clear_type_cache') def _refleak_cleanup(): if _HAS_CLEAR_TYPE_CACHE: sys._clear_type_cache() gc.collect() def _check_refleak(test_func, verbose): nrun = 6 for i in range(1, nrun + 1): if verbose: if i > 1: print() print("Run %s/%s:" % (i, nrun)) sys.stdout.flush() init_refcnt = sys.gettotalrefcount() test_func() _refleak_cleanup() diff = sys.gettotalrefcount() - init_refcnt if i > 3 and diff: raise AssertionError("refcnt leak, diff: %s" % diff) def python_version(): ver = sys.version_info build = 'debug' if hasattr(sys, 'gettotalrefcount') else 'release' if hasattr(sys, 'implementation'): python_impl = sys.implementation.name if python_impl == 'cpython': python_impl = 'CPython' elif python_impl == 'pypy': python_impl = 'PyPy' else: if "PyPy" in sys.version: python_impl = "PyPy" else: python_impl = 'Python' return "%s %s.%s (%s build)" % (python_impl, ver.major, ver.minor, build) def run_tests(module_name, lang): title = "Test %s (%s)" % (module_name, lang) display_title(title) try: testmod = import_tests(module_name) except ImportError: # The C extension must always be available if lang == "C": raise if VERBOSE: print("%s: skip %s, missing %s extension" % (python_version(), lang, module_name)) print() return if VERBOSE: empty_line = False for attr in ('__cplusplus', 'PY_VERSION', 'PY_VERSION_HEX', 'PYPY_VERSION', 'PYPY_VERSION_NUM'): try: value = getattr(testmod, attr) except AttributeError: pass else: if attr in ("PY_VERSION_HEX", "PYPY_VERSION_NUM"): value = "0x%x" % value print("%s: %s" % (attr, value)) empty_line = True if empty_line: print() check_refleak = hasattr(sys, 'gettotalrefcount') tests = [(name, getattr(testmod, name)) for name in dir(testmod) if name.startswith("test")] def test_func(): _run_tests(tests, VERBOSE) if check_refleak: _check_refleak(test_func, VERBOSE) else: test_func() if VERBOSE: print() msg = "%s %s tests succeeded!" % (len(tests), lang) msg = "%s: %s" % (python_version(), msg) if check_refleak: msg = "%s (no reference leak detected)" % msg print(msg) def main(): global VERBOSE VERBOSE = ("-v" in sys.argv[1:] or "--verbose" in sys.argv[1:]) if (3, 13) <= sys.version_info <= (3, 13, 0, 'alpha', 4): print("SKIP Python 3.13 alpha 1..4: not supported!") return if faulthandler is not None: faulthandler.enable() src_dir = os.path.dirname(__file__) if src_dir: os.chdir(src_dir) build_ext() for module_name, lang in TESTS: run_tests(module_name, lang) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3653042 pygobject-3.54.5/subprojects/pythoncapi-compat/tests/test_pythoncapi_compat_cext.c0000644000000000000000000017203215074677100027463 0ustar00rootroot// Always enable assertions #undef NDEBUG #include "pythoncapi_compat.h" #ifdef NDEBUG # error "assertions must be enabled" #endif #ifdef Py_LIMITED_API # error "Py_LIMITED_API is not supported" #endif #if PY_VERSION_HEX >= 0x03000000 # define PYTHON3 1 #endif #if defined(__cplusplus) && __cplusplus >= 201402 # define MODULE_NAME test_pythoncapi_compat_cpp14ext #elif defined(__cplusplus) && __cplusplus >= 201103 # define MODULE_NAME test_pythoncapi_compat_cpp11ext #elif defined(__cplusplus) && !defined(_MSC_VER) # define MODULE_NAME test_pythoncapi_compat_cpp03ext #elif defined(__cplusplus) # define MODULE_NAME test_pythoncapi_compat_cppext #else # define MODULE_NAME test_pythoncapi_compat_cext #endif #define _STR(NAME) #NAME #define STR(NAME) _STR(NAME) #define _CONCAT(a, b) a ## b #define CONCAT(a, b) _CONCAT(a, b) #define MODULE_NAME_STR STR(MODULE_NAME) // Ignore reference count checks on PyPy #ifndef PYPY_VERSION # define CHECK_REFCNT #endif // CPython 3.12 beta 1 implements immortal objects (PEP 683) #if 0x030C00B1 <= PY_VERSION_HEX && !defined(PYPY_VERSION) // Don't check reference count of Python 3.12 immortal objects (ex: bool // and str types) # define IMMORTAL_OBJS #endif #ifdef CHECK_REFCNT # define ASSERT_REFCNT(expr) assert(expr) #else # define ASSERT_REFCNT(expr) #endif // Marker to check that pointer value was set static const char uninitialized[] = "uninitialized"; #define UNINITIALIZED_OBJ ((PyObject *)uninitialized) #define UNINITIALIZED_INT 0x83ff979 static PyObject* create_string(const char *str) { PyObject *obj; #ifdef PYTHON3 obj = PyUnicode_FromString(str); #else obj = PyString_FromString(str); #endif assert(obj != _Py_NULL); return obj; } static PyObject * test_object(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored)) { PyObject *obj = PyList_New(0); if (obj == _Py_NULL) { return _Py_NULL; } Py_ssize_t refcnt = Py_REFCNT(obj); // Py_NewRef() PyObject *ref = Py_NewRef(obj); assert(ref == obj); assert(Py_REFCNT(obj) == (refcnt + 1)); Py_DECREF(ref); // Py_XNewRef() PyObject *xref = Py_XNewRef(obj); assert(xref == obj); assert(Py_REFCNT(obj) == (refcnt + 1)); Py_DECREF(xref); assert(Py_XNewRef(_Py_NULL) == _Py_NULL); // Py_SETREF() PyObject *setref = Py_NewRef(obj); PyObject *none = Py_None; assert(Py_REFCNT(obj) == (refcnt + 1)); Py_SETREF(setref, none); assert(setref == none); assert(Py_REFCNT(obj) == refcnt); Py_INCREF(setref); Py_SETREF(setref, _Py_NULL); assert(setref == _Py_NULL); // Py_XSETREF() PyObject *xsetref = _Py_NULL; Py_INCREF(obj); assert(Py_REFCNT(obj) == (refcnt + 1)); Py_XSETREF(xsetref, obj); assert(xsetref == obj); Py_XSETREF(xsetref, _Py_NULL); assert(Py_REFCNT(obj) == refcnt); assert(xsetref == _Py_NULL); // Py_SET_REFCNT Py_SET_REFCNT(obj, Py_REFCNT(obj)); // Py_SET_TYPE Py_SET_TYPE(obj, Py_TYPE(obj)); // Py_SET_SIZE Py_SET_SIZE(obj, Py_SIZE(obj)); // Py_IS_TYPE() int is_type = Py_IS_TYPE(obj, Py_TYPE(obj)); assert(is_type); assert(Py_REFCNT(obj) == refcnt); Py_DECREF(obj); Py_RETURN_NONE; } static PyObject * test_py_is(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored)) { PyObject *o_none = Py_None; PyObject *o_true = Py_True; PyObject *o_false = Py_False; PyObject *obj = PyList_New(0); if (obj == _Py_NULL) { return _Py_NULL; } /* test Py_Is() */ assert(Py_Is(obj, obj)); assert(!Py_Is(obj, o_none)); /* test Py_IsNone() */ assert(Py_IsNone(o_none)); assert(!Py_IsNone(obj)); /* test Py_IsTrue() */ assert(Py_IsTrue(o_true)); assert(!Py_IsTrue(o_false)); assert(!Py_IsTrue(obj)); /* testPy_IsFalse() */ assert(Py_IsFalse(o_false)); assert(!Py_IsFalse(o_true)); assert(!Py_IsFalse(obj)); Py_DECREF(obj); Py_RETURN_NONE; } #ifndef PYPY_VERSION static void test_frame_getvar(PyFrameObject *frame) { // Make the assumption that test_frame_getvar() is only called by // _run_tests() of test_pythoncapi_compat.py and so that the "name" // variable exists. // test PyFrame_GetVar() and PyFrame_GetVarString() PyObject *attr = PyUnicode_FromString("name"); assert(attr != _Py_NULL); PyObject *name1 = PyFrame_GetVar(frame, attr); Py_DECREF(attr); assert(name1 != _Py_NULL); Py_DECREF(name1); PyObject *name2 = PyFrame_GetVarString(frame, "name"); assert(name2 != _Py_NULL); Py_DECREF(name2); // test PyFrame_GetVar() and PyFrame_GetVarString() NameError PyObject *attr3 = PyUnicode_FromString("dontexist"); assert(attr3 != _Py_NULL); PyObject *name3 = PyFrame_GetVar(frame, attr3); Py_DECREF(attr3); assert(name3 == _Py_NULL); assert(PyErr_ExceptionMatches(PyExc_NameError)); PyErr_Clear(); PyObject *name4 = PyFrame_GetVarString(frame, "dontexist"); assert(name4 == _Py_NULL); assert(PyErr_ExceptionMatches(PyExc_NameError)); PyErr_Clear(); } static PyObject * test_frame(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored)) { PyThreadState *tstate = PyThreadState_Get(); // test PyThreadState_GetFrame() PyFrameObject *frame = PyThreadState_GetFrame(tstate); if (frame == _Py_NULL) { PyErr_SetString(PyExc_AssertionError, "PyThreadState_GetFrame failed"); return _Py_NULL; } // test _PyThreadState_GetFrameBorrow() Py_ssize_t frame_refcnt = Py_REFCNT(frame); PyFrameObject *frame2 = _PyThreadState_GetFrameBorrow(tstate); assert(frame2 == frame); assert(Py_REFCNT(frame) == frame_refcnt); // test PyFrame_GetCode() PyCodeObject *code = PyFrame_GetCode(frame); assert(code != _Py_NULL); assert(PyCode_Check(code)); // test _PyFrame_GetCodeBorrow() Py_ssize_t code_refcnt = Py_REFCNT(code); PyCodeObject *code2 = _PyFrame_GetCodeBorrow(frame); assert(code2 == code); assert(Py_REFCNT(code) == code_refcnt); Py_DECREF(code); // PyFrame_GetBack() PyFrameObject* back = PyFrame_GetBack(frame); if (back != _Py_NULL) { assert(PyFrame_Check(back)); } // test _PyFrame_GetBackBorrow() if (back != _Py_NULL) { Py_ssize_t back_refcnt = Py_REFCNT(back); PyFrameObject *back2 = _PyFrame_GetBackBorrow(frame); assert(back2 == back); assert(Py_REFCNT(back) == back_refcnt); } else { PyFrameObject *back2 = _PyFrame_GetBackBorrow(frame); assert(back2 == back); } Py_XDECREF(back); // test PyFrame_GetLocals() PyObject *locals = PyFrame_GetLocals(frame); assert(locals != _Py_NULL); // Python 3.13 creates a local proxy #if PY_VERSION_HEX < 0x030D0000 assert(PyDict_Check(locals)); #endif // test PyFrame_GetGlobals() PyObject *globals = PyFrame_GetGlobals(frame); assert(globals != _Py_NULL); assert(PyDict_Check(globals)); // test PyFrame_GetBuiltins() PyObject *builtins = PyFrame_GetBuiltins(frame); assert(builtins != _Py_NULL); assert(PyDict_Check(builtins)); assert(locals != globals); assert(globals != builtins); assert(builtins != locals); Py_DECREF(locals); Py_DECREF(globals); Py_DECREF(builtins); // test PyFrame_GetLasti() int lasti = PyFrame_GetLasti(frame); assert(lasti >= 0); // test PyFrame_GetVar() and PyFrame_GetVarString() test_frame_getvar(frame); // done Py_DECREF(frame); Py_RETURN_NONE; } #endif static PyObject * test_thread_state(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored)) { PyThreadState *tstate = PyThreadState_Get(); // test PyThreadState_GetInterpreter() PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate); assert(interp != _Py_NULL); #ifndef PYPY_VERSION // test PyThreadState_GetFrame() PyFrameObject *frame = PyThreadState_GetFrame(tstate); if (frame != _Py_NULL) { assert(PyFrame_Check(frame)); } Py_XDECREF(frame); #endif #if 0x030700A1 <= PY_VERSION_HEX && !defined(PYPY_VERSION) uint64_t id = PyThreadState_GetID(tstate); assert(id > 0); #endif #ifndef PYPY_VERSION // PyThreadState_EnterTracing(), PyThreadState_LeaveTracing() PyThreadState_EnterTracing(tstate); PyThreadState_LeaveTracing(tstate); #endif #if PY_VERSION_HEX >= 0x03050200 // PyThreadState_GetUnchecked() assert(PyThreadState_GetUnchecked() == tstate); #endif Py_RETURN_NONE; } static PyObject * test_interpreter(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored)) { // test PyInterpreterState_Get() PyInterpreterState *interp = PyInterpreterState_Get(); assert(interp != _Py_NULL); PyThreadState *tstate = PyThreadState_Get(); PyInterpreterState *interp2 = PyThreadState_GetInterpreter(tstate); assert(interp == interp2); #if 0x030300A1 <= PY_VERSION_HEX && (!defined(PYPY_VERSION_NUM) || PYPY_VERSION_NUM >= 0x7030000) // test Py_IsFinalizing() assert(Py_IsFinalizing() == 0); #endif Py_RETURN_NONE; } static PyObject * test_calls(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored)) { PyObject *func = _Py_CAST(PyObject*, &PyUnicode_Type); // test PyObject_CallNoArgs(): str() returns '' PyObject *res = PyObject_CallNoArgs(func); if (res == _Py_NULL) { return _Py_NULL; } assert(PyUnicode_Check(res)); Py_DECREF(res); // test PyObject_CallOneArg(): str(1) returns '1' PyObject *arg = PyLong_FromLong(1); if (arg == _Py_NULL) { return _Py_NULL; } res = PyObject_CallOneArg(func, arg); Py_DECREF(arg); if (res == _Py_NULL) { return _Py_NULL; } assert(PyUnicode_Check(res)); Py_DECREF(res); Py_RETURN_NONE; } static PyObject * test_gc(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored)) { PyObject *tuple = PyTuple_New(1); Py_INCREF(Py_None); PyTuple_SET_ITEM(tuple, 0, Py_None); #if !defined(PYPY_VERSION) // test PyObject_GC_IsTracked() int tracked = PyObject_GC_IsTracked(tuple); assert(tracked); #endif #if PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION) // test PyObject_GC_IsFinalized() int finalized = PyObject_GC_IsFinalized(tuple); assert(!finalized); #endif Py_DECREF(tuple); Py_RETURN_NONE; } static int check_module_attr(PyObject *module, const char *name, PyObject *expected) { PyObject *attr = PyObject_GetAttrString(module, name); if (attr == _Py_NULL) { return -1; } assert(attr == expected); Py_DECREF(attr); if (PyObject_DelAttrString(module, name) < 0) { return -1; } return 0; } // test PyModule_AddType() static int test_module_add_type(PyObject *module) { PyTypeObject *type = &PyUnicode_Type; #ifdef PYTHON3 const char *type_name = "str"; #else const char *type_name = "unicode"; #endif #ifdef CHECK_REFCNT Py_ssize_t refcnt = Py_REFCNT(type); #endif if (PyModule_AddType(module, type) < 0) { return -1; } #ifndef IMMORTAL_OBJS ASSERT_REFCNT(Py_REFCNT(type) == refcnt + 1); #endif if (check_module_attr(module, type_name, _Py_CAST(PyObject*, type)) < 0) { return -1; } ASSERT_REFCNT(Py_REFCNT(type) == refcnt); return 0; } // test PyModule_AddObjectRef() static int test_module_addobjectref(PyObject *module) { const char *name = "test_module_addobjectref"; PyObject *obj = PyUnicode_FromString(name); assert(obj != _Py_NULL); #ifdef CHECK_REFCNT Py_ssize_t refcnt = Py_REFCNT(obj); #endif if (PyModule_AddObjectRef(module, name, obj) < 0) { ASSERT_REFCNT(Py_REFCNT(obj) == refcnt); Py_DECREF(obj); return -1; } ASSERT_REFCNT(Py_REFCNT(obj) == refcnt + 1); if (check_module_attr(module, name, obj) < 0) { Py_DECREF(obj); return -1; } ASSERT_REFCNT(Py_REFCNT(obj) == refcnt); // PyModule_AddObjectRef() with value=NULL must not crash assert(!PyErr_Occurred()); int res = PyModule_AddObjectRef(module, name, _Py_NULL); assert(res < 0); assert(PyErr_ExceptionMatches(PyExc_SystemError)); PyErr_Clear(); Py_DECREF(obj); return 0; } // test PyModule_Add() static int test_module_add(PyObject *module) { const char *name = "test_module_add"; PyObject *obj = PyUnicode_FromString(name); assert(obj != _Py_NULL); #ifdef CHECK_REFCNT Py_ssize_t refcnt = Py_REFCNT(obj); #endif if (PyModule_Add(module, name, Py_NewRef(obj)) < 0) { ASSERT_REFCNT(Py_REFCNT(obj) == refcnt); Py_DECREF(obj); return -1; } ASSERT_REFCNT(Py_REFCNT(obj) == refcnt + 1); if (check_module_attr(module, name, obj) < 0) { Py_DECREF(obj); return -1; } ASSERT_REFCNT(Py_REFCNT(obj) == refcnt); // PyModule_Add() with value=NULL must not crash assert(!PyErr_Occurred()); int res = PyModule_Add(module, name, _Py_NULL); assert(res < 0); assert(PyErr_ExceptionMatches(PyExc_SystemError)); PyErr_Clear(); Py_DECREF(obj); return 0; } static PyObject * test_module(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored)) { PyObject *module = PyImport_ImportModule("sys"); if (module == _Py_NULL) { return _Py_NULL; } assert(PyModule_Check(module)); if (test_module_add_type(module) < 0) { goto error; } if (test_module_addobjectref(module) < 0) { goto error; } if (test_module_add(module) < 0) { goto error; } Py_DECREF(module); Py_RETURN_NONE; error: Py_DECREF(module); return _Py_NULL; } #if (PY_VERSION_HEX <= 0x030B00A1 || 0x030B00A7 <= PY_VERSION_HEX) && !defined(PYPY_VERSION) static PyObject * test_float_pack(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored)) { const int big_endian = 0; const int little_endian = 1; char data[8]; const double d = 1.5; #if PY_VERSION_HEX >= 0x030600B1 # define HAVE_FLOAT_PACK2 #endif // Test Pack (big endian) #ifdef HAVE_FLOAT_PACK2 assert(PyFloat_Pack2(d, data, big_endian) == 0); assert(memcmp(data, ">\x00", 2) == 0); #endif assert(PyFloat_Pack4(d, data, big_endian) == 0); assert(memcmp(data, "?\xc0\x00\x00", 2) == 0); assert(PyFloat_Pack8(d, data, big_endian) == 0); assert(memcmp(data, "?\xf8\x00\x00\x00\x00\x00\x00", 2) == 0); // Test Pack (little endian) #ifdef HAVE_FLOAT_PACK2 assert(PyFloat_Pack2(d, data, little_endian) == 0); assert(memcmp(data, "\x00>", 2) == 0); #endif assert(PyFloat_Pack4(d, data, little_endian) == 0); assert(memcmp(data, "\x00\x00\xc0?", 2) == 0); assert(PyFloat_Pack8(d, data, little_endian) == 0); assert(memcmp(data, "\x00\x00\x00\x00\x00\x00\xf8?", 2) == 0); // Test Unpack (big endian) #ifdef HAVE_FLOAT_PACK2 assert(PyFloat_Unpack2(">\x00", big_endian) == d); #endif assert(PyFloat_Unpack4("?\xc0\x00\x00", big_endian) == d); assert(PyFloat_Unpack8("?\xf8\x00\x00\x00\x00\x00\x00", big_endian) == d); // Test Unpack (little endian) #ifdef HAVE_FLOAT_PACK2 assert(PyFloat_Unpack2("\x00>", little_endian) == d); #endif assert(PyFloat_Unpack4("\x00\x00\xc0?", little_endian) == d); assert(PyFloat_Unpack8("\x00\x00\x00\x00\x00\x00\xf8?", little_endian) == d); Py_RETURN_NONE; } #endif #if !defined(PYPY_VERSION) static PyObject * test_code(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored)) { PyThreadState *tstate = PyThreadState_Get(); PyFrameObject *frame = PyThreadState_GetFrame(tstate); if (frame == _Py_NULL) { PyErr_SetString(PyExc_AssertionError, "PyThreadState_GetFrame failed"); return _Py_NULL; } PyCodeObject *code = PyFrame_GetCode(frame); // PyCode_GetCode() { PyObject *co_code = PyCode_GetCode(code); assert(co_code != _Py_NULL); assert(PyBytes_Check(co_code)); Py_DECREF(co_code); } // PyCode_GetVarnames { PyObject *co_varnames = PyCode_GetVarnames(code); assert(co_varnames != _Py_NULL); assert(PyTuple_CheckExact(co_varnames)); assert(PyTuple_GET_SIZE(co_varnames) != 0); Py_DECREF(co_varnames); } // PyCode_GetCellvars { PyObject *co_cellvars = PyCode_GetCellvars(code); assert(co_cellvars != _Py_NULL); assert(PyTuple_CheckExact(co_cellvars)); assert(PyTuple_GET_SIZE(co_cellvars) == 0); Py_DECREF(co_cellvars); } // PyCode_GetFreevars { PyObject *co_freevars = PyCode_GetFreevars(code); assert(co_freevars != _Py_NULL); assert(PyTuple_CheckExact(co_freevars)); assert(PyTuple_GET_SIZE(co_freevars) == 0); Py_DECREF(co_freevars); } Py_DECREF(code); Py_DECREF(frame); Py_RETURN_NONE; } #endif #ifdef __cplusplus // Class to test operator casting an object to PyObject* class StrongRef { public: StrongRef(PyObject *obj) : m_obj(obj) { Py_INCREF(this->m_obj); } ~StrongRef() { Py_DECREF(this->m_obj); } // Cast to PyObject*: get a borrowed reference inline operator PyObject*() const { return this->m_obj; } private: PyObject *m_obj; // Strong reference }; #endif static PyObject * test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { PyObject *obj = Py_BuildValue("(ii)", 1, 2); if (obj == _Py_NULL) { return _Py_NULL; } Py_ssize_t refcnt = Py_REFCNT(obj); assert(refcnt >= 1); // gh-92138: For backward compatibility, functions of Python C API accepts // "const PyObject*". Check that using it does not emit C++ compiler // warnings. const PyObject *const_obj = obj; Py_INCREF(const_obj); Py_DECREF(const_obj); PyTypeObject *type = Py_TYPE(const_obj); assert(Py_REFCNT(const_obj) == refcnt); assert(type == &PyTuple_Type); assert(PyTuple_GET_SIZE(const_obj) == 2); PyObject *one = PyTuple_GET_ITEM(const_obj, 0); assert(PyLong_AsLong(one) == 1); #ifdef __cplusplus // gh-92898: StrongRef doesn't inherit from PyObject but has an operator to // cast to PyObject*. StrongRef strong_ref(obj); assert(Py_TYPE(strong_ref) == &PyTuple_Type); assert(Py_REFCNT(strong_ref) == (refcnt + 1)); Py_INCREF(strong_ref); Py_DECREF(strong_ref); #endif // gh-93442: Pass 0 as NULL for PyObject* Py_XINCREF(0); Py_XDECREF(0); #if _cplusplus >= 201103 // Test nullptr passed as PyObject* Py_XINCREF(nullptr); Py_XDECREF(nullptr); #endif Py_DECREF(obj); Py_RETURN_NONE; } static PyObject * test_import(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { PyObject *mod = PyImport_ImportModule("sys"); if (mod == _Py_NULL) { return _Py_NULL; } Py_ssize_t refcnt = Py_REFCNT(mod); // test PyImport_AddModuleRef() PyObject *mod2 = PyImport_AddModuleRef("sys"); if (mod2 == _Py_NULL) { return _Py_NULL; } assert(PyModule_Check(mod2)); assert(Py_REFCNT(mod) == (refcnt + 1)); Py_DECREF(mod2); Py_DECREF(mod); Py_RETURN_NONE; } static void gc_collect(void) { #if defined(PYPY_VERSION) && PY_VERSION_HEX < 0x030B0000 PyObject *mod = PyImport_ImportModule("gc"); assert(mod != _Py_NULL); PyObject *res = PyObject_CallMethod(mod, "collect", _Py_NULL); Py_DECREF(mod); assert(res != _Py_NULL); Py_DECREF(res); #else PyGC_Collect(); #endif } static PyObject * func_varargs(PyObject *Py_UNUSED(module), PyObject *args, PyObject *kwargs) { if (kwargs != _Py_NULL) { return PyTuple_Pack(2, args, kwargs); } else { return PyTuple_Pack(1, args); } } static void check_int(PyObject *obj, int value) { #ifdef PYTHON3 assert(PyLong_Check(obj)); assert(PyLong_AsLong(obj) == value); #else assert(PyInt_Check(obj)); assert(PyInt_AsLong(obj) == value); #endif } static PyObject * test_weakref(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { // Create a new heap type, create an instance of this type, and delete the // type. This object supports weak references. PyObject *new_type = PyObject_CallFunction((PyObject*)&PyType_Type, "s(){}", "TypeName"); if (new_type == _Py_NULL) { return _Py_NULL; } PyObject *obj = PyObject_CallNoArgs(new_type); Py_DECREF(new_type); if (obj == _Py_NULL) { return _Py_NULL; } Py_ssize_t refcnt = Py_REFCNT(obj); // create a weak reference PyObject *weakref = PyWeakref_NewRef(obj, _Py_NULL); if (weakref == _Py_NULL) { return _Py_NULL; } // test PyWeakref_GetRef(), reference is alive PyObject *ref = UNINITIALIZED_OBJ; assert(PyWeakref_GetRef(weakref, &ref) == 1); assert(ref == obj); assert(Py_REFCNT(obj) == (refcnt + 1)); Py_DECREF(ref); // delete the referenced object: clear the weakref Py_DECREF(obj); gc_collect(); // test PyWeakref_GetRef(), reference is dead ref = Py_True; assert(PyWeakref_GetRef(weakref, &ref) == 0); assert(ref == _Py_NULL); // test PyWeakref_GetRef(), invalid type PyObject *invalid_weakref = Py_None; assert(!PyErr_Occurred()); ref = Py_True; assert(PyWeakref_GetRef(invalid_weakref, &ref) == -1); assert(PyErr_ExceptionMatches(PyExc_TypeError)); assert(ref == _Py_NULL); PyErr_Clear(); #ifndef PYPY_VERSION // test PyWeakref_GetRef(NULL) ref = Py_True; assert(PyWeakref_GetRef(_Py_NULL, &ref) == -1); assert(PyErr_ExceptionMatches(PyExc_SystemError)); assert(ref == _Py_NULL); PyErr_Clear(); #endif Py_DECREF(weakref); Py_RETURN_NONE; } static void test_vectorcall_noargs(PyObject *func_varargs) { PyObject *res = PyObject_Vectorcall(func_varargs, _Py_NULL, 0, _Py_NULL); assert(res != _Py_NULL); assert(PyTuple_Check(res)); assert(PyTuple_GET_SIZE(res) == 1); PyObject *posargs = PyTuple_GET_ITEM(res, 0); assert(PyTuple_Check(posargs)); assert(PyTuple_GET_SIZE(posargs) == 0); Py_DECREF(res); } static void test_vectorcall_args(PyObject *func_varargs) { PyObject *args_tuple = Py_BuildValue("ii", 1, 2); assert(args_tuple != _Py_NULL); size_t nargs = (size_t)PyTuple_GET_SIZE(args_tuple); PyObject **args = &PyTuple_GET_ITEM(args_tuple, 0); PyObject *res = PyObject_Vectorcall(func_varargs, args, nargs, _Py_NULL); Py_DECREF(args_tuple); assert(res != _Py_NULL); assert(PyTuple_Check(res)); assert(PyTuple_GET_SIZE(res) == 1); PyObject *posargs = PyTuple_GET_ITEM(res, 0); assert(PyTuple_Check(posargs)); assert(PyTuple_GET_SIZE(posargs) == 2); check_int(PyTuple_GET_ITEM(posargs, 0), 1); check_int(PyTuple_GET_ITEM(posargs, 1), 2); Py_DECREF(res); } static void test_vectorcall_args_offset(PyObject *func_varargs) { // args contains 3 values, but only pass 2 last values PyObject *args_tuple = Py_BuildValue("iii", 1, 2, 3); assert(args_tuple != _Py_NULL); size_t nargs = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET; PyObject **args = &PyTuple_GET_ITEM(args_tuple, 1); PyObject *arg0 = PyTuple_GET_ITEM(args_tuple, 0); PyObject *res = PyObject_Vectorcall(func_varargs, args, nargs, _Py_NULL); assert(PyTuple_GET_ITEM(args_tuple, 0) == arg0); Py_DECREF(args_tuple); assert(res != _Py_NULL); assert(PyTuple_Check(res)); assert(PyTuple_GET_SIZE(res) == 1); PyObject *posargs = PyTuple_GET_ITEM(res, 0); assert(PyTuple_Check(posargs)); assert(PyTuple_GET_SIZE(posargs) == 2); check_int(PyTuple_GET_ITEM(posargs, 0), 2); check_int(PyTuple_GET_ITEM(posargs, 1), 3); Py_DECREF(res); } static void test_vectorcall_args_kwnames(PyObject *func_varargs) { PyObject *args_tuple = Py_BuildValue("iiiii", 1, 2, 3, 4, 5); assert(args_tuple != _Py_NULL); PyObject **args = &PyTuple_GET_ITEM(args_tuple, 0); #ifdef PYTHON3 PyObject *key1 = PyUnicode_FromString("key1"); PyObject *key2 = PyUnicode_FromString("key2"); #else PyObject *key1 = PyString_FromString("key1"); PyObject *key2 = PyString_FromString("key2"); #endif assert(key1 != _Py_NULL); assert(key2 != _Py_NULL); PyObject *kwnames = PyTuple_Pack(2, key1, key2); assert(kwnames != _Py_NULL); size_t nargs = (size_t)(PyTuple_GET_SIZE(args_tuple) - PyTuple_GET_SIZE(kwnames)); PyObject *res = PyObject_Vectorcall(func_varargs, args, nargs, kwnames); Py_DECREF(args_tuple); Py_DECREF(kwnames); assert(res != _Py_NULL); assert(PyTuple_Check(res)); assert(PyTuple_GET_SIZE(res) == 2); PyObject *posargs = PyTuple_GET_ITEM(res, 0); PyObject *kwargs = PyTuple_GET_ITEM(res, 1); assert(PyTuple_Check(posargs)); assert(PyTuple_GET_SIZE(posargs) == 3); check_int(PyTuple_GET_ITEM(posargs, 0), 1); check_int(PyTuple_GET_ITEM(posargs, 1), 2); check_int(PyTuple_GET_ITEM(posargs, 2), 3); assert(PyDict_Check(kwargs)); assert(PyDict_Size(kwargs) == 2); Py_ssize_t pos = 0; PyObject *key, *value; while (PyDict_Next(kwargs, &pos, &key, &value)) { #ifdef PYTHON3 assert(PyUnicode_Check(key)); #else assert(PyString_Check(key)); #endif if (PyObject_RichCompareBool(key, key1, Py_EQ)) { check_int(value, 4); } else { assert(PyObject_RichCompareBool(key, key2, Py_EQ)); check_int(value, 5); } } Py_DECREF(res); Py_DECREF(key1); Py_DECREF(key2); } static PyObject * test_vectorcall(PyObject *module, PyObject *Py_UNUSED(args)) { #ifndef PYTHON3 module = PyImport_ImportModule(MODULE_NAME_STR); assert(module != _Py_NULL); #endif PyObject *func_varargs = PyObject_GetAttrString(module, "func_varargs"); #ifndef PYTHON3 Py_DECREF(module); #endif if (func_varargs == _Py_NULL) { return _Py_NULL; } // test PyObject_Vectorcall() test_vectorcall_noargs(func_varargs); test_vectorcall_args(func_varargs); test_vectorcall_args_offset(func_varargs); test_vectorcall_args_kwnames(func_varargs); Py_DECREF(func_varargs); Py_RETURN_NONE; } static PyObject * test_getattr(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { assert(!PyErr_Occurred()); PyObject *obj = PyImport_ImportModule("sys"); if (obj == _Py_NULL) { return _Py_NULL; } PyObject *attr_name = create_string("version"); PyObject *missing_attr = create_string("nonexistant_attr_name"); // test PyObject_GetOptionalAttr(): attribute exists PyObject *value; value = UNINITIALIZED_OBJ; assert(PyObject_GetOptionalAttr(obj, attr_name, &value) == 1); assert(value != _Py_NULL); Py_DECREF(value); // test PyObject_HasAttrWithError(): attribute exists assert(PyObject_HasAttrWithError(obj, attr_name) == 1); // test PyObject_GetOptionalAttrString(): attribute exists value = UNINITIALIZED_OBJ; assert(PyObject_GetOptionalAttrString(obj, "version", &value) == 1); assert(!PyErr_Occurred()); assert(value != _Py_NULL); Py_DECREF(value); // test PyObject_HasAttrStringWithError(): attribute exists assert(PyObject_HasAttrStringWithError(obj, "version") == 1); assert(!PyErr_Occurred()); // test PyObject_GetOptionalAttr(): attribute doesn't exist value = UNINITIALIZED_OBJ; assert(PyObject_GetOptionalAttr(obj, missing_attr, &value) == 0); assert(!PyErr_Occurred()); assert(value == _Py_NULL); // test PyObject_HasAttrWithError(): attribute doesn't exist assert(PyObject_HasAttrWithError(obj, missing_attr) == 0); assert(!PyErr_Occurred()); // test PyObject_GetOptionalAttrString(): attribute doesn't exist value = UNINITIALIZED_OBJ; assert(PyObject_GetOptionalAttrString(obj, "nonexistant_attr_name", &value) == 0); assert(!PyErr_Occurred()); assert(value == _Py_NULL); // test PyObject_HasAttrStringWithError(): attribute doesn't exist assert(PyObject_HasAttrStringWithError(obj, "nonexistant_attr_name") == 0); assert(!PyErr_Occurred()); Py_DECREF(attr_name); Py_DECREF(missing_attr); Py_DECREF(obj); Py_RETURN_NONE; } static PyObject * test_getitem(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { assert(!PyErr_Occurred()); PyObject *value = Py_BuildValue("s", "value"); assert(value != _Py_NULL); PyObject *obj = Py_BuildValue("{sO}", "key", value); assert(obj != _Py_NULL); PyObject *present_key, *missing_key; PyObject *item; present_key = create_string("key"); missing_key = create_string("dontexist"); // test PyMapping_GetOptionalItem(): key is present item = UNINITIALIZED_OBJ; assert(PyMapping_GetOptionalItem(obj, present_key, &item) == 1); assert(item == value); Py_DECREF(item); assert(!PyErr_Occurred()); // test PyMapping_HasKeyWithError(): key is present assert(PyMapping_HasKeyWithError(obj, present_key) == 1); assert(!PyErr_Occurred()); // test PyMapping_GetOptionalItemString(): key is present item = UNINITIALIZED_OBJ; assert(PyMapping_GetOptionalItemString(obj, "key", &item) == 1); assert(item == value); Py_DECREF(item); // test PyMapping_HasKeyStringWithError(): key is present assert(PyMapping_HasKeyStringWithError(obj, "key") == 1); assert(!PyErr_Occurred()); // test PyMapping_GetOptionalItem(): missing key item = UNINITIALIZED_OBJ; assert(PyMapping_GetOptionalItem(obj, missing_key, &item) == 0); assert(item == _Py_NULL); assert(!PyErr_Occurred()); // test PyMapping_HasKeyWithError(): missing key assert(PyMapping_HasKeyWithError(obj, missing_key) == 0); assert(!PyErr_Occurred()); // test PyMapping_GetOptionalItemString(): missing key item = UNINITIALIZED_OBJ; assert(PyMapping_GetOptionalItemString(obj, "dontexist", &item) == 0); assert(item == _Py_NULL); // test PyMapping_HasKeyStringWithError(): missing key assert(PyMapping_HasKeyStringWithError(obj, "dontexist") == 0); assert(!PyErr_Occurred()); Py_DECREF(obj); Py_DECREF(value); Py_DECREF(present_key); Py_DECREF(missing_key); Py_RETURN_NONE; } static PyObject * test_dict_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { assert(!PyErr_Occurred()); PyObject *dict = NULL, *key = NULL, *missing_key = NULL, *value = NULL; PyObject *invalid_key = NULL; PyObject *invalid_dict = NULL; PyObject *get_value = NULL; int res; // test PyDict_New() dict = PyDict_New(); if (dict == NULL) { goto error; } key = PyUnicode_FromString("key"); if (key == NULL) { goto error; } invalid_dict = key; // borrowed reference missing_key = PyUnicode_FromString("missing_key"); if (missing_key == NULL) { goto error; } invalid_key = PyList_New(0); // not hashable key if (invalid_key == NULL) { goto error; } value = PyUnicode_FromString("value"); if (value == NULL) { goto error; } res = PyDict_SetItemString(dict, "key", value); if (res < 0) { goto error; } assert(res == 0); // test PyDict_Contains() assert(PyDict_Contains(dict, key) == 1); assert(PyDict_Contains(dict, missing_key) == 0); // test PyDict_ContainsString() assert(PyDict_ContainsString(dict, "key") == 1); assert(PyDict_ContainsString(dict, "missing_key") == 0); assert(PyDict_ContainsString(dict, "\xff") == -1); assert(PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)); PyErr_Clear(); // test PyDict_GetItemRef(), key is present get_value = UNINITIALIZED_OBJ; assert(PyDict_GetItemRef(dict, key, &get_value) == 1); assert(get_value == value); Py_DECREF(get_value); // test PyDict_GetItemStringRef(), key is present get_value = UNINITIALIZED_OBJ; assert(PyDict_GetItemStringRef(dict, "key", &get_value) == 1); assert(get_value == value); Py_DECREF(get_value); // test PyDict_GetItemRef(), missing key get_value = UNINITIALIZED_OBJ; assert(PyDict_GetItemRef(dict, missing_key, &get_value) == 0); assert(!PyErr_Occurred()); assert(get_value == NULL); // test PyDict_GetItemStringRef(), missing key get_value = UNINITIALIZED_OBJ; assert(PyDict_GetItemStringRef(dict, "missing_key", &get_value) == 0); assert(!PyErr_Occurred()); assert(get_value == NULL); // test PyDict_GetItemRef(), invalid dict get_value = UNINITIALIZED_OBJ; assert(PyDict_GetItemRef(invalid_dict, key, &get_value) == -1); assert(PyErr_ExceptionMatches(PyExc_SystemError)); PyErr_Clear(); assert(get_value == NULL); // test PyDict_GetItemStringRef(), invalid dict get_value = UNINITIALIZED_OBJ; assert(PyDict_GetItemStringRef(invalid_dict, "key", &get_value) == -1); assert(PyErr_ExceptionMatches(PyExc_SystemError)); PyErr_Clear(); assert(get_value == NULL); // test PyDict_GetItemRef(), invalid key get_value = UNINITIALIZED_OBJ; assert(PyDict_GetItemRef(dict, invalid_key, &get_value) == -1); assert(PyErr_ExceptionMatches(PyExc_TypeError)); PyErr_Clear(); assert(get_value == NULL); Py_DECREF(dict); Py_DECREF(key); Py_DECREF(missing_key); Py_DECREF(value); Py_DECREF(invalid_key); Py_RETURN_NONE; error: Py_XDECREF(dict); Py_XDECREF(key); Py_XDECREF(missing_key); Py_XDECREF(value); Py_XDECREF(invalid_key); return NULL; } static PyObject * test_dict_pop(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { PyObject *dict = PyDict_New(); if (dict == NULL) { return NULL; } PyObject *key = PyUnicode_FromString("key"); assert(key != NULL); PyObject *value = PyUnicode_FromString("abc"); assert(value != NULL); // test PyDict_Pop(), get the removed value, key is present assert(PyDict_SetItem(dict, key, value) == 0); PyObject *removed = UNINITIALIZED_OBJ; assert(PyDict_Pop(dict, key, &removed) == 1); assert(removed == value); Py_DECREF(removed); // test PyDict_Pop(), ignore the removed value, key is present assert(PyDict_SetItem(dict, key, value) == 0); assert(PyDict_Pop(dict, key, NULL) == 1); // test PyDict_Pop(), key is missing removed = UNINITIALIZED_OBJ; assert(PyDict_Pop(dict, key, &removed) == 0); assert(removed == NULL); assert(PyDict_Pop(dict, key, NULL) == 0); // test PyDict_PopString(), get the removed value, key is present assert(PyDict_SetItem(dict, key, value) == 0); removed = UNINITIALIZED_OBJ; assert(PyDict_PopString(dict, "key", &removed) == 1); assert(removed == value); Py_DECREF(removed); // test PyDict_PopString(), ignore the removed value, key is present assert(PyDict_SetItem(dict, key, value) == 0); assert(PyDict_PopString(dict, "key", NULL) == 1); // test PyDict_PopString(), key is missing removed = UNINITIALIZED_OBJ; assert(PyDict_PopString(dict, "key", &removed) == 0); assert(removed == NULL); assert(PyDict_PopString(dict, "key", NULL) == 0); // dict error removed = UNINITIALIZED_OBJ; assert(PyDict_Pop(key, key, &removed) == -1); assert(removed == NULL); assert(PyErr_ExceptionMatches(PyExc_SystemError)); PyErr_Clear(); assert(PyDict_Pop(key, key, NULL) == -1); assert(PyErr_ExceptionMatches(PyExc_SystemError)); PyErr_Clear(); removed = UNINITIALIZED_OBJ; assert(PyDict_PopString(key, "key", &removed) == -1); assert(removed == NULL); assert(PyErr_ExceptionMatches(PyExc_SystemError)); PyErr_Clear(); assert(PyDict_PopString(key, "key", NULL) == -1); assert(PyErr_ExceptionMatches(PyExc_SystemError)); PyErr_Clear(); // exit Py_DECREF(dict); Py_DECREF(key); Py_DECREF(value); Py_RETURN_NONE; } static PyObject * test_dict_setdefault(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { PyObject *dict = PyDict_New(); if (dict == NULL) { return NULL; } PyObject *key = PyUnicode_FromString("key"); assert(key != NULL); PyObject *value = PyUnicode_FromString("abc"); assert(value != NULL); PyObject *invalid_key = PyList_New(0); // not hashable key assert(invalid_key != NULL); // insert item PyObject *result = UNINITIALIZED_OBJ; assert(PyDict_SetDefaultRef(dict, key, value, &result) == 0); assert(result == value); Py_DECREF(result); // item already present result = UNINITIALIZED_OBJ; assert(PyDict_SetDefaultRef(dict, key, value, &result) == 1); assert(result == value); Py_DECREF(result); // error: invalid key assert(!PyErr_Occurred()); result = UNINITIALIZED_OBJ; assert(PyDict_SetDefaultRef(dict, invalid_key, value, &result) == -1); assert(result == NULL); assert(PyErr_Occurred()); PyErr_Clear(); // insert item with NULL result assert(PyDict_Pop(dict, key, NULL) == 1); assert(PyDict_SetDefaultRef(dict, key, value, NULL) == 0); // item already present with NULL result assert(PyDict_SetDefaultRef(dict, key, value, NULL) == 1); // error: invalid key with NULL result assert(!PyErr_Occurred()); assert(PyDict_SetDefaultRef(dict, invalid_key, value, NULL) == -1); assert(PyErr_Occurred()); PyErr_Clear(); // exit Py_DECREF(dict); Py_DECREF(key); Py_DECREF(value); Py_DECREF(invalid_key); Py_RETURN_NONE; } static PyObject * test_long_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { // test PyLong_AsInt() assert(!PyErr_Occurred()); PyObject *obj = PyLong_FromLong(123); if (obj == NULL) { return NULL; } int value = PyLong_AsInt(obj); assert(value == 123); assert(!PyErr_Occurred()); Py_DECREF(obj); // test PyLong_AsInt() with overflow PyObject *obj2 = PyLong_FromLongLong((long long)INT_MAX + 1); if (obj2 == NULL) { return NULL; } value = PyLong_AsInt(obj2); assert(value == -1); assert(PyErr_ExceptionMatches(PyExc_OverflowError)); PyErr_Clear(); Py_DECREF(obj2); // test PyLong_GetSign() int sign = UNINITIALIZED_INT; assert(PyLong_GetSign(obj, &sign) == 0); assert(sign == 1); // test PyLong_IsPositive(), PyLong_IsNegative() and PyLong_IsZero() assert(PyLong_IsPositive(obj) == 1); assert(PyLong_IsNegative(obj) == 0); assert(PyLong_IsZero(obj) == 0); #if defined(PYTHON3) && !defined(PYPY_VERSION) // test import/export API digit *digits; PyLongWriter *writer; static PyLongExport long_export; writer = PyLongWriter_Create(1, 1, (void**)&digits); PyLongWriter_Discard(writer); writer = PyLongWriter_Create(1, 1, (void**)&digits); digits[0] = 123; obj = PyLongWriter_Finish(writer); check_int(obj, -123); PyLong_Export(obj, &long_export); assert(long_export.value == -123); assert(long_export.digits == NULL); PyLong_FreeExport(&long_export); Py_DECREF(obj); writer = PyLongWriter_Create(0, 5, (void**)&digits); digits[0] = 1; digits[1] = 0; digits[2] = 0; digits[3] = 0; digits[4] = 1; obj = PyLongWriter_Finish(writer); PyLong_Export(obj, &long_export); assert(long_export.value == 0); digits = (digit*)long_export.digits; assert(digits[0] == 1); assert(digits[1] == 0); assert(digits[2] == 0); assert(digits[3] == 0); assert(digits[4] == 1); PyLong_FreeExport(&long_export); Py_DECREF(obj); const PyLongLayout *layout = PyLong_GetNativeLayout(); assert(layout->digits_order == -1); assert(layout->digit_size == sizeof(digit)); #endif // defined(PYTHON3) && !defined(PYPY_VERSION) Py_RETURN_NONE; } // --- HeapCTypeWithManagedDict -------------------------------------------- // Py_TPFLAGS_MANAGED_DICT was added to Python 3.11.0a3 but is not implemented on PyPy #if PY_VERSION_HEX >= 0x030B00A3 && ! defined(PYPY_VERSION) # define TEST_MANAGED_DICT typedef struct { PyObject_HEAD } HeapCTypeObject; static int heapmanaged_traverse(PyObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); // Test PyObject_VisitManagedDict() return PyObject_VisitManagedDict(self, visit, arg); } static int heapmanaged_clear(PyObject *self) { // Test PyObject_ClearManagedDict() PyObject_ClearManagedDict(self); return 0; } static void heapmanaged_dealloc(HeapCTypeObject *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_ClearManagedDict((PyObject *)self); PyObject_GC_UnTrack(self); PyObject_GC_Del(self); Py_DECREF(tp); } static PyType_Slot HeapCTypeWithManagedDict_slots[] = { {Py_tp_traverse, _Py_CAST(void*, heapmanaged_traverse)}, {Py_tp_clear, _Py_CAST(void*, heapmanaged_clear)}, {Py_tp_dealloc, _Py_CAST(void*, heapmanaged_dealloc)}, {0, 0}, }; static PyType_Spec HeapCTypeWithManagedDict_spec = { "test_pythoncapi_compat.HeapCTypeWithManagedDict", sizeof(PyObject), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT, HeapCTypeWithManagedDict_slots }; static PyObject * test_managed_dict(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { // Test PyObject_VisitManagedDict() and PyObject_ClearManagedDict() PyObject *type = PyType_FromSpec(&HeapCTypeWithManagedDict_spec); if (type == NULL) { return NULL; } PyObject *obj = PyObject_CallNoArgs(type); if (obj == NULL) { Py_DECREF(type); return NULL; } // call heapmanaged_traverse() PyGC_Collect(); // call heapmanaged_clear() Py_DECREF(obj); PyGC_Collect(); Py_DECREF(type); // Just in case! PyGC_Collect(); Py_RETURN_NONE; } #endif // PY_VERSION_HEX >= 0x030B00A3 static PyObject * test_unicode(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { PyObject *abc = PyUnicode_FromString("abc"); if (abc == NULL) { return NULL; } PyObject *abc0def = PyUnicode_FromStringAndSize("abc\0def", 7); if (abc0def == NULL) { Py_DECREF(abc); return NULL; } // PyUnicode_EqualToUTF8() and PyUnicode_EqualToUTF8AndSize() can be called // with an exception raised and they must not clear the current exception. PyErr_NoMemory(); assert(PyUnicode_EqualToUTF8AndSize(abc, "abc", 3) == 1); assert(PyUnicode_EqualToUTF8AndSize(abc, "Python", 6) == 0); assert(PyUnicode_EqualToUTF8AndSize(abc0def, "abc\0def", 7) == 1); assert(PyUnicode_EqualToUTF8(abc, "abc") == 1); assert(PyUnicode_EqualToUTF8(abc, "Python") == 0); assert(PyUnicode_EqualToUTF8(abc0def, "abc\0def") == 0); assert(PyErr_ExceptionMatches(PyExc_MemoryError)); PyErr_Clear(); // Test PyUnicode_Equal() assert(PyUnicode_Equal(abc, abc) == 1); assert(PyUnicode_Equal(abc, abc0def) == 0); assert(PyUnicode_Equal(abc, Py_True) == -1); assert(PyErr_ExceptionMatches(PyExc_TypeError)); PyErr_Clear(); Py_DECREF(abc); Py_DECREF(abc0def); Py_RETURN_NONE; } static PyObject * test_list(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { PyObject *list = PyList_New(0); if (list == NULL) { return NULL; } // test PyList_Extend() { PyObject *abc = PyUnicode_FromString("abc"); if (abc == NULL) { Py_DECREF(list); return NULL; } assert(PyList_Extend(list, abc) == 0); Py_DECREF(abc); assert(PyList_GET_SIZE(list) == 3); } // test PyList_GetItemRef() PyObject *item = PyList_GetItemRef(list, 1); assert(item != NULL); assert(item == PyList_GetItem(list, 1)); Py_DECREF(item); // test PyList_Clear() assert(PyList_Clear(list) == 0); assert(PyList_GET_SIZE(list) == 0); Py_DECREF(list); Py_RETURN_NONE; } static PyObject * test_hash(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { void *ptr0 = NULL; assert(Py_HashPointer(ptr0) == 0); #ifndef PYPY_VERSION #if SIZEOF_VOID_P == 8 void *ptr1 = (void*)(uintptr_t)0xABCDEF1234567890; assert(Py_HashPointer(ptr1) == (uintptr_t)0x0ABCDEF123456789); #else void *ptr1 = (void*)(uintptr_t)0xDEADCAFE; assert(Py_HashPointer(ptr1) == (uintptr_t)0xEDEADCAF); #endif #else // PyPy #if SIZEOF_VOID_P == 8 void *ptr1 = (void*)(uintptr_t)0xABCDEF1234567890; #else void *ptr1 = (void*)(uintptr_t)0xDEADCAFE; #endif assert(Py_HashPointer(ptr1) == (Py_hash_t)ptr1); #endif #if ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \ || (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \ && PYPY_VERSION_NUM >= 0x07030800)) // Just check that constants are available size_t bits = PyHASH_BITS; assert(bits >= 8); size_t mod = PyHASH_MODULUS; assert(mod >= 7); size_t inf = PyHASH_INF; assert(inf != 0); size_t imag = PyHASH_IMAG; assert(imag != 0); #endif // Test Py_HashBuffer() { PyObject *abc = PyBytes_FromString("abc"); if (abc == NULL) { return NULL; } Py_hash_t hash = Py_HashBuffer(PyBytes_AS_STRING(abc), PyBytes_GET_SIZE(abc)); Py_hash_t hash2 = PyObject_Hash(abc); assert(hash == hash2); Py_DECREF(abc); } Py_RETURN_NONE; } #if PY_VERSION_HEX >= 0x03050000 #define TEST_PYTIME static PyObject * test_time(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { PyTime_t t; #define UNINITIALIZED_TIME ((PyTime_t)-483884113929936179) t = UNINITIALIZED_TIME; assert(PyTime_Time(&t) == 0); assert(t != UNINITIALIZED_TIME); t = UNINITIALIZED_TIME; assert(PyTime_Monotonic(&t) == 0); assert(t != UNINITIALIZED_TIME); // Test multiple times since an implementation uses a cache for (int i=0; i < 5; i++) { t = UNINITIALIZED_TIME; assert(PyTime_PerfCounter(&t) == 0); assert(t != UNINITIALIZED_TIME); } assert(PyTime_AsSecondsDouble(1) == 1e-9); assert(PyTime_AsSecondsDouble(1500 * 1000 * 1000) == 1.5); assert(PyTime_AsSecondsDouble(-500 * 1000 * 1000) == -0.5); Py_RETURN_NONE; } #endif static void check_get_constant(PyObject* (*get_constant)(unsigned int), int borrowed) { #define CLEAR(var) if (!borrowed) { Py_DECREF(var); } PyObject *obj, *expected; // Py_CONSTANT_NONE obj = get_constant(Py_CONSTANT_NONE); assert(obj == Py_None); CLEAR(obj); // Py_CONSTANT_FALSE obj = get_constant(Py_CONSTANT_FALSE); assert(obj == Py_False); CLEAR(obj); // Py_CONSTANT_TRUE obj = get_constant(Py_CONSTANT_TRUE); assert(obj == Py_True); CLEAR(obj); // Py_CONSTANT_ELLIPSIS obj = get_constant(Py_CONSTANT_ELLIPSIS); assert(obj == Py_Ellipsis); CLEAR(obj); // Py_CONSTANT_NOT_IMPLEMENTED obj = get_constant(Py_CONSTANT_NOT_IMPLEMENTED); assert(obj == Py_NotImplemented); CLEAR(obj); // Py_CONSTANT_ZERO obj = get_constant(Py_CONSTANT_ZERO); expected = PyLong_FromLong(0); assert(expected != NULL); assert(Py_TYPE(obj) == &PyLong_Type); assert(PyObject_RichCompareBool(obj, expected, Py_EQ) == 1); CLEAR(obj); Py_DECREF(expected); // Py_CONSTANT_ONE obj = get_constant(Py_CONSTANT_ONE); expected = PyLong_FromLong(1); assert(expected != NULL); assert(Py_TYPE(obj) == &PyLong_Type); assert(PyObject_RichCompareBool(obj, expected, Py_EQ) == 1); CLEAR(obj); Py_DECREF(expected); // Py_CONSTANT_EMPTY_STR obj = get_constant(Py_CONSTANT_EMPTY_STR); assert(Py_TYPE(obj) == &PyUnicode_Type); #if PY_VERSION_HEX >= 0x03030000 assert(PyUnicode_GetLength(obj) == 0); #else assert(PyUnicode_GetSize(obj) == 0); #endif CLEAR(obj); // Py_CONSTANT_EMPTY_BYTES obj = get_constant(Py_CONSTANT_EMPTY_BYTES); assert(Py_TYPE(obj) == &PyBytes_Type); assert(PyBytes_Size(obj) == 0); CLEAR(obj); // Py_CONSTANT_EMPTY_TUPLE obj = get_constant(Py_CONSTANT_EMPTY_TUPLE); assert(Py_TYPE(obj) == &PyTuple_Type); assert(PyTuple_Size(obj) == 0); CLEAR(obj); #undef CLEAR } static PyObject * test_get_constant(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { check_get_constant(Py_GetConstant, 0); check_get_constant(Py_GetConstantBorrowed, 1); Py_RETURN_NONE; } #if PY_VERSION_HEX < 0x030E0000 && PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION) #define TEST_UNICODEWRITER 1 static PyObject * test_unicodewriter(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); if (writer == NULL) { return NULL; } int ret; // test PyUnicodeWriter_WriteStr() PyObject *str = PyUnicode_FromString("var"); if (str == NULL) { goto error; } ret = PyUnicodeWriter_WriteStr(writer, str); Py_CLEAR(str); if (ret < 0) { goto error; } // test PyUnicodeWriter_WriteChar() if (PyUnicodeWriter_WriteChar(writer, '=') < 0) { goto error; } // test PyUnicodeWriter_WriteSubstring() str = PyUnicode_FromString("[long]"); if (str == NULL) { goto error; } ret = PyUnicodeWriter_WriteSubstring(writer, str, 1, 5); Py_CLEAR(str); if (ret < 0) { goto error; } // test PyUnicodeWriter_WriteUTF8() if (PyUnicodeWriter_WriteUTF8(writer, " valu\xC3\xA9", -1) < 0) { goto error; } if (PyUnicodeWriter_WriteChar(writer, ' ') < 0) { goto error; } // test PyUnicodeWriter_WriteRepr() str = PyUnicode_FromString("repr"); if (str == NULL) { goto error; } if (PyUnicodeWriter_WriteRepr(writer, str) < 0) { goto error; } Py_CLEAR(str); { PyObject *result = PyUnicodeWriter_Finish(writer); if (result == NULL) { return NULL; } assert(PyUnicode_EqualToUTF8(result, "var=long valu\xC3\xA9 'repr'")); Py_DECREF(result); } Py_RETURN_NONE; error: PyUnicodeWriter_Discard(writer); return NULL; } static PyObject * test_unicodewriter_widechar(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); if (writer == NULL) { return NULL; } // test PyUnicodeWriter_WriteWideChar() int ret = PyUnicodeWriter_WriteWideChar(writer, L"euro=\u20AC", -1); if (ret < 0) { goto error; } { PyObject *result = PyUnicodeWriter_Finish(writer); if (result == NULL) { return NULL; } assert(PyUnicode_EqualToUTF8(result, "euro=\xe2\x82\xac")); Py_DECREF(result); } Py_RETURN_NONE; error: PyUnicodeWriter_Discard(writer); return NULL; } static PyObject * test_unicodewriter_format(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); if (writer == NULL) { return NULL; } // test PyUnicodeWriter_Format() if (PyUnicodeWriter_Format(writer, "%s %i", "Hello", 123) < 0) { goto error; } // test PyUnicodeWriter_WriteChar() if (PyUnicodeWriter_WriteChar(writer, '.') < 0) { goto error; } { PyObject *result = PyUnicodeWriter_Finish(writer); if (result == NULL) { return NULL; } assert(PyUnicode_EqualToUTF8(result, "Hello 123.")); Py_DECREF(result); } Py_RETURN_NONE; error: PyUnicodeWriter_Discard(writer); return NULL; } #endif static PyObject * test_bytes(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { // Test PyBytes_Join() PyObject *abc = PyBytes_FromString("a b c"); if (abc == NULL) { return NULL; } PyObject *list = PyObject_CallMethod(abc, "split", NULL); Py_DECREF(abc); if (list == NULL) { return NULL; } PyObject *sep = PyBytes_FromString("-"); if (sep == NULL) { Py_DECREF(list); return NULL; } PyObject *join = PyBytes_Join(sep, list); assert(join != NULL); assert(PyBytes_Check(join)); assert(memcmp(PyBytes_AS_STRING(join), "a-b-c", 5) == 0); Py_DECREF(join); Py_DECREF(list); Py_DECREF(sep); Py_RETURN_NONE; } static PyObject * test_iter(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { // Test PyIter_NextItem() PyObject *tuple = Py_BuildValue("(i)", 123); if (tuple == NULL) { return NULL; } PyObject *iter = PyObject_GetIter(tuple); Py_DECREF(tuple); if (iter == NULL) { return NULL; } // first item PyObject *item = UNINITIALIZED_OBJ; assert(PyIter_NextItem(iter, &item) == 1); { PyObject *expected = PyLong_FromLong(123); assert(PyObject_RichCompareBool(item, expected, Py_EQ) == 1); assert(expected != NULL); Py_DECREF(expected); } // StopIteration item = UNINITIALIZED_OBJ; assert(PyIter_NextItem(iter, &item) == 0); assert(item == NULL); assert(!PyErr_Occurred()); // non-iterable object item = UNINITIALIZED_OBJ; assert(PyIter_NextItem(Py_None, &item) == -1); assert(item == NULL); assert(PyErr_ExceptionMatches(PyExc_TypeError)); PyErr_Clear(); Py_DECREF(iter); Py_RETURN_NONE; } static PyObject * test_long_stdint(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { PyObject *obj; // Test PyLong_FromInt32() and PyLong_AsInt32() obj = PyLong_FromInt32(INT32_C(-0x12345678)); assert(obj != NULL); int32_t i32; assert(PyLong_AsInt32(obj, &i32) == 0); assert(i32 == INT32_C(-0x12345678)); Py_DECREF(obj); // Test PyLong_FromUInt32() and PyLong_AsUInt32() obj = PyLong_FromUInt32(UINT32_C(0xDEADBEEF)); assert(obj != NULL); uint32_t u32; assert(PyLong_AsUInt32(obj, &u32) == 0); assert(u32 == UINT32_C(0xDEADBEEF)); Py_DECREF(obj); // Test PyLong_FromInt64() and PyLong_AsInt64() obj = PyLong_FromInt64(INT64_C(-0x12345678DEADBEEF)); assert(obj != NULL); int64_t i64; assert(PyLong_AsInt64(obj, &i64) == 0); assert(i64 == INT64_C(-0x12345678DEADBEEF)); Py_DECREF(obj); // Test PyLong_FromUInt64() and PyLong_AsUInt64() obj = PyLong_FromUInt64(UINT64_C(0xDEADBEEF12345678)); assert(obj != NULL); uint64_t u64; assert(PyLong_AsUInt64(obj, &u64) == 0); assert(u64 == UINT64_C(0xDEADBEEF12345678)); Py_DECREF(obj); Py_RETURN_NONE; } static PyObject * test_structmember(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { assert(Py_T_SHORT >= 0); assert(Py_T_INT >= 0); assert(Py_T_LONG >= 0); assert(Py_T_FLOAT >= 0); assert(Py_T_DOUBLE >= 0); assert(Py_T_STRING >= 0); assert(_Py_T_OBJECT >= 0); assert(Py_T_CHAR >= 0); assert(Py_T_BYTE >= 0); assert(Py_T_UBYTE >= 0); assert(Py_T_USHORT >= 0); assert(Py_T_UINT >= 0); assert(Py_T_ULONG >= 0); assert(Py_T_STRING_INPLACE >= 0); assert(Py_T_BOOL >= 0); assert(Py_T_OBJECT_EX >= 0); assert(Py_T_LONGLONG >= 0); assert(Py_T_ULONGLONG >= 0); assert(Py_T_PYSSIZET >= 0); #if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION) assert(_Py_T_NONE >= 0); #endif assert(Py_READONLY >= 0); assert(Py_AUDIT_READ >= 0); assert(_Py_WRITE_RESTRICTED >= 0); Py_RETURN_NONE; } static PyObject * test_file(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { const char *filename = __FILE__; PyObject *path = create_string(filename); FILE *fp = Py_fopen(path, "rb"); Py_DECREF(path); assert(fp != NULL); Py_fclose(fp); Py_RETURN_NONE; } #if 0x03090000 <= PY_VERSION_HEX && !defined(PYPY_VERSION) static PyObject * test_config(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { // Test PyConfig_Get() PyObject *sys = PyImport_ImportModule("sys"); if (sys == _Py_NULL) { return _Py_NULL; } PyObject *obj = PyConfig_Get("argv"); PyObject *sys_attr = PyObject_GetAttrString(sys, "argv"); assert(obj == sys_attr); Py_DECREF(obj); Py_DECREF(sys_attr); obj = PyConfig_Get("module_search_paths"); sys_attr = PyObject_GetAttrString(sys, "path"); assert(obj == sys_attr); Py_DECREF(obj); Py_DECREF(sys_attr); obj = PyConfig_Get("xoptions"); sys_attr = PyObject_GetAttrString(sys, "_xoptions"); assert(obj == sys_attr); Py_DECREF(obj); Py_DECREF(sys_attr); obj = PyConfig_Get("use_environment"); assert(PyBool_Check(obj)); Py_DECREF(obj); obj = PyConfig_Get("verbose"); assert(PyLong_Check(obj)); Py_DECREF(obj); // Get the last member #if 0x030A0000 <= PY_VERSION_HEX obj = PyConfig_Get("warn_default_encoding"); #else obj = PyConfig_Get("user_site_directory"); #endif assert(PyLong_Check(obj)); Py_DECREF(obj); assert(PyConfig_Get("nonexistent") == NULL); assert(PyErr_ExceptionMatches(PyExc_ValueError)); PyErr_Clear(); // Test PyConfig_GetInt() int value = -3; assert(PyConfig_GetInt("verbose", &value) == 0); assert(value >= 0); assert(PyConfig_GetInt("argv", &value) == -1); assert(PyErr_ExceptionMatches(PyExc_TypeError)); PyErr_Clear(); assert(PyConfig_GetInt("nonexistent", &value) == -1); assert(PyErr_ExceptionMatches(PyExc_ValueError)); PyErr_Clear(); Py_DECREF(sys); Py_RETURN_NONE; } #endif static struct PyMethodDef methods[] = { {"test_object", test_object, METH_NOARGS, _Py_NULL}, {"test_py_is", test_py_is, METH_NOARGS, _Py_NULL}, #ifndef PYPY_VERSION {"test_frame", test_frame, METH_NOARGS, _Py_NULL}, #endif {"test_thread_state", test_thread_state, METH_NOARGS, _Py_NULL}, {"test_interpreter", test_interpreter, METH_NOARGS, _Py_NULL}, {"test_calls", test_calls, METH_NOARGS, _Py_NULL}, {"test_gc", test_gc, METH_NOARGS, _Py_NULL}, {"test_module", test_module, METH_NOARGS, _Py_NULL}, #if (PY_VERSION_HEX <= 0x030B00A1 || 0x030B00A7 <= PY_VERSION_HEX) && !defined(PYPY_VERSION) {"test_float_pack", test_float_pack, METH_NOARGS, _Py_NULL}, #endif #ifndef PYPY_VERSION {"test_code", test_code, METH_NOARGS, _Py_NULL}, #endif {"test_api_casts", test_api_casts, METH_NOARGS, _Py_NULL}, {"test_import", test_import, METH_NOARGS, _Py_NULL}, {"test_weakref", test_weakref, METH_NOARGS, _Py_NULL}, {"func_varargs", (PyCFunction)(void*)func_varargs, METH_VARARGS | METH_KEYWORDS, _Py_NULL}, {"test_vectorcall", test_vectorcall, METH_NOARGS, _Py_NULL}, {"test_getattr", test_getattr, METH_NOARGS, _Py_NULL}, {"test_getitem", test_getitem, METH_NOARGS, _Py_NULL}, {"test_dict_api", test_dict_api, METH_NOARGS, _Py_NULL}, {"test_dict_pop", test_dict_pop, METH_NOARGS, _Py_NULL}, {"test_dict_setdefault", test_dict_setdefault, METH_NOARGS, _Py_NULL}, {"test_long_api", test_long_api, METH_NOARGS, _Py_NULL}, #ifdef TEST_MANAGED_DICT {"test_managed_dict", test_managed_dict, METH_NOARGS, _Py_NULL}, #endif {"test_unicode", test_unicode, METH_NOARGS, _Py_NULL}, {"test_list", test_list, METH_NOARGS, _Py_NULL}, {"test_hash", test_hash, METH_NOARGS, _Py_NULL}, #ifdef TEST_PYTIME {"test_time", test_time, METH_NOARGS, _Py_NULL}, #endif {"test_get_constant", test_get_constant, METH_NOARGS, _Py_NULL}, #ifdef TEST_UNICODEWRITER {"test_unicodewriter", test_unicodewriter, METH_NOARGS, _Py_NULL}, {"test_unicodewriter_widechar", test_unicodewriter_widechar, METH_NOARGS, _Py_NULL}, {"test_unicodewriter_format", test_unicodewriter_format, METH_NOARGS, _Py_NULL}, #endif {"test_bytes", test_bytes, METH_NOARGS, _Py_NULL}, {"test_iter", test_iter, METH_NOARGS, _Py_NULL}, {"test_long_stdint", test_long_stdint, METH_NOARGS, _Py_NULL}, {"test_structmember", test_structmember, METH_NOARGS, _Py_NULL}, {"test_file", test_file, METH_NOARGS, _Py_NULL}, #if 0x03090000 <= PY_VERSION_HEX && !defined(PYPY_VERSION) {"test_config", test_config, METH_NOARGS, _Py_NULL}, #endif {_Py_NULL, _Py_NULL, 0, _Py_NULL} }; static int module_exec(PyObject *module) { #ifdef __cplusplus if (PyModule_AddIntMacro(module, __cplusplus)) { return -1; } #endif if (PyModule_AddStringMacro(module, PY_VERSION)) { return -1; } if (PyModule_AddIntMacro(module, PY_VERSION_HEX)) { return -1; } #ifdef PYPY_VERSION if (PyModule_AddStringMacro(module, PYPY_VERSION)) { return -1; } #endif #ifdef PYPY_VERSION_NUM if (PyModule_AddIntMacro(module, PYPY_VERSION_NUM)) { return -1; } #endif return 0; } #if PY_VERSION_HEX >= 0x03050000 static PyModuleDef_Slot module_slots[] = { {Py_mod_exec, _Py_CAST(void*, module_exec)}, {0, _Py_NULL} }; #endif #ifdef PYTHON3 static struct PyModuleDef module_def = { PyModuleDef_HEAD_INIT, MODULE_NAME_STR, // m_name _Py_NULL, // m_doc 0, // m_size methods, // m_methods #if PY_VERSION_HEX >= 0x03050000 module_slots, // m_slots #else _Py_NULL, // m_reload #endif _Py_NULL, // m_traverse _Py_NULL, // m_clear _Py_NULL, // m_free }; #define INIT_FUNC CONCAT(PyInit_, MODULE_NAME) #if PY_VERSION_HEX >= 0x03050000 PyMODINIT_FUNC INIT_FUNC(void) { return PyModuleDef_Init(&module_def); } #else // Python 3.4 PyMODINIT_FUNC INIT_FUNC(void) { PyObject *module = PyModule_Create(&module_def); if (module == _Py_NULL) { return _Py_NULL; } if (module_exec(module) < 0) { Py_DECREF(module); return _Py_NULL; } return module; } #endif #else // Python 2 #define INIT_FUNC CONCAT(init, MODULE_NAME) PyMODINIT_FUNC INIT_FUNC(void) { PyObject *module; module = Py_InitModule4(MODULE_NAME_STR, methods, _Py_NULL, _Py_NULL, PYTHON_API_VERSION); if (module == _Py_NULL) { return; } if (module_exec(module) < 0) { return; } } #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3653042 pygobject-3.54.5/subprojects/pythoncapi-compat/tests/test_pythoncapi_compat_cppext.cpp0000644000000000000000000000027215074677100030357 0ustar00rootroot// C++ flavor of the C extension. // Reuse the whole C source code using an #include, but the file has ".cpp" // extension to use a C++ builder. #include "test_pythoncapi_compat_cext.c" ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3653042 pygobject-3.54.5/subprojects/pythoncapi-compat/tests/test_upgrade_pythoncapi.py0000644000000000000000000006552015074677100027015 0ustar00rootroot#!/usr/bin/env python3 import io import os import sys import tempfile import textwrap import unittest # Get upgrade_pythoncapi.py of the parent directory sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) import upgrade_pythoncapi # noqa def operations(disable=None): if isinstance(disable, str): disable = (disable,) elif not disable: disable = () operations = ["all"] for op in upgrade_pythoncapi.EXCLUDE_FROM_ALL: if op.NAME in disable: continue operations.append(op.NAME) for name in disable: operations.append(f'-{name}') operations = ','.join(operations) return operations def patch(source, no_compat=False, disable=None): args = ['script', 'mod.c', '-o', operations(disable=disable)] if no_compat: args.append('--no-compat') patcher = upgrade_pythoncapi.Patcher(args) return patcher.patch(source) def reformat(source): return textwrap.dedent(source).strip() class Tests(unittest.TestCase): maxDiff = 80 * 30 def _test_patch_file(self, tmp_dir): # test Patcher.patcher() source = """ PyTypeObject* test_type(PyObject *obj, PyTypeObject *type) { Py_TYPE(obj) = type; return Py_TYPE(obj); } """ expected = """ #include "pythoncapi_compat.h" PyTypeObject* test_type(PyObject *obj, PyTypeObject *type) { Py_SET_TYPE(obj, type); return Py_TYPE(obj); } """ source = reformat(source) expected = reformat(expected) filename = tempfile.mktemp(suffix='.c', dir=tmp_dir) old_filename = filename + ".old" try: with open(filename, "w", encoding="utf-8") as fp: fp.write(source) old_stderr = sys.stderr old_argv = list(sys.argv) try: # redirect stderr sys.stderr = io.StringIO() if tmp_dir is not None: arg = tmp_dir else: arg = filename sys.argv = ['script', arg] try: upgrade_pythoncapi.Patcher().main() except SystemExit as exc: self.assertEqual(exc.code, 0) else: self.fail("SystemExit not raised") finally: sys.stderr = old_stderr sys.argv = old_argv with open(filename, encoding="utf-8") as fp: new_contents = fp.read() with open(old_filename, encoding="utf-8") as fp: old_contents = fp.read() finally: try: os.unlink(filename) except FileNotFoundError: pass try: os.unlink(old_filename) except FileNotFoundError: pass self.assertEqual(new_contents, expected) self.assertEqual(old_contents, source) def test_patch_file(self): self._test_patch_file(None) def test_patch_directory(self): with tempfile.TemporaryDirectory() as tmp_dir: self._test_patch_file(tmp_dir) def check_replace(self, source, expected, **kwargs): source = reformat(source) expected = reformat(expected) self.assertEqual(patch(source, **kwargs), expected) def check_dont_replace(self, source, disable=None): source = reformat(source) self.assertEqual(patch(source, disable=disable), source) def test_expr_regex(self): # Test EXPR_REGEX self.check_replace("a->b->ob_type", "Py_TYPE(a->b)") self.check_replace("a.b->ob_type", "Py_TYPE(a.b)") self.check_replace("array[2]->ob_type", "Py_TYPE(array[2])") # Don't match function calls self.check_dont_replace("func()->ob_type") def test_pythoncapi_compat(self): # If pythoncapi_compat.h is included, avoid compatibility includes # and macros. # # Otherise, Py_SET_TYPE() requires a macro and PyFrame_GetBack() # requires 2 macros and an include. HEADERS = ( '', '"pythoncapi_compat.h"', ) for header in HEADERS: # There is no empty line between the include and the function # on purpose. self.check_replace(""" #include %s void test_set_type(PyObject *obj, PyTypeObject *type) { Py_TYPE(obj) = type; } PyFrameObject* frame_back_borrowed(PyFrameObject *frame) { return frame->f_back; } """ % header, """ #include %s void test_set_type(PyObject *obj, PyTypeObject *type) { Py_SET_TYPE(obj, type); } PyFrameObject* frame_back_borrowed(PyFrameObject *frame) { return _PyFrame_GetBackBorrow(frame); } """ % header) def test_py_type(self): source = """ PyTypeObject* get_type(PyObject *obj) { return obj->ob_type; } """ expected = """ PyTypeObject* get_type(PyObject *obj) { return Py_TYPE(obj); } """ self.check_replace(source, expected) def test_py_size(self): source = """ Py_ssize_t get_size(PyVarObject *obj) { return obj->ob_size; } """ expected = """ Py_ssize_t get_size(PyVarObject *obj) { return Py_SIZE(obj); } """ self.check_replace(source, expected) def test_py_refcnt(self): source = """ Py_ssize_t get_refcnt(PyObject *obj) { return obj->ob_refcnt; } """ expected = """ Py_ssize_t get_refcnt(PyObject *obj) { return Py_REFCNT(obj); } """ self.check_replace(source, expected) def test_py_set_type(self): source = """ void test_type(PyObject *obj, PyTypeObject *type) { obj->ob_type = type; Py_TYPE(obj) = type; } """ expected = """ #include "pythoncapi_compat.h" void test_type(PyObject *obj, PyTypeObject *type) { Py_SET_TYPE(obj, type); Py_SET_TYPE(obj, type); } """ self.check_replace(source, expected) self.check_dont_replace(""" PyTypeObject* get_type(PyObject *obj, PyTypeObject *check_type) { assert(Py_TYPE(args) == check_type); return Py_TYPE(obj); } """) def test_py_set_size(self): source = """\ void test_size(PyVarObject *obj) { obj->ob_size = 3; Py_SIZE(obj) = 4; } """ expected = """\ #include "pythoncapi_compat.h" void test_size(PyVarObject *obj) { Py_SET_SIZE(obj, 3); Py_SET_SIZE(obj, 4); } """ self.check_replace(source, expected) self.check_dont_replace(""" Py_ssize_t get_size(PyObject *obj) { assert(Py_SIZE(args) == 1); return Py_SIZE(obj); } """) def test_py_set_refcnt(self): source = """\ void set_refcnt(PyObject *obj) { obj->ob_refcnt = 1; Py_REFCNT(obj) = 2; } """ expected = """\ #include "pythoncapi_compat.h" void set_refcnt(PyObject *obj) { Py_SET_REFCNT(obj, 1); Py_SET_REFCNT(obj, 2); } """ self.check_replace(source, expected) self.check_dont_replace(""" Py_ssize_t get_refcnt(PyObject *obj) { assert(Py_REFCNT(args) == 1); return Py_REFCNT(obj); } """) def test_pyobject_new(self): source = """\ capsule = PyObject_NEW(PyCapsule, &PyCapsule_Type); pattern = PyObject_NEW_VAR(PatternObject, Pattern_Type, n); """ expected = """\ capsule = PyObject_New(PyCapsule, &PyCapsule_Type); pattern = PyObject_NewVar(PatternObject, Pattern_Type, n); """ self.check_replace(source, expected) self.check_dont_replace(""" func = PyObject_NEW; capsule2 = PyObject_NEW2(PyCapsule, &PyCapsule_Type); func2 = PyObject_NEW_VAR; pattern2 = PyObject_NEW_VAR2(PatternObject, Pattern_Type, n); """) def test_pymem_malloc(self): source = """\ void *ptr = PyMem_MALLOC(10); ptr = PyMem_REALLOC(ptr, 20); PyMem_FREE(ptr); PyMem_DEL(ptr); PyMem_Del(ptr); """ expected = """\ void *ptr = PyMem_Malloc(10); ptr = PyMem_Realloc(ptr, 20); PyMem_Free(ptr); PyMem_Free(ptr); PyMem_Free(ptr); """ self.check_replace(source, expected) def test_pyobject_malloc(self): source = """\ void *ptr = PyObject_MALLOC(10); ptr = PyObject_REALLOC(ptr, 20); PyObject_FREE(ptr); PyObject_DEL(ptr); PyObject_Del(ptr); """ expected = """\ void *ptr = PyObject_Malloc(10); ptr = PyObject_Realloc(ptr, 20); PyObject_Free(ptr); PyObject_Free(ptr); PyObject_Free(ptr); """ self.check_replace(source, expected) def test_pyframe_getback(self): source = """\ PyFrameObject* frame_back_borrowed(PyFrameObject *frame) { return frame->f_back; } """ expected = """\ #include "pythoncapi_compat.h" PyFrameObject* frame_back_borrowed(PyFrameObject *frame) { return _PyFrame_GetBackBorrow(frame); } """ self.check_replace(source, expected) def test_pyframe_getcode(self): self.check_replace("""\ PyCodeObject* frame_code_borrowed(PyFrameObject *frame) { return frame->f_code; } """, """\ #include "pythoncapi_compat.h" PyCodeObject* frame_code_borrowed(PyFrameObject *frame) { return _PyFrame_GetCodeBorrow(frame); } """) def test_get_member_regex(self): # Use PyFrame_GetCode() to test get_member_regex() self.check_dont_replace(""" void frame_set_code(PyFrameObject *frame, PyCodeObject *code) { frame->f_code = code; } void frame_clear_code(PyFrameObject *frame) { Py_CLEAR(frame->f_code); } """) def test_pythreadstate_getinterpreter(self): self.check_replace(""" PyInterpreterState* get_interp(PyThreadState *tstate) { return tstate->interp; } """, """ #include "pythoncapi_compat.h" PyInterpreterState* get_interp(PyThreadState *tstate) { return PyThreadState_GetInterpreter(tstate); } """) def test_pythreadstate_getframe(self): self.check_replace(""" PyFrameObject* get_frame(PyThreadState *tstate) { return tstate->frame; } """, """ #include "pythoncapi_compat.h" PyFrameObject* get_frame(PyThreadState *tstate) { return _PyThreadState_GetFrameBorrow(tstate); } """) def test_py_newref_return(self): self.check_replace(""" PyObject* new_ref(PyObject *obj) { Py_INCREF(obj); return obj; } PyObject* same_line(PyObject *obj) { Py_INCREF(obj); return obj; } PyObject* new_xref(PyObject *obj) { Py_XINCREF(obj); return obj; } PyObject* cast(PyLongObject *obj) { Py_XINCREF(obj); return (PyObject *)obj; } """, """ #include "pythoncapi_compat.h" PyObject* new_ref(PyObject *obj) { return Py_NewRef(obj); } PyObject* same_line(PyObject *obj) { return Py_NewRef(obj); } PyObject* new_xref(PyObject *obj) { return Py_XNewRef(obj); } PyObject* cast(PyLongObject *obj) { return Py_XNewRef(obj); } """) def test_py_newref(self): # INCREF, assign self.check_replace(""" void set_attr(MyStruct *obj, PyObject *value, int test) { // 1 Py_INCREF(value); obj->attr = value; // 2 obj->attr = value; Py_INCREF(value); // 3 obj->attr = value; Py_INCREF(obj->attr); } """, """ #include "pythoncapi_compat.h" void set_attr(MyStruct *obj, PyObject *value, int test) { // 1 obj->attr = Py_NewRef(value); // 2 obj->attr = Py_NewRef(value); // 3 obj->attr = Py_NewRef(value); } """) # Same line self.check_replace(""" void set_attr(MyStruct *obj, PyObject *value, int test) { // same line 1 obj->attr = value; Py_INCREF(value); // same line 2 if (test) { obj->attr = value; Py_INCREF(obj->attr); } // same line 3 if (test) { Py_INCREF(value); obj->attr = value; } } """, """ #include "pythoncapi_compat.h" void set_attr(MyStruct *obj, PyObject *value, int test) { // same line 1 obj->attr = Py_NewRef(value); // same line 2 if (test) { obj->attr = Py_NewRef(value); } // same line 3 if (test) { obj->attr = Py_NewRef(value); } } """) # Cast self.check_replace(""" void set_attr(MyStruct *obj, PyObject *value, int test) { // cast 1 Py_INCREF(value); obj->attr = (PyObject*)value; // cast 2 obj->attr = (PyObject*)value; Py_INCREF(value); // assign var, incref PyCodeObject *code_obj = (PyCodeObject *)code; Py_INCREF(code_obj); // assign var, incref PyCodeObject* code_obj = (PyCodeObject *)code; Py_INCREF(code); // assign var, xincref PyCodeObject * code_obj = (PyCodeObject *)code; Py_XINCREF(code_obj); // incref, assign var Py_INCREF(code); PyCodeObject* code_obj = (PyCodeObject *)code; // xincref, assign var Py_XINCREF(code); PyCodeObject *code_obj = (PyCodeObject *)code; } """, """ #include "pythoncapi_compat.h" void set_attr(MyStruct *obj, PyObject *value, int test) { // cast 1 obj->attr = Py_NewRef(value); // cast 2 obj->attr = Py_NewRef(value); // assign var, incref PyCodeObject *code_obj = (PyCodeObject *)Py_NewRef(code); // assign var, incref PyCodeObject* code_obj = (PyCodeObject *)Py_NewRef(code); // assign var, xincref PyCodeObject * code_obj = (PyCodeObject *)Py_XNewRef(code); // incref, assign var PyCodeObject* code_obj = (PyCodeObject *)Py_NewRef(code); // xincref, assign var PyCodeObject *code_obj = (PyCodeObject *)Py_XNewRef(code); } """) # Py_XINCREF self.check_replace(""" void set_xattr(MyStruct *obj, PyObject *value) { // 1 Py_XINCREF(value); obj->attr = value; // 2 obj->attr = value; Py_XINCREF(value); // 3 obj->attr = value; Py_XINCREF(obj->attr); } """, """ #include "pythoncapi_compat.h" void set_xattr(MyStruct *obj, PyObject *value) { // 1 obj->attr = Py_XNewRef(value); // 2 obj->attr = Py_XNewRef(value); // 3 obj->attr = Py_XNewRef(value); } """) # the first Py_INCREF should be replaced before the second one, # otherwise the first Py_INCREF is not replaced. self.check_replace(""" void set(void) { PyObject *x, *y; Py_INCREF(Py_None); x = Py_None; Py_INCREF(Py_None); x = Py_None; Py_DECREF(x); Py_DECREF(y); } """, """ #include "pythoncapi_compat.h" void set(void) { PyObject *x, *y; x = Py_NewRef(Py_None); x = Py_NewRef(Py_None); Py_DECREF(x); Py_DECREF(y); } """) # Indentation matters for conditional code self.check_dont_replace(""" void test1(int test) { PyObject *res; if (test) res = Py_True; else res = Py_False; Py_INCREF(res); Py_DECREF(res); } int test2(struct datetime* result, PyObject *tzinfo) { int res = 0; if (test) res = 1; else Py_INCREF(tzinfo); result->tzinfo = tzinfo; return res; } """) def test_py_clear(self): self.check_replace(""" void clear(int test) { PyObject *obj; // two lines Py_XDECREF(obj); obj = NULL; // inside if if (test) { Py_XDECREF(obj); obj = NULL; } } """, """ void clear(int test) { PyObject *obj; // two lines Py_CLEAR(obj); // inside if if (test) { Py_CLEAR(obj); } } """) # Don't replace Py_DECREF() self.check_dont_replace(""" void dont_clear(void) { PyObject *obj; Py_DECREF(obj); obj = NULL; } """, disable="Py_SETREF") def test_py_setref(self): self.check_replace(""" void set(PyObject **obj, PyObject *t) { // DECREF Py_DECREF(*obj); *obj = t; // XDECREF Py_XDECREF(*obj); *obj = t; // DECREF, INCREF Py_DECREF(*obj); Py_INCREF(t); *obj = t; } """, """ #include "pythoncapi_compat.h" void set(PyObject **obj, PyObject *t) { // DECREF Py_SETREF(*obj, t); // XDECREF Py_XSETREF(*obj, t); // DECREF, INCREF Py_SETREF(*obj, Py_NewRef(t)); } """) self.check_replace(""" void set(PyObject **obj, PyObject *value) { // 1 PyObject *old = *obj; *obj = value; Py_DECREF(old); // 2 PyObject *old = *obj; *obj = Py_XNewRef(value); Py_DECREF(old); // 3 PyObject *old = *obj; *obj = value; Py_XDECREF(old); // 4 PyObject *old = *obj; *obj = Py_NewRef(value); Py_XDECREF(old); } """, """ #include "pythoncapi_compat.h" void set(PyObject **obj, PyObject *value) { // 1 Py_SETREF(*obj, value); // 2 Py_SETREF(*obj, Py_XNewRef(value)); // 3 Py_XSETREF(*obj, value); // 4 Py_XSETREF(*obj, Py_NewRef(value)); } """) # INCREF, DECREF, assign self.check_replace(""" void set(void) { // 1 Py_INCREF(value); Py_DECREF(obj); obj = value; // 2 Py_INCREF(value); Py_XDECREF(obj); obj = value; // 3 Py_XINCREF(value); Py_DECREF(obj); obj = value; // 4 Py_XINCREF(value); Py_XDECREF(obj); obj = value; } """, """ #include "pythoncapi_compat.h" void set(void) { // 1 Py_SETREF(obj, Py_NewRef(value)); // 2 Py_XSETREF(obj, Py_NewRef(value)); // 3 Py_SETREF(obj, Py_XNewRef(value)); // 4 Py_XSETREF(obj, Py_XNewRef(value)); } """) # old variable self.check_replace(""" void set(PyObject **obj, PyObject *value) { // 1 PyObject *old_next = (PyObject*)self->tb_next; self->tb_next = (PyTracebackObject *)Py_XNewRef(new_next); Py_XDECREF(old_next); // 2 old_next = (PyObject*)self->tb_next; self->tb_next = (PyTracebackObject *)Py_XNewRef(new_next); Py_XDECREF(old_next); } """, """ #include "pythoncapi_compat.h" void set(PyObject **obj, PyObject *value) { // 1 Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(new_next)); // 2 Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(new_next)); } """) # Py_CLEAR self.check_replace(""" void set(PyObject **obj, PyObject *value) { // 1 Py_CLEAR(self->tb_next); self->tb_next = value; // 2 Py_INCREF(value); Py_CLEAR(self->tb_next); self->tb_next = value; // 3 Py_XINCREF(value); Py_CLEAR(self->tb_next); self->tb_next = value; } """, """ #include "pythoncapi_compat.h" void set(PyObject **obj, PyObject *value) { // 1 Py_XSETREF(self->tb_next, value); // 2 Py_XSETREF(self->tb_next, Py_NewRef(value)); // 3 Py_XSETREF(self->tb_next, Py_XNewRef(value)); } """) def test_py_is(self): self.check_replace(""" void test_py_is(PyObject *x) { if (x == Py_None) { return 1; } if (x == Py_True) { return 2; } if (x == Py_False) { return 3; } return 0; } void test_py_is_not(PyObject *x) { if (x != Py_None) { return 1; } if (x != Py_True) { return 2; } if (x != Py_False) { return 3; } return 0; } """, """ #include "pythoncapi_compat.h" void test_py_is(PyObject *x) { if (Py_IsNone(x)) { return 1; } if (Py_IsTrue(x)) { return 2; } if (Py_IsFalse(x)) { return 3; } return 0; } void test_py_is_not(PyObject *x) { if (!Py_IsNone(x)) { return 1; } if (!Py_IsTrue(x)) { return 2; } if (!Py_IsFalse(x)) { return 3; } return 0; } """) self.check_replace(""" void test_expr(struct MyStruct *obj, PyObject **obj2) { if (obj->attr1 == Py_None) { return 1; } if (obj->attr2.name == Py_None) { return 1; } if (*obj2 == Py_None) { return 1; } return 0; } """, """ #include "pythoncapi_compat.h" void test_expr(struct MyStruct *obj, PyObject **obj2) { if (Py_IsNone(obj->attr1)) { return 1; } if (Py_IsNone(obj->attr2.name)) { return 1; } if (Py_IsNone(*obj2)) { return 1; } return 0; } """) def test_no_compat(self): # Don't add "#include "pythoncapi_compat.h" source = """ void test_type(PyObject *obj, PyTypeObject *type) { obj->ob_type = type; } """ expected = """ void test_type(PyObject *obj, PyTypeObject *type) { Py_SET_TYPE(obj, type); } """ self.check_replace(source, expected, no_compat=True) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3653042 pygobject-3.54.5/subprojects/pythoncapi-compat/tests/utils.py0000644000000000000000000000165015074677100023223 0ustar00rootrootimport subprocess import sys PYTHON3 = (sys.version_info >= (3,)) def run_command(cmd, **kw): if hasattr(subprocess, 'run'): proc = subprocess.run(cmd, **kw) else: kw['shell'] = False proc = subprocess.Popen(cmd, **kw) try: proc.wait() except: proc.kill() proc.wait() raise exitcode = proc.returncode if exitcode: sys.exit(exitcode) def command_stdout(cmd, **kw): kw['stdout'] = subprocess.PIPE kw['universal_newlines'] = True if hasattr(subprocess, 'run'): proc = subprocess.run(cmd, **kw) return (proc.returncode, proc.stdout) else: kw['shell'] = False proc = subprocess.Popen(cmd, **kw) try: stdout = proc.communicate()[0] except: proc.kill() proc.wait() raise return (proc.returncode, stdout) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760788032.3653042 pygobject-3.54.5/subprojects/pythoncapi-compat/upgrade_pythoncapi.py0000755000000000000000000006175615074677100024626 0ustar00rootroot#!/usr/bin/env python3 import argparse import os import re import urllib.request import sys MIN_PYTHON = (2, 7) PYTHONCAPI_COMPAT_URL = ('https://raw.githubusercontent.com/python/' 'pythoncapi-compat/main/pythoncapi_compat.h') PYTHONCAPI_COMPAT_H = 'pythoncapi_compat.h' INCLUDE_PYTHONCAPI_COMPAT = f'#include "{PYTHONCAPI_COMPAT_H}"' INCLUDE_PYTHONCAPI_COMPAT2 = f'#include <{PYTHONCAPI_COMPAT_H}>' C_FILE_EXT = ( # C language ".c", ".h", # C++ language ".cc", ".cpp", ".cxx", ".hpp", ) IGNORE_DIRS = (".git", ".tox") # Match spaces but not newline characters. # Similar to \s but exclude newline characters and only look for ASCII spaces SPACE_REGEX = r'[ \t\f\v]' # Match the end of a line: newline characters of a single line NEWLINE_REGEX = r'(?:\n|\r|\r\n)' # Match the indentation at the beginning of a line INDENTATION_REGEX = fr'^{SPACE_REGEX}*' # Match a C identifier: 'identifier', 'var_3', 'NameCamelCase', '_var' # Use \b to only match a full word: match "a_b", but not just "b" in "a_b". ID_REGEX = r'\b[a-zA-Z_][a-zA-Z0-9_]*\b' # Match 'array[3]' SUBEXPR_REGEX = fr'{ID_REGEX}(?:\[[^]]+\])*' # Match a C expression like "frame", "frame.attr", "obj->attr" or "*obj". # Don't match functions calls like "func()". EXPR_REGEX = (fr"\*?" # "*" prefix fr"{SUBEXPR_REGEX}" # "var" fr"(?:(?:->|\.){SUBEXPR_REGEX})*") # "->attr" or ".attr" # # Match 'PyObject *var' and 'struct MyStruct* var' TYPE_PTR_REGEX = fr'{ID_REGEX} *\*' # Match '(PyObject*)' and nothing OPT_CAST_REGEX = fr'(?:\({TYPE_PTR_REGEX} *\){SPACE_REGEX}*)?' def same_indentation(group): # the regex must have re.MULTILINE flag return fr'{SPACE_REGEX}*(?:{NEWLINE_REGEX}{group})?' def get_member_regex_str(member): # Match "var->member". return fr'\b({EXPR_REGEX}) *-> *{member}\b' def get_member_regex(member): # Match "var->member" (get). # Don't match "var->member = value" (set). # Don't match "Py_CLEAR(var->member)". # Only "Py_CLEAR(" exact string is excluded. regex = (r'(?member = expr;". regex = assign_regex_str(get_member_regex_str(member), r'([^=].*)') return re.compile(regex) def call_assign_regex(name): # Match "Py_TYPE(expr) = expr;". # Don't match "assert(Py_TYPE(expr) == expr);". # Tolerate spaces regex = fr'{name} *\( *(.+) *\) *= *([^=].*) *;' return re.compile(regex) def is_c_filename(filename): return filename.endswith(C_FILE_EXT) class Operation: NAME = "" REPLACE = () NEED_PYTHONCAPI_COMPAT = False def __init__(self, patcher): self.patcher = patcher def patch(self, content): old_content = content for regex, replace in self.REPLACE: content = regex.sub(replace, content) if content != old_content and self.NEED_PYTHONCAPI_COMPAT: content = self.patcher.add_pythoncapi_compat(content) return content class Py_TYPE(Operation): NAME = "Py_TYPE" REPLACE = ( (get_member_regex('ob_type'), r'Py_TYPE(\1)'), ) # Py_TYPE() was added to Python 2.6. class Py_SIZE(Operation): NAME = "Py_SIZE" REPLACE = ( (get_member_regex('ob_size'), r'Py_SIZE(\1)'), ) # Py_SIZE() was added to Python 2.6. class Py_REFCNT(Operation): NAME = "Py_REFCNT" REPLACE = ( (get_member_regex('ob_refcnt'), r'Py_REFCNT(\1)'), ) # Py_REFCNT() was added to Python 2.6. class Py_SET_TYPE(Operation): NAME = "Py_SET_TYPE" REPLACE = ( (call_assign_regex('Py_TYPE'), r'Py_SET_TYPE(\1, \2);'), (set_member_regex('ob_type'), r'Py_SET_TYPE(\1, \2);'), ) # Need Py_SET_TYPE(): new in Python 3.9. NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9)) class Py_SET_SIZE(Operation): NAME = "Py_SET_SIZE" REPLACE = ( (call_assign_regex('Py_SIZE'), r'Py_SET_SIZE(\1, \2);'), (set_member_regex('ob_size'), r'Py_SET_SIZE(\1, \2);'), ) # Need Py_SET_SIZE(): new in Python 3.9. NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9)) class Py_SET_REFCNT(Operation): NAME = "Py_SET_REFCNT" REPLACE = ( (call_assign_regex('Py_REFCNT'), r'Py_SET_REFCNT(\1, \2);'), (set_member_regex('ob_refcnt'), r'Py_SET_REFCNT(\1, \2);'), ) # Need Py_SET_REFCNT(): new in Python 3.9. NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9)) class PyObject_NEW(Operation): NAME = "PyObject_NEW" # In Python 3.9, the PyObject_NEW() macro becomes an alias to the # PyObject_New() macro, and the PyObject_NEW_VAR() macro becomes an alias # to the PyObject_NewVar() macro. REPLACE = ( (re.compile(r"\bPyObject_NEW\b( *\()"), r'PyObject_New\1'), (re.compile(r"\bPyObject_NEW_VAR\b( *\()"), r'PyObject_NewVar\1'), ) class PyMem_MALLOC(Operation): NAME = "PyMem_MALLOC" # In Python 3.9, the PyObject_NEW() macro becomes an alias to the # PyObject_New() macro, and the PyObject_NEW_VAR() macro becomes an alias # to the PyObject_NewVar() macro. REPLACE = ( (re.compile(r"\bPyMem_MALLOC\b( *\()"), r'PyMem_Malloc\1'), (re.compile(r"\bPyMem_REALLOC\b( *\()"), r'PyMem_Realloc\1'), (re.compile(r"\bPyMem_FREE\b( *\()"), r'PyMem_Free\1'), (re.compile(r"\bPyMem_Del\b( *\()"), r'PyMem_Free\1'), (re.compile(r"\bPyMem_DEL\b( *\()"), r'PyMem_Free\1'), ) class PyObject_MALLOC(Operation): NAME = "PyObject_MALLOC" # In Python 3.9, the PyObject_NEW() macro becomes an alias to the # PyObject_New() macro, and the PyObject_NEW_VAR() macro becomes an alias # to the PyObject_NewVar() macro. REPLACE = ( (re.compile(r"\bPyObject_MALLOC\b( *\()"), r'PyObject_Malloc\1'), (re.compile(r"\bPyObject_REALLOC\b( *\()"), r'PyObject_Realloc\1'), (re.compile(r"\bPyObject_FREE\b( *\()"), r'PyObject_Free\1'), (re.compile(r"\bPyObject_Del\b( *\()"), r'PyObject_Free\1'), (re.compile(r"\bPyObject_DEL\b( *\()"), r'PyObject_Free\1'), ) class PyFrame_GetBack(Operation): NAME = "PyFrame_GetBack" REPLACE = ( (get_member_regex('f_back'), r'_PyFrame_GetBackBorrow(\1)'), ) # Need _PyFrame_GetBackBorrow() (PyFrame_GetBack() is new in Python 3.9) NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9)) class PyFrame_GetCode(Operation): NAME = "PyFrame_GetCode" REPLACE = ( (get_member_regex('f_code'), r'_PyFrame_GetCodeBorrow(\1)'), ) # Need _PyFrame_GetCodeBorrow() (PyFrame_GetCode() is new in Python 3.9) NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9)) class PyThreadState_GetInterpreter(Operation): NAME = "PyThreadState_GetInterpreter" REPLACE = ( (get_member_regex('interp'), r'PyThreadState_GetInterpreter(\1)'), ) # Need PyThreadState_GetInterpreter() (new in Python 3.9) NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9)) class PyThreadState_GetFrame(Operation): NAME = "PyThreadState_GetFrame" REPLACE = ( (get_member_regex('frame'), r'_PyThreadState_GetFrameBorrow(\1)'), ) # Need _PyThreadState_GetFrameBorrow() # (PyThreadState_GetFrame() is new in Python 3.9) NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9)) class Py_NewRef(Operation): NAME = "Py_NewRef" REPLACE = ( # "Py_INCREF(x); return x;" => "return Py_NewRef(x);" # "Py_XINCREF(x); return x;" => "return Py_XNewRef(x);" # The two statements must be at the same indentation, otherwise the # regex does not match. (re.compile(fr'({INDENTATION_REGEX})' + fr'Py_(X?)INCREF\(({EXPR_REGEX})\)\s*;' + same_indentation(r'\1') + fr'return {OPT_CAST_REGEX}\3;', re.MULTILINE), r'\1return Py_\2NewRef(\3);'), # Same regex than the previous one, # but the two statements are on the same line. (re.compile(fr'Py_(X?)INCREF\(({EXPR_REGEX})\)\s*;' + fr'{SPACE_REGEX}*' + fr'return {OPT_CAST_REGEX}\2;', re.MULTILINE), r'return Py_\1NewRef(\2);'), # "Py_INCREF(x); y = x;" must be replaced before # "y = x; Py_INCREF(y);", to not miss consecutive # "Py_INCREF; assign; Py_INCREF; assign; ..." (see unit tests). # "Py_INCREF(x); y = x;" => "y = Py_NewRef(x)" # "Py_XINCREF(x); y = x;" => "y = Py_XNewRef(x)" # The two statements must have the same indentation, otherwise the # regex does not match. (re.compile(fr'({INDENTATION_REGEX})' + fr'Py_(X?)INCREF\(({EXPR_REGEX})\);' + same_indentation(r'\1') + assign_regex_str(fr'({EXPR_REGEX})', fr'{OPT_CAST_REGEX}\3'), re.MULTILINE), r'\1\4 = Py_\2NewRef(\3);'), # Same regex than the previous one, # but the two statements are on the same line. (re.compile(fr'Py_(X?)INCREF\(({EXPR_REGEX})\);' + fr'{SPACE_REGEX}*' + assign_regex_str(fr'({EXPR_REGEX})', fr'{OPT_CAST_REGEX}\2')), r'\3 = Py_\1NewRef(\2);'), # "y = x; Py_INCREF(x);" => "y = Py_NewRef(x);" # "y = x; Py_INCREF(y);" => "y = Py_NewRef(x);" # "y = x; Py_XINCREF(x);" => "y = Py_XNewRef(x);" # "y = x; Py_XINCREF(y);" => "y = Py_XNewRef(x);" # "y = (PyObject*)x; Py_XINCREF(y);" => "y = Py_XNewRef(x);" # The two statements must have the same indentation, otherwise the # regex does not match. (re.compile(fr'({INDENTATION_REGEX})' + assign_regex_str(fr'({EXPR_REGEX})', fr'{OPT_CAST_REGEX}({EXPR_REGEX})') + same_indentation(r'\1') + r'Py_(X?)INCREF\((?:\2|\3)\);', re.MULTILINE), r'\1\2 = Py_\4NewRef(\3);'), # Same regex than the previous one, # but the two statements are on the same line. (re.compile(assign_regex_str(fr'({EXPR_REGEX})', fr'{OPT_CAST_REGEX}({EXPR_REGEX})') + fr'{SPACE_REGEX}*' + r'Py_(X?)INCREF\((?:\1|\2)\);'), r'\1 = Py_\3NewRef(\2);'), # "PyObject *var = x; Py_INCREF(x);" => "PyObject *var = Py_NewRef(x);" # The two statements must have the same indentation, otherwise the # regex does not match. (re.compile(fr'({INDENTATION_REGEX})' # "type* var = expr;" + assign_regex_str(fr'({TYPE_PTR_REGEX} *)({EXPR_REGEX})', fr'({OPT_CAST_REGEX})({EXPR_REGEX})') + same_indentation(r'\1') # "Py_INCREF(var);" + r'Py_(X?)INCREF\((?:\3|\5)\);', re.MULTILINE), r'\1\2\3 = \4Py_\6NewRef(\5);'), # "Py_INCREF(x); PyObject *var = x;" => "PyObject *var = Py_NewRef(x);" # The two statements must have the same indentation, otherwise the # regex does not match. (re.compile(fr'({INDENTATION_REGEX})' # "Py_INCREF(var);" + fr'Py_(X?)INCREF\(({EXPR_REGEX})\);' + same_indentation(r'\1') # "type* var = expr;" + assign_regex_str(fr'({TYPE_PTR_REGEX} *{EXPR_REGEX})', fr'({OPT_CAST_REGEX})\3'), re.MULTILINE), r'\1\4 = \5Py_\2NewRef(\3);'), ) # Need Py_NewRef(): new in Python 3.10 NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 10)) class Py_CLEAR(Operation): NAME = "Py_CLEAR" REPLACE = ( # "Py_XDECREF(x); x = NULL;" => "Py_CLEAR(x)"; # The two statements must have the same indentation, otherwise the # regex does not match. (re.compile(fr'({INDENTATION_REGEX})' + fr'Py_XDECREF\(({EXPR_REGEX})\) *;' + same_indentation(r'\1') + assign_regex_str(r'\2', r'NULL'), re.MULTILINE), r'\1Py_CLEAR(\2);'), # "Py_XDECREF(x); x = NULL;" => "Py_CLEAR(x)"; (re.compile(fr'Py_XDECREF\(({EXPR_REGEX})\) *;' + fr'{SPACE_REGEX}*' + assign_regex_str(r'\1', r'NULL')), r'Py_CLEAR(\1);'), ) SETREF_VALUE = fr'{OPT_CAST_REGEX}(?:{EXPR_REGEX}|Py_X?NewRef\({EXPR_REGEX}\))' class Py_SETREF(Operation): NAME = "Py_SETREF" REPLACE = ( # "Py_INCREF(y); Py_CLEAR(x); x = y;" => "Py_XSETREF(x, y)"; # Statements must have the same indentation, otherwise the regex does # not match. (re.compile(fr'({INDENTATION_REGEX})' + fr'Py_(X?)INCREF\(({EXPR_REGEX})\) *;' + same_indentation(r'\1') + fr'Py_CLEAR\(({EXPR_REGEX})\) *;' + same_indentation(r'\1') + assign_regex_str(r'\4', r'\3'), re.MULTILINE), r'\1Py_XSETREF(\4, Py_\2NewRef(\3));'), # "Py_CLEAR(x); x = y;" => "Py_XSETREF(x, y)"; # Statements must have the same indentation, otherwise the regex does # not match. (re.compile(fr'({INDENTATION_REGEX})' + fr'Py_CLEAR\(({EXPR_REGEX})\) *;' + same_indentation(r'\1') + assign_regex_str(r'\2', fr'({SETREF_VALUE})'), re.MULTILINE), r'\1Py_XSETREF(\2, \3);'), # "Py_INCREF(y); Py_DECREF(x); x = y;" => "Py_SETREF(x, y)"; # Statements must have the same indentation, otherwise the regex does # not match. (re.compile(fr'({INDENTATION_REGEX})' + fr'Py_(X?)INCREF\(({EXPR_REGEX})\) *;' + same_indentation(r'\1') + fr'Py_(X?)DECREF\(({EXPR_REGEX})\) *;' + same_indentation(r'\1') + assign_regex_str(r'\5', r'\3'), re.MULTILINE), r'\1Py_\4SETREF(\5, Py_\2NewRef(\3));'), # "Py_DECREF(x); x = y;" => "Py_SETREF(x, y)"; # "Py_DECREF(x); x = Py_NewRef(y);" => "Py_SETREF(x, Py_NewRef(y))"; # Statements must have the same indentation, otherwise the regex does # not match. (re.compile(fr'({INDENTATION_REGEX})' + fr'Py_(X?)DECREF\(({EXPR_REGEX})\) *;' + same_indentation(r'\1') + assign_regex_str(r'\3', fr'({SETREF_VALUE})'), re.MULTILINE), r'\1Py_\2SETREF(\3, \4);'), # "old = var; var = new; Py_DECREF(old);" => "Py_SETREF(var, new);" # "PyObject *old = var; var = new; Py_DECREF(old);" => "Py_SETREF(var, new);" # Statements must have the same indentation, otherwise the regex does # not match. (re.compile(fr'({INDENTATION_REGEX})' + fr'(?:{ID_REGEX} *\* *)?({ID_REGEX}) *= *{OPT_CAST_REGEX}({EXPR_REGEX}) *;' + same_indentation(r'\1') + assign_regex_str(r'\3', fr'({SETREF_VALUE})') + same_indentation(r'\1') + fr'Py_(X?)DECREF\(\2\) *;', re.MULTILINE), r'\1Py_\5SETREF(\3, \4);'), ) # Need Py_NewRef(): new in Python 3.5 NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 5)) class Py_Is(Operation): NAME = "Py_Is" def replace2(regs): x = regs.group(1) y = regs.group(2) if y == 'NULL': return regs.group(0) return f'{x} = _Py_StealRef({y});' REPLACE = [] expr = fr'({EXPR_REGEX})' for name in ('None', 'True', 'False'): REPLACE.extend(( (re.compile(fr'{expr} == Py_{name}\b'), fr'Py_Is{name}(\1)'), (re.compile(fr'{expr} != Py_{name}\b'), fr'!Py_Is{name}(\1)'), )) # Need Py_IsNone(), Py_IsTrue(), Py_IsFalse(): new in Python 3.10 NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 10)) OPERATIONS = ( Py_SET_TYPE, Py_SET_SIZE, Py_SET_REFCNT, # Py_SET_xxx must be run before Py_xxx Py_TYPE, Py_SIZE, Py_REFCNT, Py_Is, PyObject_NEW, PyMem_MALLOC, PyObject_MALLOC, PyFrame_GetBack, PyFrame_GetCode, PyThreadState_GetInterpreter, PyThreadState_GetFrame, # Code style: excluded from "all" Py_NewRef, Py_CLEAR, Py_SETREF, ) EXCLUDE_FROM_ALL = ( Py_NewRef, Py_CLEAR, Py_SETREF, ) def all_operations(): return set(operation_class.NAME for operation_class in OPERATIONS if operation_class not in EXCLUDE_FROM_ALL) class Patcher: def __init__(self, args=None): self.exitcode = 0 self.pythoncapi_compat_added = 0 self.want_pythoncapi_compat = False self.operations = None self.applied_operations = set() # Set temporariliy by patch() self._has_pythoncapi_compat = None self._applied_operations = None self._parse_options(args) def log(self, msg=''): print(msg, file=sys.stderr, flush=True) def warning(self, msg): self.log(f"WARNING: {msg}") def _get_operations(self, parser): args_names = self.args.operations.split(',') wanted = set() for name in args_names: name = name.strip() if not name: continue if name == "all": wanted |= all_operations() elif name.startswith("-"): name = name[1:] wanted.discard(name) else: wanted.add(name) operations = [] for operation_class in OPERATIONS: name = operation_class.NAME if name not in wanted: continue wanted.discard(name) operation = operation_class(self) operations.append(operation) if wanted: print(f"invalid operations: {','.join(wanted)}") print() self.usage(parser) sys.exit(1) return operations def add_line(self, content, line): line = line + '\n' # FIXME: tolerate trailing spaces if line not in content: # FIXME: add macro after the first header comment # FIXME: add macro after includes # FIXME: add macro after: #define PY_SSIZE_T_CLEAN return line + '\n' + content else: return content def add_pythoncapi_compat(self, content): if self._has_pythoncapi_compat: return content content = self.add_line(content, INCLUDE_PYTHONCAPI_COMPAT) self._has_pythoncapi_compat = True self.pythoncapi_compat_added += 1 return content def _patch(self, content): try: has = (self.args.no_compat or INCLUDE_PYTHONCAPI_COMPAT in content or INCLUDE_PYTHONCAPI_COMPAT2 in content) self._has_pythoncapi_compat = has self._applied_operations = [] for operation in self.operations: new_content = operation.patch(content) if new_content != content: self._applied_operations.append(operation.NAME) content = new_content applied_operations = self._applied_operations finally: self._has_pythoncapi_compat = None self._applied_operations = None return (content, applied_operations) def patch(self, content): return self._patch(content)[0] def patch_file(self, filename): if os.path.basename(filename) == PYTHONCAPI_COMPAT_H: self.log(f"Skip {filename}") return encoding = "utf-8" errors = "surrogateescape" with open(filename, encoding=encoding, errors=errors) as fp: old_contents = fp.read() new_contents, operations = self._patch(old_contents) if self.args.to_stdout: print(new_contents, end="") return (new_contents != old_contents) # Don't rewrite if the filename for in-place replacement, # to avoid changing the file modification time. if new_contents == old_contents: return False if not self.args.no_backup: old_filename = filename + ".old" # If old_filename already exists, replace it os.replace(filename, old_filename) with open(filename, "w", encoding=encoding, errors=errors) as fp: fp.write(new_contents) self.applied_operations |= set(operations) operations = ', '.join(operations) self.log(f"Patched file: {filename} ({operations})") return True def _walk_dir(self, path): empty = True for dirpath, dirnames, filenames in os.walk(path): # Don't walk into .tox for ignore_name in IGNORE_DIRS: try: dirnames.remove(ignore_name) except ValueError: pass for filename in filenames: if is_c_filename(filename): yield os.path.join(dirpath, filename) empty = False if empty: self.warning(f"Directory {path} doesn't contain any C file") self.exitcode = 1 def walk(self, paths): for path in paths: if os.path.isdir(path): for filename in self._walk_dir(path): yield filename elif os.path.exists(path): yield path else: self.warning(f"Path {path} does not exist") self.exitcode = 1 def get_latest_header(self, base_dir): target = os.path.join(base_dir, PYTHONCAPI_COMPAT_H) self.log(f"Download the file from {PYTHONCAPI_COMPAT_URL} to {target}.") urllib.request.urlretrieve(PYTHONCAPI_COMPAT_URL, target) @staticmethod def usage(parser): parser.print_help() print() print("Operations:") print() for operation in sorted(OPERATIONS, key=lambda operation: operation.NAME.lower()): print(f"- {operation.NAME}") print() print("If a directory is passed, search for .c and .h files " "in subdirectories.") def _parse_dir_path(self, path): if os.path.isdir(path): return path else: raise argparse.ArgumentTypeError(f"{path} is not a valid path") def _parse_options(self, args): parser = argparse.ArgumentParser( description="Upgrade C extension modules to newer Python C API") parser.add_argument( '-o', '--operations', action="store", default="all", help='Space separated list of operation names to apply') parser.add_argument( '-q', '--quiet', action="store_true", help='Quiet mode') parser.add_argument( '-c', '--to-stdout', action="store_true", help='Write output into stdout instead of modifying files ' 'in-place (imply quiet mode)') parser.add_argument( '-B', '--no-backup', action="store_true", help="Don't create .old backup files") parser.add_argument( '-C', '--no-compat', action="store_true", help=f"Don't add: {INCLUDE_PYTHONCAPI_COMPAT}") parser.add_argument( '-d', '--download', metavar='PATH', help=f'Download latest pythoncapi_compat.h file to designated PATH', type=self._parse_dir_path) parser.add_argument( metavar='file_or_directory', dest="paths", nargs='*') args = parser.parse_args(args) if not args.paths and not args.download: self.usage(parser) sys.exit(1) if args.to_stdout: args.quiet = True self.args = args self.operations = self._get_operations(parser) def main(self): if self.args.paths: for filename in self.walk(self.args.paths): self.patch_file(filename) if self.applied_operations: nops = len(self.applied_operations) ops = ', '.join(sorted(self.applied_operations)) self.log() self.log(f"Applied operations ({nops}): {ops}") if self.args.download: path = self.args.download self.get_latest_header(path) if self.pythoncapi_compat_added and not self.args.quiet: self.log() self.log(f"{INCLUDE_PYTHONCAPI_COMPAT} added: you may have " f"to copy {PYTHONCAPI_COMPAT_H} to your project") self.log("Run 'python upgrade_pythoncapi.py --download '") sys.exit(self.exitcode) if __name__ == "__main__": Patcher().main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/subprojects/pythoncapi-compat.wrap0000664000000000000000000000027415074673150021246 0ustar00rootroot[wrap-git] directory=pythoncapi-compat url=https://github.com/python/pythoncapi-compat.git revision=632d1aa0c4be6c67498d6b97630ddd7d7eb0f90a depth=1 diff_files=pythoncapi-compat-meson.diff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/conftest.py0000664000000000000000000001327015074673150015712 0ustar00rootrootimport os import sys import signal import subprocess import atexit import warnings import pytest import contextlib @pytest.hookimpl(hookwrapper=True, tryfirst=True) def pytest_runtest_call(item): """A pytest hook which takes over sys.excepthook and raises any uncaught exception (with PyGObject this happesn often when we get called from C, like any signal handler, vfuncs tc). """ exceptions = [] def on_hook(type_, value, tback): exceptions.append((type_, value, tback)) orig_excepthook = sys.excepthook sys.excepthook = on_hook try: outcome = yield finally: sys.excepthook = orig_excepthook if exceptions: tp, value, tb = exceptions[0] outcome.force_exception(tp(value).with_traceback(tb)) def set_dll_search_path(): # Python 3.8 no longer searches for DLLs in PATH, so we have to add # everything in PATH manually. Note that unlike PATH add_dll_directory # has no defined order, so if there are two cairo DLLs in PATH we # might get a random one. if os.name != "nt" or not hasattr(os, "add_dll_directory"): return for p in os.environ.get("PATH", "").split(os.pathsep): with contextlib.suppress(OSError): os.add_dll_directory(p) def os_environ_prepend(envvar, path): current = os.environ.get(envvar) os.environ[envvar] = os.path.pathsep.join([path, current] if current else [path]) def init_test_environ(): set_dll_search_path() def dbus_launch_session(): if os.name == "nt" or sys.platform == "darwin": return (-1, "") try: out = subprocess.check_output( [ "dbus-daemon", "--session", "--fork", "--print-address=1", "--print-pid=1", ] ) except (subprocess.CalledProcessError, OSError): return (-1, "") else: out = out.decode("utf-8") addr, pid = out.splitlines() return int(pid), addr pid, addr = dbus_launch_session() if pid >= 0: os.environ["DBUS_SESSION_BUS_ADDRESS"] = addr atexit.register(os.kill, pid, signal.SIGKILL) else: os.environ["DBUS_SESSION_BUS_ADDRESS"] = "." # force untranslated messages, as we check for them in some tests os.environ["LC_MESSAGES"] = "C" os.environ["G_DEBUG"] = "fatal-warnings fatal-criticals" if sys.platform == "darwin" or os.name == "nt": # gtk 3.22 has warnings and ciriticals on OS X, ignore for now. # On Windows glib will create an error dialog which will block tests # so it's never a good idea there to make things fatal. os.environ["G_DEBUG"] = "" # First add test directory, since we have a gi package there tests_srcdir = os.path.abspath(os.path.dirname(__file__)) srcdir = os.path.dirname(tests_srcdir) sys.path.insert(0, tests_srcdir) sys.path.insert(0, srcdir) import gi gi_builddir = os.path.dirname(gi._gi.__file__) builddir = os.path.dirname(gi_builddir) tests_builddir = os.path.join(builddir, "tests") sys.path.insert(0, tests_builddir) sys.path.insert(0, builddir) # make Gio able to find our gschemas.compiled in tests/. This needs to be set # before importing Gio. Support a separate build tree, so look in build dir # first. os.environ["GSETTINGS_BACKEND"] = "memory" os.environ["GSETTINGS_SCHEMA_DIR"] = tests_builddir os.environ["G_FILENAME_ENCODING"] = "UTF-8" # Avoid accessibility dbus warnings os.environ["NO_AT_BRIDGE"] = "1" # A workaround for https://gitlab.gnome.org/GNOME/glib/-/issues/2251 # The gtk4 a11y stack calls get_dbus_object_path() on the default app os.environ["GTK_A11Y"] = "none" # Force the default theme so broken themes don't affect the tests os.environ["GTK_THEME"] = "Adwaita" gi_gir_path = os.path.join( builddir, "subprojects", "glib", "girepository", "introspection" ) if os.path.exists(gi_gir_path): os_environ_prepend("GI_TYPELIB_PATH", gi_gir_path) gi.require_version("GIRepository", "3.0") repo = gi.Repository.get_default() gi_tests_path = os.path.join(builddir, "subprojects", "gobject-introspection-tests") repo.prepend_library_path(gi_tests_path) repo.prepend_search_path(gi_tests_path) def try_require_version(namespace, version): try: gi.require_version(namespace, version) except ValueError: # prevent tests from running with the wrong version sys.modules["gi.repository." + namespace] = None # Optional try_require_version("Gtk", os.environ.get("TEST_GTK_VERSION", "3.0")) try_require_version("Gdk", os.environ.get("TEST_GTK_VERSION", "3.0")) try_require_version("GdkPixbuf", "2.0") try_require_version("Pango", "1.0") try_require_version("PangoCairo", "1.0") try_require_version("Atk", "1.0") # Required gi.require_versions( { "GIMarshallingTests": "1.0", "Regress": "1.0", "GLib": "2.0", "Gio": "2.0", "GObject": "2.0", } ) # It's disabled for stable releases by default, this makes sure it's # always on for the tests. warnings.simplefilter("default", gi.PyGIDeprecationWarning) # Otherwise we crash on the first gtk use when e.g. DISPLAY isn't set try: from gi.repository import Gtk except ImportError: pass else: res = Gtk.init_check() if Gtk._version == "4.0" else Gtk.init_check([])[0] if not res: raise RuntimeError("Gtk available, but Gtk.init_check() failed") init_test_environ() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/gi/overrides/Regress.py0000664000000000000000000000253315074673150020100 0ustar00rootroot# Copyright (C) 2012 Martin Pitt # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA from ..importer import get_introspection_module from ..overrides import override Regress = get_introspection_module("Regress") REGRESS_OVERRIDE = 42 class Bitmask(Regress.Bitmask): """Replicate override of Bitmask (uint64), similar to GStreamer.""" def __init__(self, v): if not isinstance(v, int): raise TypeError(f"{type(v)} is not an int.") self.v = int(v) def __str__(self): return hex(self.v) def __eq__(self, other): return self.v == other Bitmask = override(Bitmask) __all__ = ["REGRESS_OVERRIDE", "Bitmask"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/gi/overrides/__init__.py0000664000000000000000000000011415074673150020216 0ustar00rootrootfrom pkgutil import extend_path __path__ = extend_path(__path__, __name__) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/helper.py0000664000000000000000000000712515074673150015346 0ustar00rootrootimport contextlib import unittest import inspect import warnings import functools import sys from collections import namedtuple from io import StringIO import gi from gi import PyGIDeprecationWarning from gi.repository import GLib ExceptionInfo = namedtuple("ExceptionInfo", ["type", "value", "traceback"]) """The type used for storing exceptions used by capture_exceptions()""" @contextlib.contextmanager def capture_exceptions(): """Installs a temporary sys.excepthook which records all exceptions instead of printing them. """ exceptions = [] def custom_excepthook(*args): exceptions.append(ExceptionInfo(*args)) old_hook = sys.excepthook sys.excepthook = custom_excepthook try: yield exceptions finally: sys.excepthook = old_hook def ignore_gi_deprecation_warnings(func_or_class): """A unittest class and function decorator which makes them ignore PyGIDeprecationWarning. """ if inspect.isclass(func_or_class): assert issubclass(func_or_class, unittest.TestCase) cls = func_or_class for name, value in cls.__dict__.items(): if callable(value) and name.startswith("test_"): new_value = ignore_gi_deprecation_warnings(value) setattr(cls, name, new_value) return cls func = func_or_class @functools.wraps(func) def wrapper(*args, **kwargs): with capture_gi_deprecation_warnings(): return func(*args, **kwargs) return wrapper @contextlib.contextmanager def capture_gi_deprecation_warnings(): """Temporarily suppress PyGIDeprecationWarning output and record them.""" with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always", category=PyGIDeprecationWarning) yield warn @contextlib.contextmanager def capture_glib_warnings(allow_warnings=False, allow_criticals=False): """Temporarily suppress glib warning output and record them. The test suite is run with G_DEBUG="fatal-warnings fatal-criticals" by default. Setting allow_warnings and allow_criticals will temporarily allow warnings or criticals without terminating the test run. """ old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags(0)) new_mask = old_mask if allow_warnings: new_mask &= ~GLib.LogLevelFlags.LEVEL_WARNING if allow_criticals: new_mask &= ~GLib.LogLevelFlags.LEVEL_CRITICAL GLib.log_set_always_fatal(GLib.LogLevelFlags(new_mask)) GLibWarning = gi._gi.Warning try: with warnings.catch_warnings(record=True) as warn: warnings.filterwarnings("always", category=GLibWarning) yield warn finally: GLib.log_set_always_fatal(old_mask) @contextlib.contextmanager def capture_glib_deprecation_warnings(): """Temporarily suppress glib deprecation warning output and record them.""" GLibWarning = gi._gi.Warning with warnings.catch_warnings(record=True) as warn: warnings.filterwarnings( "always", category=GLibWarning, message=".+ is deprecated and shouldn't be used anymore\\. " "It will be removed in a future version\\.", ) yield warn @contextlib.contextmanager def capture_output(): """With capture_output() as (stdout, stderr): some_action() print(stdout.getvalue(), stderr.getvalue()). """ err = StringIO() out = StringIO() old_err = sys.stderr old_out = sys.stdout sys.stderr = err sys.stdout = out try: yield (out, err) finally: sys.stderr = old_err sys.stdout = old_out ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/meson.build0000664000000000000000000000266115074673150015657 0ustar00rootrootgnome = import('gnome') host_system = host_machine.system() cc = meson.get_compiler('c') helper_sources = [ 'testhelpermodule.c', 'test-floating.c', 'test-thread.c', 'test-unknown.c'] helperext = python.extension_module('testhelper', helper_sources, dependencies : [python_dep, glib_dep, gobject_dep, pythoncapi_compat_dep], c_args: pyext_c_args + main_c_args, include_directories: include_directories(join_paths('..', 'gi')) ) schemas = gnome.compile_schemas(build_by_default: true) envdata = environment() if host_machine.system() == 'windows' envdata.prepend('PATH', join_paths(get_option('prefix'), get_option('bindir'))) endif test_deps = [ giext, helperext, schemas, gi_tests.get_variable('gimarshallingtests_typelib'), gi_tests.get_variable('regress_typelib'), gi_tests.get_variable('utility_typelib')] python_paths = [join_paths(meson.current_build_dir(), '..')] if pycairo_dep.found() and pycairo_dep.type_name() == 'internal' python_paths += [join_paths(meson.project_build_root(), 'subprojects', 'pycairo')] test_deps += [gicairoext] endif envdata.append('PYTHONPATH', python_paths) gi_tests_builddir = meson.project_build_root() / 'subprojects' / 'gobject-introspection-tests' envdata.prepend('GI_TYPELIB_PATH', gi_tests_builddir) test('pygobject-test-suite', python, args: ['-m', 'pytest'], workdir: meson.project_source_root(), env: envdata, timeout: 90, depends: test_deps) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/org.gnome.test.gschema.xml0000664000000000000000000000166415074673150020520 0ustar00rootroot true "Hello" (1,2) [1,2] 'banana' 123 42 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test-floating.c0000664000000000000000000000640315074673150016437 0ustar00rootroot/* * test-floating.c - Source for TestFloating * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-floating.h" /* TestFloating */ G_DEFINE_TYPE (TestFloating, test_floating, G_TYPE_INITIALLY_UNOWNED) static void test_floating_finalize (GObject *gobject) { TestFloating *object = TEST_FLOATING (gobject); if (g_object_is_floating (object)) { g_warning ( "A floating object was finalized. This means that someone\n" "called g_object_unref() on an object that had only a floating\n" "reference; the initial floating reference is not owned by " "anyone\n" "and must be removed without g_object_ref_sink()."); } G_OBJECT_CLASS (test_floating_parent_class)->finalize (gobject); } static void test_floating_class_init (TestFloatingClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = test_floating_finalize; } static void test_floating_init (TestFloating *self) { } /* TestOwnedByLibrary */ G_DEFINE_TYPE (TestOwnedByLibrary, test_owned_by_library, G_TYPE_OBJECT) static GSList *obl_instance_list = NULL; static void test_owned_by_library_class_init (TestOwnedByLibraryClass *klass) { } static void test_owned_by_library_init (TestOwnedByLibrary *self) { g_object_ref (self); obl_instance_list = g_slist_prepend (obl_instance_list, self); } void test_owned_by_library_release (TestOwnedByLibrary *self) { obl_instance_list = g_slist_remove (obl_instance_list, self); g_object_unref (self); } GSList * test_owned_by_library_get_instance_list (void) { return obl_instance_list; } /* TestFloatingAndSunk * This object is mimicking the GtkWindow behaviour, ie a GInitiallyUnowned subclass * whose floating reference has already been sunk when g_object_new() returns it. * The reference is already sunk because the instance is already owned by the instance * list. */ G_DEFINE_TYPE (TestFloatingAndSunk, test_floating_and_sunk, G_TYPE_INITIALLY_UNOWNED) static GSList *fas_instance_list = NULL; static void test_floating_and_sunk_class_init (TestFloatingAndSunkClass *klass) { } static void test_floating_and_sunk_init (TestFloatingAndSunk *self) { g_object_ref_sink (self); fas_instance_list = g_slist_prepend (fas_instance_list, self); } void test_floating_and_sunk_release (TestFloatingAndSunk *self) { fas_instance_list = g_slist_remove (fas_instance_list, self); g_object_unref (self); } GSList * test_floating_and_sunk_get_instance_list (void) { return fas_instance_list; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test-floating.h0000664000000000000000000001074715074673150016452 0ustar00rootroot/* * test-floating.h - Header for TestFloating * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include /* TestFloating */ typedef struct { GInitiallyUnowned parent; } TestFloating; typedef struct { GInitiallyUnownedClass parent_class; } TestFloatingClass; #define TEST_TYPE_FLOATING (test_floating_get_type ()) #define TEST_FLOATING(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_FLOATING, TestFloating)) #define TEST_FLOATING_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_FLOATING, TestFloatingClass)) #define TEST_IS_FLOATING(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_FLOATING)) #define TEST_IS_FLOATING_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((obj), TEST_TYPE_FLOATING)) #define TEST_FLOATING_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_FLOATING, TestFloatingClass)) GType test_floating_get_type (void); /* TestOwnedByLibrary */ typedef struct { GObject parent; } TestOwnedByLibrary; typedef struct { GObjectClass parent_class; } TestOwnedByLibraryClass; #define TEST_TYPE_OWNED_BY_LIBRARY (test_owned_by_library_get_type ()) #define TEST_OWNED_BY_LIBRARY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_OWNED_BY_LIBRARY, \ TestOwnedByLibrary)) #define TEST_OWNED_BY_LIBRARY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OWNED_BY_LIBRARY, \ TestOwnedByLibraryClass)) #define TEST_IS_OWNED_BY_LIBRARY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_OWNED_BY_LIBRARY)) #define TEST_IS_OWNED_BY_LIBRARY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((obj), TEST_TYPE_OWNED_BY_LIBRARY)) #define TEST_OWNED_BY_LIBRARY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OWNED_BY_LIBRARY, \ TestOwnedByLibraryClass)) GType test_owned_by_library_get_type (void); void test_owned_by_library_release (TestOwnedByLibrary *self); GSList *test_owned_by_library_get_instance_list (void); /* TestFloatingAndSunk */ typedef struct { GInitiallyUnowned parent; } TestFloatingAndSunk; typedef struct { GInitiallyUnownedClass parent_class; } TestFloatingAndSunkClass; #define TEST_TYPE_FLOATING_AND_SUNK (test_floating_and_sunk_get_type ()) #define TEST_FLOATING_AND_SUNK(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_FLOATING_AND_SUNK, \ TestFloatingAndSunk)) #define TEST_FLOATING_AND_SUNK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_FLOATING_AND_SUNK, \ TestFloatingAndSunkClass)) #define TEST_IS_FLOATING_AND_SUNK(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_FLOATING_AND_SUNK)) #define TEST_IS_FLOATING_AND_SUNK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((obj), TEST_TYPE_FLOATING_AND_SUNK)) #define TEST_FLOATING_AND_SUNK_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_FLOATING_AND_SUNK, \ TestFloatingAndSunkClass)) GType test_floating_and_sunk_get_type (void); void test_floating_and_sunk_release (TestFloatingAndSunk *self); GSList *test_floating_and_sunk_get_instance_list (void); ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test-thread.c0000664000000000000000000000314115074673150016077 0ustar00rootroot#include "test-thread.h" enum { /* methods */ SIGNAL_EMIT_SIGNAL, SIGNAL_FROM_THREAD, LAST_SIGNAL }; static guint test_thread_signals[LAST_SIGNAL] = { 0 }; typedef enum { TEST_THREAD_A, TEST_THREAD_B } ThreadEnumType; static GType test_thread_enum_get_type (void) { static GType enum_type = 0; static GEnumValue enum_values[] = { { TEST_THREAD_A, "TEST_THREAD_A", "a as in apple" }, { 0, NULL, NULL }, }; if (!enum_type) { enum_type = g_enum_register_static ("TestThreadEnum", enum_values); } return enum_type; } G_DEFINE_TYPE (TestThread, test_thread, G_TYPE_OBJECT); static G_NORETURN void other_thread_cb (TestThread *self) { g_signal_emit_by_name (self, "from-thread", 0, NULL); g_thread_exit (0); } static void test_thread_emit_signal (TestThread *self) { self->thread = g_thread_new ("t", (GThreadFunc)other_thread_cb, self); } static void test_thread_init (TestThread *self) { } static void test_thread_class_init (TestThreadClass *klass) { test_thread_signals[SIGNAL_EMIT_SIGNAL] = g_signal_new ( "emit-signal", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (TestThreadClass, emit_signal), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); test_thread_signals[SIGNAL_FROM_THREAD] = g_signal_new ( "from-thread", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (TestThreadClass, from_thread), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, test_thread_enum_get_type ()); klass->emit_signal = test_thread_emit_signal; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test-thread.h0000664000000000000000000000206615074673150016111 0ustar00rootroot#include typedef struct { GObject parent; GThread *thread; } TestThread; typedef struct { GObjectClass parent_class; void (*emit_signal) (TestThread *sink); void (*from_thread) (TestThread *sink); } TestThreadClass; GType test_thread_get_type (void); #define TEST_TYPE_THREAD (test_thread_get_type ()) #define TEST_THREAD(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_THREAD, TestTHREAD)) #define TEST_THREAD_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_THREAD, TestTHREADClass)) #define TEST_IS_THREAD(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_THREAD)) #define TEST_IS_THREAD_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((obj), TEST_TYPE_THREAD)) #define TEST_THREAD_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_THREAD, TestTHREADClass)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test-unknown.c0000664000000000000000000000513615074673150016335 0ustar00rootroot#include "test-unknown.h" enum { PROP_SOME_PROPERTY = 1, }; static void test_interface_base_init (gpointer g_iface) { static gboolean initialized = FALSE; if (!initialized) { g_object_interface_install_property ( g_iface, g_param_spec_string ("some-property", "some-property", "A simple test property", NULL, G_PARAM_READWRITE)); initialized = TRUE; } } GType test_interface_get_type (void) { static GType gtype = 0; if (!gtype) { static const GTypeInfo info = { sizeof (TestInterfaceIface), /* class_size */ test_interface_base_init, /* base_init */ NULL, /* base_finalize */ NULL, NULL, /* class_finalize */ NULL, /* class_data */ 0, 0, /* n_preallocs */ NULL }; gtype = g_type_register_static (G_TYPE_INTERFACE, "TestInterface", &info, 0); g_type_interface_add_prerequisite (gtype, G_TYPE_OBJECT); } return gtype; } static void test_unknown_iface_method (TestInterface *iface) { } static void test_unknown_test_interface_init (TestInterfaceIface *iface) { iface->iface_method = test_unknown_iface_method; } G_DEFINE_TYPE_WITH_CODE ( TestUnknown, test_unknown, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TEST_TYPE_INTERFACE, test_unknown_test_interface_init)); static void test_unknown_init (TestUnknown *self) { } static void test_unknown_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { } static void test_unknown_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { } static void test_unknown_class_init (TestUnknownClass *klass) { GObjectClass *gobject_class = (GObjectClass *)klass; gobject_class->get_property = test_unknown_get_property; gobject_class->set_property = test_unknown_set_property; g_object_class_install_property ( G_OBJECT_CLASS (klass), PROP_SOME_PROPERTY, g_param_spec_string ("some-property", "some-property", "A simple test property", NULL, G_PARAM_READWRITE)); } void test_interface_iface_method (TestInterface *instance) { TestInterfaceIface *iface = TEST_INTERFACE_GET_IFACE (instance); (*iface->iface_method) (instance); } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test-unknown.h0000664000000000000000000000360015074673150016334 0ustar00rootroot#include /* TestUnknown */ typedef struct { GObject parent; } TestUnknown; typedef struct { GObjectClass parent_class; } TestUnknownClass; #define TEST_TYPE_UNKNOWN (test_unknown_get_type ()) #define TEST_UNKNOWN(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_UNKNOWN, TestUnknown)) #define TEST_UNKNOWN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_UNKNOWN, TestUnknownClass)) #define TEST_IS_UNKNOWN(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_UNKNOWN)) #define TEST_IS_UNKNOWN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((obj), TEST_TYPE_UNKNOWN)) #define TEST_UNKNOWN_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_UNKNOWN, TestUnknownClass)) GType test_unknown_get_type (void); /* TestInterface */ typedef struct _TestInterface TestInterface; typedef struct _TestInterfaceIface TestInterfaceIface; struct _TestInterfaceIface { GTypeInterface g_iface; /* VTable */ void (*iface_method) (TestInterface *iface); }; #define TEST_TYPE_INTERFACE (test_interface_get_type ()) #define TEST_INTERFACE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_INTERFACE, TestInterface)) #define TEST_IS_INTERFACE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_INTERFACE)) #define TEST_INTERFACE_GET_IFACE(obj) \ (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_INTERFACE, \ TestInterfaceIface)) GType test_interface_get_type (void); void test_interface_iface_method (TestInterface *iface); ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_async.py0000664000000000000000000001347015074673150016243 0ustar00rootrootimport pytest import platform import unittest import asyncio from gi.repository import GLib, Gio from gi.events import GLibEventLoopPolicy class TestAsync(unittest.TestCase): def setUp(self): policy = GLibEventLoopPolicy() asyncio.set_event_loop_policy(policy) self.addCleanup(asyncio.set_event_loop_policy, None) self.loop = policy.get_event_loop() self.addCleanup(self.loop.close) def test_async_enumerate(self): f = Gio.file_new_for_path("./") called = False def cb(): nonlocal called called = True async def run(): nonlocal called, self self.loop.call_soon(cb) iter_info = [ info.get_name() for info in await f.enumerate_children_async( "standard::*", 0, GLib.PRIORITY_DEFAULT ) ] # The await runs the mainloop and cb is called. self.assertEqual(called, True) next_info = [] enumerator = f.enumerate_children("standard::*", 0, None) while True: info = enumerator.next_file(None) if info is None: break next_info.append(info.get_name()) self.assertEqual(iter_info, next_info) self.loop.run_until_complete(run()) def test_async_cancellation(self): """Cancellation raises G_IO_ERROR_CANCELLED.""" f = Gio.file_new_for_path("./") async def run(): nonlocal self # cancellable created implicitly res = f.enumerate_children_async("standard::*", 0, GLib.PRIORITY_DEFAULT) res.cancel() with self.assertRaisesRegex(GLib.GError, "Operation was cancelled"): await res # cancellable passed explicitly cancel = Gio.Cancellable() res = f.enumerate_children_async( "standard::*", 0, GLib.PRIORITY_DEFAULT, cancel ) self.assertEqual(res.cancellable, cancel) cancel.cancel() with self.assertRaisesRegex(GLib.GError, "Operation was cancelled"): await res self.loop.run_until_complete(run()) def test_not_completed(self): """Querying an uncompleted task raises exceptions.""" f = Gio.file_new_for_path("./") async def run(): nonlocal self # cancellable created implicitly res = f.enumerate_children_async("standard::*", 0, GLib.PRIORITY_DEFAULT) with self.assertRaises(asyncio.InvalidStateError): res.result() with self.assertRaises(asyncio.InvalidStateError): res.exception() # And, await it await res self.loop.run_until_complete(run()) def test_async_cancel_completed(self): """Cancelling a completed task just cancels the cancellable.""" f = Gio.file_new_for_path("./") async def run(): nonlocal self res = f.enumerate_children_async("standard::*", 0, GLib.PRIORITY_DEFAULT) await res assert not res.cancellable.is_cancelled() res.cancel() assert res.cancellable.is_cancelled() self.loop.run_until_complete(run()) def test_async_completed_add_cb(self): """Adding a done cb to a completed future queues it with call_soon.""" f = Gio.file_new_for_path("./") called = False def cb(): nonlocal called called = True async def run(): nonlocal called, self res = f.enumerate_children_async("standard::*", 0, GLib.PRIORITY_DEFAULT) await res self.loop.call_soon(cb) # Python await is smart and does not iterate the EventLoop await res assert not called # So create a new future and wait on that fut = asyncio.Future() def done_cb(res): nonlocal fut fut.set_result(res.result()) res.add_done_callback(done_cb) await fut assert called self.loop.run_until_complete(run()) @pytest.mark.xfail( platform.python_implementation() == "PyPy", reason="Exception reporting does not work in pypy", ) def test_deleting_failed_logs(self): f = Gio.file_new_for_path("./") async def run(): nonlocal self res = f.enumerate_children_async("standard::*", 0, GLib.PRIORITY_DEFAULT) res.cancel() # Cancellation in Gio is not immediate, so sleep for a bit await asyncio.sleep(0.5) exc = None msg = None def handler(loop, context): nonlocal exc, msg msg = context["message"] exc = context["exception"] self.loop.set_exception_handler(handler) self.loop.run_until_complete(run()) self.assertRegex(msg, ".*exception was never retrieved") self.assertIsInstance(exc, GLib.GError) assert exc.matches(Gio.io_error_quark(), Gio.IOErrorEnum.CANCELLED) def test_no_running_loop(self): f = Gio.file_new_for_path("./") res = f.enumerate_children_async("standard::*", 0, GLib.PRIORITY_DEFAULT) self.assertIsNone(res) def test_wrong_default_context(self): f = Gio.file_new_for_path("./") async def run(): # noqa: RUF029 nonlocal self ctx = GLib.MainContext.new() GLib.MainContext.push_thread_default(ctx) self.addCleanup(GLib.MainContext.pop_thread_default, ctx) res = f.enumerate_children_async("standard::*", 0, GLib.PRIORITY_DEFAULT) self.assertIsNone(res) self.loop.run_until_complete(run()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_atoms.py0000664000000000000000000000710715074673150016251 0ustar00rootrootimport os import unittest try: from gi.repository import Gtk, Gdk except ImportError: Gdk = None Gtk = None from .helper import capture_glib_deprecation_warnings def is_X11(): try: from gi.repository import Gdk, GdkX11 except ImportError: return False display = Gdk.Display.get_default() return isinstance(display, GdkX11.X11Display) @unittest.skipUnless(Gdk, "Gdk not available") @unittest.skipIf(Gdk and Gdk._version == "4.0", "Gdk4 doesn't have GdkAtom") class TestGdkAtom(unittest.TestCase): def test_create(self): atom = Gdk.Atom.intern("my_string", False) self.assertEqual(atom.name(), "my_string") def test_str(self): atom = Gdk.Atom.intern("my_string", False) self.assertEqual(str(atom), "my_string") self.assertEqual(str(Gdk.SELECTION_CLIPBOARD), "CLIPBOARD") def test_repr(self): # __repr__ should generate a string which is parsable when possible # http://docs.python.org/2/reference/datamodel.html#object.__repr__ atom = Gdk.Atom.intern("my_string", False) self.assertEqual(repr(atom), 'Gdk.Atom.intern("my_string", False)') self.assertEqual(eval(repr(atom)), atom) self.assertEqual( repr(Gdk.SELECTION_CLIPBOARD), 'Gdk.Atom.intern("CLIPBOARD", False)' ) @unittest.skipUnless(os.name != "nt", "not on Windows") def test_in_single(self): a_selection = Gdk.Atom.intern("test_clipboard", False) clipboard = Gtk.Clipboard.get(a_selection) clipboard.set_text("hello", 5) # needs a Gdk.Atom, not a string self.assertRaises(TypeError, Gtk.Clipboard.get, "CLIPBOARD") def test_in_array(self): a_plain = Gdk.Atom.intern("text/plain", False) a_html = Gdk.Atom.intern("text/html", False) a_jpeg = Gdk.Atom.intern("image/jpeg", False) self.assertFalse(Gtk.targets_include_text([])) self.assertTrue(Gtk.targets_include_text([a_plain, a_html])) self.assertFalse(Gtk.targets_include_text([a_jpeg])) self.assertTrue(Gtk.targets_include_text([a_jpeg, a_plain])) self.assertFalse(Gtk.targets_include_image([], False)) self.assertFalse(Gtk.targets_include_image([a_plain, a_html], False)) self.assertTrue(Gtk.targets_include_image([a_jpeg], False)) self.assertTrue(Gtk.targets_include_image([a_jpeg, a_plain], False)) @unittest.skipUnless(is_X11(), "only on X11") def test_out_array(self): a_selection = Gdk.Atom.intern("my_clipboard", False) clipboard = Gtk.Clipboard.get(a_selection) # empty (res, targets) = clipboard.wait_for_targets() self.assertEqual(res, False) self.assertEqual(targets, []) # text clipboard.set_text("hello", 5) (res, targets) = clipboard.wait_for_targets() self.assertEqual(res, True) self.assertNotEqual(targets, []) self.assertEqual(type(targets[0]), Gdk.Atom) names = [t.name() for t in targets] self.assertFalse(None in names, names) self.assertTrue("TEXT" in names, names) @unittest.skipUnless(is_X11(), "only on X11") @unittest.skipIf(not Gdk or Gdk._version == "4.0", "not in gdk4") def test_out_glist(self): display = Gdk.Display.get_default() with capture_glib_deprecation_warnings(): dm = display.get_device_manager() device = dm.get_client_pointer() axes = device.list_axes() axes_names = [atom.name() for atom in axes if atom is not None] assert all(isinstance(name, str) for name in axes_names) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_cairo.py0000664000000000000000000003011215074673150016213 0ustar00rootrootimport unittest import pytest import gi try: gi.require_foreign("cairo") import cairo has_cairo = True except ImportError: has_cairo = False has_region = has_cairo and hasattr(cairo, "Region") try: from gi.repository import Gtk, Gdk Gtk, Gdk except ImportError: Gtk = None Gdk = None from gi.repository import GObject, Regress @unittest.skipUnless(has_cairo, "built without cairo support") class Test(unittest.TestCase): def test_gvalue_converters(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) matrix = cairo.Matrix() objects = { "CairoContext": context, "CairoSurface": surface, "CairoFontFace": context.get_font_face(), "CairoScaledFont": context.get_scaled_font(), "CairoPattern": context.get_source(), "CairoMatrix": matrix, } for type_name, cairo_obj in objects.items(): gtype = GObject.type_from_name(type_name) v = GObject.Value() assert v.init(gtype) is None assert v.get_value() is None v.set_value(None) assert v.get_value() is None v.set_value(cairo_obj) assert v.get_value() == cairo_obj def test_cairo_context(self): context = Regress.test_cairo_context_full_return() self.assertTrue(isinstance(context, cairo.Context)) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) Regress.test_cairo_context_none_in(context) def test_cairo_context_full_in(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) Regress.test_cairo_context_full_in(context) with pytest.raises(TypeError): Regress.test_cairo_context_full_in(object()) def test_cairo_context_none_return(self): context = Regress.test_cairo_context_none_return() self.assertTrue(isinstance(context, cairo.Context)) def test_cairo_path_full_return(self): path = Regress.test_cairo_path_full_return() if hasattr(cairo, "Path"): # pycairo 1.15.1+ assert isinstance(path, cairo.Path) def test_cairo_path_none_in(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) path = context.copy_path() Regress.test_cairo_path_none_in(path) surface.finish() with pytest.raises(TypeError): Regress.test_cairo_path_none_in(object()) def test_cairo_path_full_in_full_return(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) context.move_to(10, 10) context.curve_to(10, 10, 3, 4, 5, 6) path = context.copy_path() new_path = Regress.test_cairo_path_full_in_full_return(path) assert list(path) == list(new_path) surface.finish() def test_cairo_font_options_full_return(self): options = Regress.test_cairo_font_options_full_return() assert isinstance(options, cairo.FontOptions) def test_cairo_font_options_none_return(self): options = Regress.test_cairo_font_options_none_return() assert isinstance(options, cairo.FontOptions) def test_cairo_font_options_full_in(self): options = cairo.FontOptions() Regress.test_cairo_font_options_full_in(options) with pytest.raises(TypeError): Regress.test_cairo_font_options_full_in(object()) def test_cairo_font_options_none_in(self): options = cairo.FontOptions() Regress.test_cairo_font_options_none_in(options) def test_cairo_font_face_full_return(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) font_face = Regress.test_cairo_font_face_full_return(context) assert font_face def test_cairo_scaled_font_full_return(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) scaled_font = Regress.test_cairo_scaled_font_full_return(context) assert scaled_font def test_cairo_pattern_full_in(self): pattern = cairo.SolidPattern(1, 1, 1, 1) Regress.test_cairo_pattern_full_in(pattern) with pytest.raises(TypeError): Regress.test_cairo_pattern_full_in(object()) def test_cairo_pattern_none_in(self): pattern = cairo.SolidPattern(1, 1, 1, 1) Regress.test_cairo_pattern_none_in(pattern) def test_cairo_pattern_full_return(self): pattern = Regress.test_cairo_pattern_full_return() self.assertTrue(isinstance(pattern, cairo.Pattern)) self.assertTrue(isinstance(pattern, cairo.SolidPattern)) def test_cairo_pattern_none_return(self): pattern = Regress.test_cairo_pattern_none_return() self.assertTrue(isinstance(pattern, cairo.Pattern)) self.assertTrue(isinstance(pattern, cairo.SolidPattern)) def test_cairo_region_full_in(self): region = cairo.Region() Regress.test_cairo_region_full_in(region) with pytest.raises(TypeError): Regress.test_cairo_region_full_in(object()) def test_cairo_matrix_none_in(self): matrix = cairo.Matrix() Regress.test_cairo_matrix_none_in(matrix) with pytest.raises(TypeError): Regress.test_cairo_matrix_none_in(object()) def test_cairo_matrix_none_return(self): matrix = Regress.test_cairo_matrix_none_return() assert matrix == cairo.Matrix() def test_cairo_matrix_out_caller_allocates(self): matrix = Regress.test_cairo_matrix_out_caller_allocates() assert matrix == cairo.Matrix() def test_cairo_surface(self): surface = Regress.test_cairo_surface_none_return() self.assertTrue(isinstance(surface, cairo.ImageSurface)) self.assertTrue(isinstance(surface, cairo.Surface)) self.assertEqual(surface.get_format(), cairo.FORMAT_ARGB32) self.assertEqual(surface.get_width(), 10) self.assertEqual(surface.get_height(), 10) surface = Regress.test_cairo_surface_full_return() self.assertTrue(isinstance(surface, cairo.ImageSurface)) self.assertTrue(isinstance(surface, cairo.Surface)) self.assertEqual(surface.get_format(), cairo.FORMAT_ARGB32) self.assertEqual(surface.get_width(), 10) self.assertEqual(surface.get_height(), 10) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) Regress.test_cairo_surface_none_in(surface) surface = Regress.test_cairo_surface_full_out() self.assertTrue(isinstance(surface, cairo.ImageSurface)) self.assertTrue(isinstance(surface, cairo.Surface)) self.assertEqual(surface.get_format(), cairo.FORMAT_ARGB32) self.assertEqual(surface.get_width(), 10) self.assertEqual(surface.get_height(), 10) def test_cairo_surface_full_in(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) Regress.test_cairo_surface_full_in(surface) with pytest.raises(TypeError): Regress.test_cairo_surface_full_in(object()) def test_require_foreign(self): self.assertEqual(gi.require_foreign("cairo"), None) self.assertEqual(gi.require_foreign("cairo", "Context"), None) self.assertRaises(ImportError, gi.require_foreign, "invalid_module") self.assertRaises( ImportError, gi.require_foreign, "invalid_module", "invalid_symbol" ) self.assertRaises(ImportError, gi.require_foreign, "cairo", "invalid_symbol") @unittest.skipUnless(has_cairo, "built without cairo support") @unittest.skipUnless(has_region, "built without cairo.Region support") @unittest.skipUnless(Gdk, "Gdk not available") class TestRegion(unittest.TestCase): def test_region_to_py(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) context.paint() region = Gdk.cairo_region_create_from_surface(surface) r = region.get_extents() self.assertEqual((r.height, r.width), (10, 10)) def test_region_from_py(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) region = cairo.Region(cairo.RectangleInt(0, 0, 42, 42)) Gdk.cairo_region(context, region) self.assertTrue("42" in repr(list(context.copy_path()))) @unittest.skipUnless(has_cairo, "built without cairo support") @unittest.skipUnless(Gtk, "Gtk not available") class TestPango(unittest.TestCase): def test_cairo_font_options(self): window = Gtk.Window() if Gtk._version == "4.0": window.set_font_options(cairo.FontOptions()) font_opts = window.get_font_options() else: screen = window.get_screen() font_opts = screen.get_font_options() assert font_opts is not None self.assertTrue(isinstance(font_opts.get_subpixel_order(), int)) if has_cairo: from gi.repository import cairo as CairoGObject # Use PyGI signals to test non-introspected foreign marshaling. class CairoSignalTester(GObject.Object): sig_context = GObject.Signal(arg_types=[CairoGObject.Context]) sig_surface = GObject.Signal(arg_types=[CairoGObject.Surface]) sig_font_face = GObject.Signal(arg_types=[CairoGObject.FontFace]) sig_scaled_font = GObject.Signal(arg_types=[CairoGObject.ScaledFont]) sig_pattern = GObject.Signal(arg_types=[CairoGObject.Pattern]) @unittest.skipUnless(has_cairo, "built without cairo support") class TestSignalMarshaling(unittest.TestCase): # Tests round tripping of cairo objects through non-introspected signals. def setUp(self): self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) self.context = cairo.Context(self.surface) self.tester = CairoSignalTester() def pass_object_through_signal(self, obj, signal): """Pass the given `obj` through the `signal` emission storing the `obj` passed through the signal and returning it. """ passthrough_result = [] def callback(instance, passthrough): passthrough_result.append(passthrough) signal.connect(callback) signal.emit(obj) return passthrough_result[0] def test_context(self): result = self.pass_object_through_signal(self.context, self.tester.sig_context) self.assertTrue(isinstance(result, cairo.Context)) with pytest.raises(TypeError): self.pass_object_through_signal(object(), self.tester.sig_context) def test_surface(self): result = self.pass_object_through_signal(self.surface, self.tester.sig_surface) self.assertTrue(isinstance(result, cairo.Surface)) def test_font_face(self): font_face = self.context.get_font_face() result = self.pass_object_through_signal(font_face, self.tester.sig_font_face) self.assertTrue(isinstance(result, cairo.FontFace)) with pytest.raises(TypeError): self.pass_object_through_signal(object(), self.tester.sig_font_face) def test_scaled_font(self): scaled_font = cairo.ScaledFont( self.context.get_font_face(), cairo.Matrix(), cairo.Matrix(), self.context.get_font_options(), ) result = self.pass_object_through_signal( scaled_font, self.tester.sig_scaled_font ) self.assertTrue(isinstance(result, cairo.ScaledFont)) with pytest.raises(TypeError): result = self.pass_object_through_signal( object(), self.tester.sig_scaled_font ) def test_pattern(self): pattern = cairo.SolidPattern(1, 1, 1, 1) result = self.pass_object_through_signal(pattern, self.tester.sig_pattern) self.assertTrue(isinstance(result, cairo.Pattern)) self.assertTrue(isinstance(result, cairo.SolidPattern)) with pytest.raises(TypeError): result = self.pass_object_through_signal(object(), self.tester.sig_pattern) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_callback.py0000664000000000000000000000336215074673150016661 0ustar00rootrootfrom gi.repository import GLib, Gio, Regress def iteration(): ctx = GLib.main_context_default() while ctx.pending(): ctx.iteration(False) def test_async_callback(): result = [] cancel = Gio.Cancellable() def callback(obj, res): result.append(obj.function_finish(res)) obj = Regress.TestObj() obj.function_async(GLib.PRIORITY_DEFAULT, cancellable=cancel, callback=callback) obj.function_thaw_async() iteration() assert result == [True] def test_async_callback_with_extra_callbacks(): result = [] def callback(obj, res): result.append(obj.function2_finish(res)) obj = Regress.TestObj() obj.function2(GLib.PRIORITY_DEFAULT, None, None, None, callback) obj.function_thaw_async() iteration() assert result == [(True, None)] def test_async_callback_with_extra_callbacks_filled_in(): result = [] cancel = Gio.Cancellable() def test_cb(data): result.append(data) return 0 def callback(obj, res): result.append(obj.function2_finish(res)) obj = Regress.TestObj() obj.function2(GLib.PRIORITY_DEFAULT, cancel, test_cb, ("test_cb data",), callback) obj.function_thaw_async() iteration() assert result == ["test_cb data", (True, None)] def test_async_callback_with_extra_callbacks_as_kwarg(): result = [] cancel = Gio.Cancellable() def test_cb(data): result.append(data) return 0 def callback(obj, res): result.append(obj.function2_finish(res)) obj = Regress.TestObj() obj.function2( GLib.PRIORITY_DEFAULT, cancellable=cancel, test_cb=test_cb, callback=callback ) obj.function_thaw_async() iteration() assert result == [None, (True, None)] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_docstring.py0000664000000000000000000001136715074673150017125 0ustar00rootrootimport unittest import gi.docstring from gi.repository import Regress from gi.repository import GIMarshallingTests from gi.repository import Gio from gi.repository import GObject try: from gi.repository import Gtk except ImportError: Gtk = None class Test(unittest.TestCase): def test_api(self): def new_func(info): return "docstring test" old_func = gi.docstring.get_doc_string_generator() gi.docstring.set_doc_string_generator(new_func) self.assertEqual(gi.docstring.get_doc_string_generator(), new_func) self.assertEqual(gi.docstring.generate_doc_string(None), "docstring test") # Set back to original generator gi.docstring.set_doc_string_generator(old_func) self.assertEqual(gi.docstring.get_doc_string_generator(), old_func) def test_final_signature_with_full_inout(self): self.assertEqual( GIMarshallingTests.Object.full_inout.__doc__, "full_inout(object:GIMarshallingTests.Object) -> object:GIMarshallingTests.Object", ) def test_overridden_doc_is_not_clobbered(self): self.assertEqual( GIMarshallingTests.OverridesObject.method.__doc__, "Overridden doc string." ) def test_allow_none_with_user_data_defaults(self): g_file_copy_doc = ( "copy(self, destination:Gio.File, " "flags:Gio.FileCopyFlags, " "cancellable:Gio.Cancellable=None, " "progress_callback:Gio.FileProgressCallback=None, " "progress_callback_data=None) -> bool" ) self.assertEqual(Gio.File.copy.__doc__, g_file_copy_doc) def test_array_length_arg(self): self.assertEqual(GIMarshallingTests.array_in.__doc__, "array_in(ints:list)") def test_init_function(self): # This tests implicit array length args along with skipping a # boolean return self.assertEqual( GIMarshallingTests.init_function.__doc__, "init_function(argv:list=None) -> bool, argv:list", ) def test_boolean_return(self): self.assertEqual( GIMarshallingTests.boolean_return_true.__doc__, "boolean_return_true() -> bool", ) # https://bugzilla.gnome.org/show_bug.cgi?id=740301 def test_may_return_none(self): self.assertEqual( Gio.File.get_basename.__doc__, "get_basename(self) -> str or None" ) def test_class_doc_constructors(self): doc = GIMarshallingTests.Object.__doc__ self.assertTrue("new(int_:int)" in doc) def test_struct_doc_constructors(self): doc = GIMarshallingTests.BoxedStruct.__doc__ self.assertTrue("new()" in doc) self.assertTrue("BoxedStruct()" in doc) def test_private_struct_constructors(self): # Structs without a size or constructor should have no constructor docs. doc = Regress.TestBoxedPrivate.__doc__ self.assertEqual(doc, "") def test_array_inout_etc(self): self.assertEqual( GIMarshallingTests.array_inout_etc.__doc__, "array_inout_etc(first:int, ints:list, last:int) -> ints:list, sum:int", ) def test_array_out_etc(self): self.assertEqual( GIMarshallingTests.array_out_etc.__doc__, "array_out_etc(first:int, last:int) -> ints:list, sum:int", ) @unittest.skipUnless(Gtk, "no Gtk") def test_shared_array_length_with_prior_out_arg(self): # Test the 'iter' out argument does not effect length argument skipping. self.assertRegex( Gtk.ListStore.insert_with_valuesv.__doc__, "insert_with_values.*\\(self, position:int, columns:list, values:list\\) -> iter:Gtk.TreeIter", ) def test_sub_class_doc(self): class A(GObject.Object): """first doc.""" pass class B(A): """second doc.""" pass self.assertEqual(A.__doc__, "first doc.") self.assertEqual(B.__doc__, "second doc.") def test_sub_class_no_doc(self): class A(GObject.Object): pass class B(A): """sub-class doc.""" self.assertEqual(A.__doc__, None) self.assertEqual(B.__doc__, "sub-class doc.") @unittest.expectedFailure # https://bugzilla.gnome.org/show_bug.cgi?id=734926 def test_sub_class_doc_setattr(self): class A(GObject.Object): pass class B(A): pass A.__doc__ = "custom doc" self.assertEqual(A.__doc__, "custom doc") self.assertEqual(B.__doc__, "custom doc") def test_return_array_with_length_argument(self): self.assertEqual( GIMarshallingTests.enum_array_return_type.__doc__, "enum_array_return_type() -> list", ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_enum.py0000664000000000000000000001204415074673150016066 0ustar00rootrootimport threading import unittest from gi.repository import GObject from .helper import capture_glib_warnings _lock = threading.Lock() counter = 0 def get_id(): global counter with _lock: counter += 1 return counter class EnumTests(unittest.TestCase): def test_gtype(self): class MyEnum(GObject.GEnum): ONE = 1 TWO = 2 THREE = 3 # The new enum has it's own GType, which subclasses GEnum self.assertIsInstance(MyEnum.__gtype__, GObject.GType) self.assertNotEqual(MyEnum.__gtype__, GObject.GEnum.__gtype__) self.assertEqual(MyEnum.__gtype__.parent, GObject.GEnum.__gtype__) self.assertTrue(MyEnum.__gtype__.is_a(GObject.GEnum.__gtype__)) self.assertIn(MyEnum.__gtype__, GObject.GEnum.__gtype__.children) # The class can be looked up by name type_name = MyEnum.__gtype__.name self.assertIn("MyEnum", type_name) self.assertEqual(GObject.GType.from_name(type_name), MyEnum.__gtype__) # The Python class is registered as the wrapper for the GType self.assertIs(MyEnum.__gtype__.pytype, MyEnum) def test_values(self): class MyEnum(GObject.GEnum): ONE = 1 FORTY_TWO = 42 # As this is a stdlib enum, the enum values are subclasses of the enum self.assertIsInstance(MyEnum.ONE, MyEnum) self.assertIsInstance(MyEnum.FORTY_TWO, MyEnum) # We can see the registered enum values too: self.assertEqual(MyEnum.ONE.value_name, "ONE") self.assertEqual(MyEnum.ONE.value_nick, "one") self.assertEqual(MyEnum.FORTY_TWO.value_name, "FORTY_TWO") self.assertEqual(MyEnum.FORTY_TWO.value_nick, "forty-two") def test_custom_type_name(self): type_name = f"MyEnum{get_id()}" class MyEnum(GObject.GEnum): __gtype_name__ = type_name ONE = 1 self.assertEqual(MyEnum.__gtype__.name, type_name) # Trying to register a type with the same name fails: with ( self.assertRaises(RuntimeError) as ex, capture_glib_warnings(allow_criticals=True) as w, ): class MyEnum2(GObject.GEnum): __gtype_name__ = type_name ONE = 1 self.assertEqual(str(ex.exception), f"Unable to register enum '{type_name}'") self.assertEqual(len(w), 1) self.assertEqual( str(w[0].message), f"cannot register existing type '{type_name}'" ) class FlagsTests(unittest.TestCase): def test_gtype(self): class MyFlags(GObject.GFlags): ONE = 1 TWO = 2 FOUR = 4 # The new enum has it's own GType, which subclasses GFlags self.assertIsInstance(MyFlags.__gtype__, GObject.GType) self.assertNotEqual(MyFlags.__gtype__, GObject.GFlags.__gtype__) self.assertEqual(MyFlags.__gtype__.parent, GObject.GFlags.__gtype__) self.assertTrue(MyFlags.__gtype__.is_a(GObject.GFlags.__gtype__)) self.assertIn(MyFlags.__gtype__, GObject.GFlags.__gtype__.children) # The class can be looked up by name type_name = MyFlags.__gtype__.name self.assertIn("MyFlags", type_name) self.assertEqual(GObject.GType.from_name(type_name), MyFlags.__gtype__) # The Python class is registered as the wrapper for the GType self.assertIs(MyFlags.__gtype__.pytype, MyFlags) def test_values(self): class MyFlags(GObject.GFlags): ONE = 1 THIRTY_TWO = 32 # As this is a stdlib enum, the enum values are subclasses of the enum self.assertIsInstance(MyFlags.ONE, MyFlags) self.assertIsInstance(MyFlags.THIRTY_TWO, MyFlags) # We can see the registered enum values too: self.assertEqual(MyFlags.ONE.value_names, ["ONE"]) self.assertEqual(MyFlags.ONE.value_nicks, ["one"]) self.assertEqual(MyFlags.THIRTY_TWO.value_names, ["THIRTY_TWO"]) self.assertEqual(MyFlags.THIRTY_TWO.value_nicks, ["thirty-two"]) # Similar for combinations of flags v = MyFlags.ONE | MyFlags.THIRTY_TWO self.assertIsInstance(v, MyFlags) self.assertEqual(v.value_names, ["ONE", "THIRTY_TWO"]) self.assertEqual(v.value_nicks, ["one", "thirty-two"]) def test_custom_type_name(self): type_name = f"MyFlags{get_id()}" class MyFlags(GObject.GFlags): __gtype_name__ = type_name ONE = 1 self.assertEqual(MyFlags.__gtype__.name, type_name) # Trying to register a type with the same name fails: with ( self.assertRaises(RuntimeError) as ex, capture_glib_warnings(allow_criticals=True) as w, ): class MyFlags2(GObject.GFlags): __gtype_name__ = type_name ONE = 1 self.assertEqual(str(ex.exception), f"Unable to register flags '{type_name}'") self.assertEqual(len(w), 1) self.assertEqual( str(w[0].message), f"cannot register existing type '{type_name}'" ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_error.py0000664000000000000000000001433515074673150016260 0ustar00rootroot# test_error.py: Tests for GError wrapper implementation # # Copyright (C) 2012 Will Thompson # Copyright (C) 2013 Martin Pitt # Copyright (C) 2014 Simon Feltman # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import unittest import pickle from gi.repository import GLib from gi.repository import GIMarshallingTests class TestType(unittest.TestCase): def test_attributes(self): e = GLib.Error("test message", "mydomain", 42) self.assertEqual(e.message, "test message") self.assertEqual(e.domain, "mydomain") self.assertEqual(e.code, 42) def test_new_literal(self): mydomain = GLib.quark_from_string("mydomain") e = GLib.Error.new_literal(mydomain, "test message", 42) self.assertEqual(e.message, "test message") self.assertEqual(e.domain, "mydomain") self.assertEqual(e.code, 42) def test_matches(self): mydomain = GLib.quark_from_string("mydomain") notmydomain = GLib.quark_from_string("notmydomain") e = GLib.Error("test message", "mydomain", 42) self.assertTrue(e.matches(mydomain, 42)) self.assertFalse(e.matches(notmydomain, 42)) self.assertFalse(e.matches(mydomain, 40)) def test_str(self): e = GLib.Error("test message", "mydomain", 42) self.assertEqual(str(e), "mydomain: test message (42)") def test_repr(self): e = GLib.Error("test message", "mydomain", 42) self.assertEqual(repr(e), "GLib.Error('test message', 'mydomain', 42)") def test_inheritance(self): self.assertTrue(issubclass(GLib.Error, RuntimeError)) def test_pickle(self): def check_pickle(e): assert isinstance(e, GLib.Error) new_e = pickle.loads(pickle.dumps(e)) assert type(new_e) is type(e) assert repr(e) == repr(new_e) e = GLib.Error("test message", "mydomain", 42) check_pickle(e) try: GLib.file_get_contents("") except Exception as e: check_pickle(e) class ObjectWithVFuncException(GIMarshallingTests.Object): def do_vfunc_meth_with_err(self, x): if x == 42: return True msg = f"unexpected value {x:d}" raise GLib.Error(msg, "mydomain", 42) class TestMarshalling(unittest.TestCase): def test_array_in_crash(self): # Previously there was a bug in invoke, in which C arrays were unwrapped # from inside GArrays to be passed to the C function. But when a GError was # set, invoke would attempt to free the C array as if it were a GArray. # This crash is only for C arrays. It does not happen for C functions which # take in GArrays. See https://bugzilla.gnome.org/show_bug.cgi?id=642708 self.assertRaises(GLib.Error, GIMarshallingTests.gerror_array_in, [1, 2, 3]) def test_out(self): # See https://bugzilla.gnome.org/show_bug.cgi?id=666098 error, debug = GIMarshallingTests.gerror_out() self.assertIsInstance(error, GLib.Error) self.assertEqual(error.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN) self.assertEqual(error.code, GIMarshallingTests.CONSTANT_GERROR_CODE) self.assertEqual(error.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE) self.assertEqual(debug, GIMarshallingTests.CONSTANT_GERROR_DEBUG_MESSAGE) def test_out_transfer_none(self): # See https://bugzilla.gnome.org/show_bug.cgi?id=666098 error, debug = GIMarshallingTests.gerror_out_transfer_none() self.assertIsInstance(error, GLib.Error) self.assertEqual(error.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN) self.assertEqual(error.code, GIMarshallingTests.CONSTANT_GERROR_CODE) self.assertEqual(error.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE) self.assertEqual(GIMarshallingTests.CONSTANT_GERROR_DEBUG_MESSAGE, debug) def test_return(self): # See https://bugzilla.gnome.org/show_bug.cgi?id=666098 error = GIMarshallingTests.gerror_return() self.assertIsInstance(error, GLib.Error) self.assertEqual(error.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN) self.assertEqual(error.code, GIMarshallingTests.CONSTANT_GERROR_CODE) self.assertEqual(error.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE) def test_exception(self): with self.assertRaises(GLib.Error) as context: GIMarshallingTests.gerror() e = context.exception self.assertEqual(e.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN) self.assertEqual(e.code, GIMarshallingTests.CONSTANT_GERROR_CODE) self.assertEqual(e.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE) def test_vfunc_no_exception(self): obj = ObjectWithVFuncException() self.assertTrue(obj.vfunc_meth_with_error(42)) def test_vfunc_gerror_exception(self): obj = ObjectWithVFuncException() with self.assertRaises(GLib.Error) as context: obj.vfunc_meth_with_error(-1) e = context.exception self.assertEqual(e.message, "unexpected value -1") self.assertEqual(e.domain, "mydomain") self.assertEqual(e.code, 42) def tests_compare_two_gerrors_in_gvalue(self): error = GLib.Error.new_literal(1, "error", 1) error1 = GLib.Error.new_literal(1, "error", 1) GIMarshallingTests.compare_two_gerrors_in_gvalue(error, error1) def test_nullable_error(): error = GLib.Error.new_literal(1, "error", 1) assert GIMarshallingTests.nullable_gerror(error) == 1 assert GIMarshallingTests.nullable_gerror(None) == 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_events.py0000664000000000000000000003055115074673150016431 0ustar00rootrootimport sys import pytest import unittest try: if sys.platform != "win32": from test.test_asyncio.test_events import ( UnixEventLoopTestsMixin as GLibEventLoopTestsMixin, ) else: from test.test_asyncio.test_events import EventLoopTestsMixin # There is Mixin for the ProactorEventLoop, so copy the skips class GLibEventLoopTestsMixin(EventLoopTestsMixin): def test_reader_callback(self): raise unittest.SkipTest("IocpEventLoop does not have add_reader()") def test_reader_callback_cancel(self): raise unittest.SkipTest("IocpEventLoop does not have add_reader()") def test_writer_callback(self): raise unittest.SkipTest("IocpEventLoop does not have add_writer()") def test_writer_callback_cancel(self): raise unittest.SkipTest("IocpEventLoop does not have add_writer()") def test_remove_fds_after_closing(self): raise unittest.SkipTest("IocpEventLoop does not have add_reader()") from test.test_asyncio.test_subprocess import SubprocessMixin from test.test_asyncio.utils import TestCase except: class GLibEventLoopTestsMixin: def test_unix_event_loop_tests_missing(self): import warnings warnings.warn("UnixEventLoopTestsMixin is unavailable, not running tests!") self.skipTest("UnixEventLoopTestsMixin is unavailable, not running tests!") class SubprocessMixin: def test_subprocess_mixin_tests_missing(self): import warnings warnings.warn("SubprocessMixin is unavailable, not running tests!") self.skipTest("SubprocessMixin is unavailable, not running tests!") from unittest import TestCase import sys import gi import gi.events import asyncio import socket import threading from gi.repository import GLib, Gio try: from gi.repository import Gtk except ImportError: Gtk = None GTK4 = Gtk and Gtk._version == "4.0" class GLibEventLoopTests(GLibEventLoopTestsMixin, TestCase): def __init__(self, *args): super().__init__(*args) self.loop = None def create_event_loop(self): return gi.events.GLibEventLoop(GLib.MainContext()) class SubprocessWatcherTests(SubprocessMixin, TestCase): def setUp(self): super().setUp() policy = gi.events.GLibEventLoopPolicy() asyncio.set_event_loop_policy(policy) self.loop = policy.get_event_loop() def tearDown(self): asyncio.set_event_loop_policy(None) self.loop.close() super().tearDown() class GLibEventLoopPolicyTests(unittest.TestCase): def create_policy(self): return gi.events.GLibEventLoopPolicy() def test_get_event_loop(self): policy = self.create_policy() loop = policy.get_event_loop() self.assertIsInstance(loop, gi.events.GLibEventLoop) self.assertIs(loop, policy.get_event_loop()) loop.close() def test_new_event_loop(self): policy = self.create_policy() loop = policy.new_event_loop() self.assertIsInstance(loop, gi.events.GLibEventLoop) loop.close() # Attaching a loop to the main thread fails with self.assertRaises(RuntimeError): policy.set_event_loop(loop) def test_application(self): task_completed = False async def task(): nonlocal task_completed await asyncio.sleep(1) task_completed = True def activate(app): app.hold() app.create_asyncio_task(task()) GLib.timeout_add(500, app.release) app = Gio.Application() app.connect("activate", activate) with self.create_policy(): app.run() self.assertTrue(task_completed) def test_implicit_close(self): """Verify that implicitly closing the EventLoop (from __del__) works.""" task_completed = False async def task(): nonlocal task_completed await asyncio.sleep(1) task_completed = True policy = self.create_policy() loop = policy.new_event_loop() loop.run_until_complete(task()) self.assertTrue(task_completed) with pytest.warns(ResourceWarning, match="unclosed event loop"): del loop # For some reason, PyPy needs two collect() steps import gc gc.collect() gc.collect() def test_nested_context_iteration(self): policy = self.create_policy() loop = policy.new_event_loop() called = False def cb(): nonlocal called called = True async def run(): nonlocal loop, called loop.call_soon(cb) self.assertEqual(called, False) # Iterating the main context does not cause cb to be called while loop._context.iteration(False): pass self.assertEqual(called, False) # Awaiting on anything *does* cause the cb to fire await asyncio.sleep(0) self.assertEqual(called, True) loop.run_until_complete(run()) loop.close() def test_thread_event_loop(self): policy = self.create_policy() loop = policy.new_event_loop() res = [] def thread_func(res): try: # We cannot get an event loop for the current thread with self.assertRaises(RuntimeError): policy.get_event_loop() # We can attach our loop policy.set_event_loop(loop) # Now we can get it, and it is the same self.assertIs(policy.get_event_loop(), loop) # Simple call_soon test results = [] def callback(arg1, arg2): results.append((arg1, arg2)) loop.stop() loop.call_soon(callback, "hello", "world") loop.run_forever() self.assertEqual(results, [("hello", "world")]) # We can detach it again policy.set_event_loop(None) # Which means we have none and get a runtime error with self.assertRaises(RuntimeError): policy.get_event_loop() except: res += sys.exc_info() # Initially, the thread has no event loop thread = threading.Thread(target=lambda: thread_func(res)) thread.start() thread.join() if res: t, v, tb = res raise t(v).with_traceback(tb) loop.close() def test_outside_context_iteration(self): """Iterating the main context from the outside, does not cause the EventLoop to dispatch. """ policy = self.create_policy() loop = policy.new_event_loop() called = False def cb(): nonlocal called called = True loop.call_soon(cb) while loop._context.iteration(False): pass loop.close() self.assertEqual(called, False) def test_inside_context_iteration(self): """Iterating the main context from the inside, does not cause the EventLoop to dispatch. """ policy = self.create_policy() loop = policy.get_event_loop() done = asyncio.Future(loop=loop) called = False def cb(): nonlocal called called = True def ctx_iterate(): nonlocal called loop.call_soon(cb) while loop._context.iteration(False): pass self.assertEqual(called, False) # If we by-pass the override, then the callback is called while super(GLib.MainContext, loop._context).iteration(False): pass self.assertEqual(called, True) # It'll also be called (again) before run_until_complete finishes called = False loop.call_soon(cb) done.set_result(True) return GLib.SOURCE_REMOVE GLib.idle_add(ctx_iterate) loop.run_until_complete(done) loop.close() self.assertEqual(called, True) @unittest.skipUnless(Gtk, "no Gtk") def test_recursive_stop(self): """Calling stop() on the EventLoop will quit it, even if iteration is done recursively. """ policy = self.create_policy() asyncio.set_event_loop_policy(policy) self.addCleanup(asyncio.set_event_loop_policy, None) loop = policy.get_event_loop() if not GTK4: def main_gtk(): GLib.idle_add(loop.stop) Gtk.main() GLib.idle_add(main_gtk) Gtk.main() def main_glib(): GLib.idle_add(loop.stop) GLib.MainLoop().run() GLib.idle_add(main_glib) GLib.MainLoop().run() loop.close() def test_glib_task_prio(self): """Check that we can set a task priority.""" policy = self.create_policy() loop = policy.new_event_loop() order = [] async def run_prio(priority): # Note that asyncio.sleep(0) is a special case that not sleep nonlocal order await asyncio.sleep(0) order.append(priority) await asyncio.sleep(0) order.append(priority) await asyncio.sleep(0) order.append(priority) async def run(): t1 = asyncio.create_task(run_prio(GLib.PRIORITY_DEFAULT_IDLE)) t1.set_priority(GLib.PRIORITY_DEFAULT_IDLE) t2 = asyncio.create_task(run_prio(GLib.PRIORITY_DEFAULT)) t2.set_priority(GLib.PRIORITY_DEFAULT) t3 = asyncio.create_task(run_prio(GLib.PRIORITY_HIGH)) t3.set_priority(GLib.PRIORITY_HIGH) pending = (t1, t2, t3) while pending: _, pending = await asyncio.wait(pending) loop.run_until_complete(run()) loop.close() # Check that the order was correct self.assertEqual( order, [GLib.PRIORITY_HIGH] * 3 + [GLib.PRIORITY_DEFAULT] * 3 + [GLib.PRIORITY_DEFAULT_IDLE] * 3, ) @unittest.skipIf(sys.platform == "win32", "add reader/writer not implemented") def test_source_fileobj_fd(self): """Regression test for https://gitlab.gnome.org/GNOME/pygobject/-/issues/689 """ class Echo: def __init__(self, sock, expect_bytes): self.sock = sock self.sent_bytes = 0 self.expect_bytes = expect_bytes self.done = asyncio.Future() self.data = b"" def send(self): if self.done.done(): return if self.sent_bytes < len(self.data): self.sent_bytes += self.sock.send(self.data[self.sent_bytes :]) if self.sent_bytes >= self.expect_bytes: self.done.set_result(None) self.sock.shutdown(socket.SHUT_WR) def recv(self): if self.done.done(): return self.data += self.sock.recv(self.expect_bytes) if len(self.data) >= self.expect_bytes: self.sock.shutdown(socket.SHUT_RD) async def run(): loop = asyncio.get_running_loop() s1, s2 = socket.socketpair() sample = b"Hello!" e = Echo(s1, len(sample)) # register using file object and file descriptor loop.add_reader(s1, e.recv) loop.add_writer(s1.fileno(), e.send) s2.sendall(sample) await asyncio.wait_for(e.done, timeout=2.0) echo = b"" for _ in range(len(sample)): echo += s2.recv(len(sample)) if len(echo) == len(sample): break # remove using file object and file descriptor loop.remove_reader(s1) loop.remove_writer(s1.fileno()) s1.close() s2.close() # check if the data was echoed correctly self.assertEqual(sample, echo) policy = self.create_policy() loop = policy.get_event_loop() loop.run_until_complete(run()) loop.close() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_everything.py0000664000000000000000000015373415074673150017322 0ustar00rootrootimport contextlib import unittest import traceback import ctypes import warnings import sys import os import re import platform import gc import timeit import random import pytest from gi.repository import Regress as Everything from gi.repository import GObject from gi.repository import GLib from gi.repository import Gio try: from gi.repository import Gtk Gtk except ImportError: Gtk = None from .helper import capture_exceptions const_str = b"const \xe2\x99\xa5 utf8".decode("UTF-8") noconst_str = "non" + const_str class RawGList(ctypes.Structure): _fields_ = [ ("data", ctypes.c_void_p), ("next", ctypes.c_void_p), ("prev", ctypes.c_void_p), ] @classmethod def from_wrapped(cls, obj): offset = sys.getsizeof(object()) # size of PyObject_HEAD return ctypes.POINTER(cls).from_address(id(obj) + offset) class TestInstanceTransfer(unittest.TestCase): def test_main(self): obj = Everything.TestObj() for _ in range(10): obj.instance_method_full() class TestEverything(unittest.TestCase): def test_bool(self): self.assertEqual(Everything.test_boolean(False), False) self.assertEqual(Everything.test_boolean(True), True) self.assertEqual(Everything.test_boolean("hello"), True) self.assertEqual(Everything.test_boolean(""), False) self.assertEqual(Everything.test_boolean_true(True), True) self.assertEqual(Everything.test_boolean_false(False), False) def test_int8(self): self.assertEqual(Everything.test_int8(GLib.MAXINT8), GLib.MAXINT8) self.assertEqual(Everything.test_int8(GLib.MININT8), GLib.MININT8) self.assertRaises(OverflowError, Everything.test_int8, GLib.MAXINT8 + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXINT8 + 1} not in range {GLib.MININT8} to {GLib.MAXINT8}", ): Everything.test_int8(GLib.MAXINT8 + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range {GLib.MININT8} to {GLib.MAXINT8}", ): Everything.test_int8(GLib.MAXUINT64 * 2) def test_uint8(self): self.assertEqual(Everything.test_uint8(GLib.MAXUINT8), GLib.MAXUINT8) self.assertEqual(Everything.test_uint8(0), 0) self.assertRaises(OverflowError, Everything.test_uint8, -1) self.assertRaises(OverflowError, Everything.test_uint8, GLib.MAXUINT8 + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT8 + 1} not in range 0 to {GLib.MAXUINT8}", ): Everything.test_uint8(GLib.MAXUINT8 + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range 0 to {GLib.MAXUINT8}", ): Everything.test_uint8(GLib.MAXUINT64 * 2) def test_int16(self): self.assertEqual(Everything.test_int16(GLib.MAXINT16), GLib.MAXINT16) self.assertEqual(Everything.test_int16(GLib.MININT16), GLib.MININT16) with pytest.raises(OverflowError, match="32768 not in range -32768 to 32767"): Everything.test_int16(GLib.MAXINT16 + 1) with pytest.raises( OverflowError, match="36893488147419103230 not in range -32768 to 32767" ): Everything.test_int16(GLib.MAXUINT64 * 2) def test_uint16(self): self.assertEqual(Everything.test_uint16(GLib.MAXUINT16), GLib.MAXUINT16) self.assertEqual(Everything.test_uint16(0), 0) self.assertRaises(OverflowError, Everything.test_uint16, -1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT16 + 1} not in range 0 to {GLib.MAXUINT16}", ): Everything.test_uint16(GLib.MAXUINT16 + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range 0 to {GLib.MAXUINT16}", ): Everything.test_uint16(GLib.MAXUINT64 * 2) def test_int32(self): self.assertEqual(Everything.test_int32(GLib.MAXINT32), GLib.MAXINT32) self.assertEqual(Everything.test_int32(GLib.MININT32), GLib.MININT32) with pytest.raises( OverflowError, match="2147483648 not in range -2147483648 to 2147483647" ): Everything.test_int32(GLib.MAXINT32 + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXINT64 + 1} not in range -2147483648 to 2147483647", ): Everything.test_int32(GLib.MAXINT64 + 1) def test_uint32(self): self.assertEqual(Everything.test_uint32(GLib.MAXUINT32), GLib.MAXUINT32) self.assertEqual(Everything.test_uint32(0), 0) self.assertRaises(OverflowError, Everything.test_uint32, -1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT32 + 1} not in range 0 to {GLib.MAXUINT32}", ): Everything.test_uint32(GLib.MAXUINT32 + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range 0 to {GLib.MAXUINT32}", ): Everything.test_uint32(GLib.MAXUINT64 * 2) def test_int64(self): self.assertEqual(Everything.test_int64(GLib.MAXINT64), GLib.MAXINT64) self.assertEqual(Everything.test_int64(GLib.MININT64), GLib.MININT64) with pytest.raises( OverflowError, match=f"{GLib.MAXINT64 + 1} not in range {GLib.MININT64} to {GLib.MAXINT64}", ): Everything.test_int64(GLib.MAXINT64 + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range {GLib.MININT64} to {GLib.MAXINT64}", ): Everything.test_int64(GLib.MAXUINT64 * 2) def test_uint64(self): self.assertEqual(Everything.test_uint64(GLib.MAXUINT64), GLib.MAXUINT64) self.assertEqual(Everything.test_uint64(0), 0) self.assertRaises(OverflowError, Everything.test_uint64, -1) self.assertRaises(OverflowError, Everything.test_uint64, GLib.MAXUINT64 + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 + 1} not in range 0 to {GLib.MAXUINT64}", ): Everything.test_uint64(GLib.MAXUINT64 + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range 0 to {GLib.MAXUINT64}", ): Everything.test_uint64(GLib.MAXUINT64 * 2) def test_int(self): self.assertEqual(Everything.test_int(GLib.MAXINT), GLib.MAXINT) self.assertEqual(Everything.test_int(GLib.MININT), GLib.MININT) with pytest.raises( OverflowError, match=f"{GLib.MAXINT + 1} not in range {GLib.MININT} to {GLib.MAXINT}", ): Everything.test_int(GLib.MAXINT + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range {GLib.MININT} to {GLib.MAXINT}", ): Everything.test_int(GLib.MAXUINT64 * 2) def test_uint(self): self.assertEqual(Everything.test_uint(GLib.MAXUINT), GLib.MAXUINT) self.assertEqual(Everything.test_uint(0), 0) self.assertRaises(OverflowError, Everything.test_uint, -1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT + 1} not in range 0 to {GLib.MAXUINT}", ): Everything.test_uint(GLib.MAXUINT + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range 0 to {GLib.MAXUINT}", ): Everything.test_uint(GLib.MAXUINT64 * 2) def test_short(self): self.assertEqual(Everything.test_short(GLib.MAXSHORT), GLib.MAXSHORT) self.assertEqual(Everything.test_short(GLib.MINSHORT), GLib.MINSHORT) with pytest.raises( OverflowError, match=f"{GLib.MAXSHORT + 1} not in range {GLib.MINSHORT} to {GLib.MAXSHORT}", ): Everything.test_short(GLib.MAXSHORT + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range {GLib.MINSHORT} to {GLib.MAXSHORT}", ): Everything.test_short(GLib.MAXUINT64 * 2) def test_ushort(self): self.assertEqual(Everything.test_ushort(GLib.MAXUSHORT), GLib.MAXUSHORT) self.assertEqual(Everything.test_ushort(0), 0) self.assertRaises(OverflowError, Everything.test_ushort, -1) with pytest.raises( OverflowError, match=f"{GLib.MAXUSHORT + 1} not in range 0 to {GLib.MAXUSHORT}", ): Everything.test_ushort(GLib.MAXUSHORT + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range 0 to {GLib.MAXUSHORT}", ): Everything.test_ushort(GLib.MAXUINT64 * 2) def test_long(self): self.assertEqual(Everything.test_long(GLib.MAXLONG), GLib.MAXLONG) self.assertEqual(Everything.test_long(GLib.MINLONG), GLib.MINLONG) self.assertRaises(OverflowError, Everything.test_long, GLib.MAXLONG + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXLONG + 1} not in range {GLib.MINLONG} to {GLib.MAXLONG}", ): Everything.test_long(GLib.MAXLONG + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range {GLib.MINLONG} to {GLib.MAXLONG}", ): Everything.test_long(GLib.MAXUINT64 * 2) def test_ulong(self): self.assertEqual(Everything.test_ulong(GLib.MAXULONG), GLib.MAXULONG) self.assertEqual(Everything.test_ulong(0), 0) self.assertRaises(OverflowError, Everything.test_ulong, -1) with pytest.raises( OverflowError, match=f"{GLib.MAXULONG + 1} not in range 0 to {GLib.MAXULONG}", ): Everything.test_ulong(GLib.MAXULONG + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range 0 to {GLib.MAXULONG}", ): Everything.test_ulong(GLib.MAXUINT64 * 2) def test_ssize(self): self.assertEqual(Everything.test_ssize(GLib.MAXSSIZE), GLib.MAXSSIZE) self.assertEqual(Everything.test_ssize(GLib.MINSSIZE), GLib.MINSSIZE) self.assertRaises(OverflowError, Everything.test_ssize, GLib.MAXSSIZE + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXSSIZE + 1} not in range {GLib.MINSSIZE} to {GLib.MAXSSIZE}", ): Everything.test_ssize(GLib.MAXSSIZE + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range {GLib.MINSSIZE} to {GLib.MAXSSIZE}", ): Everything.test_ssize(GLib.MAXUINT64 * 2) def test_size(self): self.assertEqual(Everything.test_size(GLib.MAXSIZE), GLib.MAXSIZE) self.assertEqual(Everything.test_size(0), 0) self.assertRaises(OverflowError, Everything.test_size, -1) self.assertRaises(OverflowError, Everything.test_size, GLib.MAXSIZE + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXSIZE + 1} not in range 0 to {GLib.MAXSIZE}", ): Everything.test_size(GLib.MAXSIZE + 1) with pytest.raises( OverflowError, match=f"{GLib.MAXUINT64 * 2} not in range 0 to {GLib.MAXSIZE}", ): Everything.test_size(GLib.MAXUINT64 * 2) def test_timet(self): self.assertEqual(Everything.test_timet(42), 42) self.assertRaises(OverflowError, Everything.test_timet, GLib.MAXUINT64 + 1) def test_unichar(self): self.assertEqual("c", Everything.test_unichar("c")) self.assertEqual( chr(sys.maxunicode), Everything.test_unichar(chr(sys.maxunicode)) ) self.assertEqual("♥", Everything.test_unichar("♥")) self.assertRaises(TypeError, Everything.test_unichar, "") self.assertRaises(TypeError, Everything.test_unichar, "morethanonechar") def test_float(self): self.assertEqual(Everything.test_float(GLib.MAXFLOAT), GLib.MAXFLOAT) self.assertEqual(Everything.test_float(GLib.MINFLOAT), GLib.MINFLOAT) self.assertRaises(OverflowError, Everything.test_float, GLib.MAXFLOAT * 2) with pytest.raises( OverflowError, match=re.escape( f"{GLib.MAXFLOAT * 2} not in range {-GLib.MAXFLOAT} to {GLib.MAXFLOAT}" ), ): Everything.test_float(GLib.MAXFLOAT * 2) def test_double(self): self.assertEqual(Everything.test_double(GLib.MAXDOUBLE), GLib.MAXDOUBLE) self.assertEqual(Everything.test_double(GLib.MINDOUBLE), GLib.MINDOUBLE) (two, three) = Everything.test_multi_double_args(2.5) self.assertAlmostEqual(two, 5.0) self.assertAlmostEqual(three, 7.5) def test_value(self): self.assertEqual(Everything.test_int_value_arg(GLib.MAXINT), GLib.MAXINT) self.assertEqual(Everything.test_value_return(GLib.MAXINT), GLib.MAXINT) def test_variant(self): v = Everything.test_gvariant_i() self.assertEqual(v.get_type_string(), "i") self.assertEqual(v.get_int32(), 1) v = Everything.test_gvariant_s() self.assertEqual(v.get_type_string(), "s") self.assertEqual(v.get_string(), "one") v = Everything.test_gvariant_v() self.assertEqual(v.get_type_string(), "v") vi = v.get_variant() self.assertEqual(vi.get_type_string(), "s") self.assertEqual(vi.get_string(), "contents") v = Everything.test_gvariant_as() self.assertEqual(v.get_type_string(), "as") self.assertEqual(v.get_strv(), ["one", "two", "three"]) v = Everything.test_gvariant_asv() self.assertEqual(v.get_type_string(), "a{sv}") self.assertEqual(v.lookup_value("nosuchkey", None), None) name = v.lookup_value("name", None) self.assertEqual(name.get_string(), "foo") timeout = v.lookup_value("timeout", None) self.assertEqual(timeout.get_int32(), 10) def test_utf8_const_return(self): self.assertEqual(Everything.test_utf8_const_return(), const_str) def test_utf8_nonconst_return(self): self.assertEqual(Everything.test_utf8_nonconst_return(), noconst_str) def test_utf8_out(self): self.assertEqual(Everything.test_utf8_out(), noconst_str) def test_utf8_const_in(self): Everything.test_utf8_const_in(const_str) def test_utf8_inout(self): self.assertEqual(Everything.test_utf8_inout(const_str), noconst_str) def test_filename_return(self): if os.name != "nt": result = [os.fsdecode(b"\xc3\xa5\xc3\xa4\xc3\xb6"), "/etc/fstab"] else: result = ["åäö", "/etc/fstab"] self.assertEqual(Everything.test_filename_return(), result) def test_int_out_utf8(self): # returns g_utf8_strlen() in out argument self.assertEqual(Everything.test_int_out_utf8(""), 0) self.assertEqual(Everything.test_int_out_utf8("hello world"), 11) self.assertEqual(Everything.test_int_out_utf8("åäö"), 3) def test_utf8_out_out(self): self.assertEqual(Everything.test_utf8_out_out(), ("first", "second")) def test_utf8_out_nonconst_return(self): self.assertEqual( Everything.test_utf8_out_nonconst_return(), ("first", "second") ) def test_enum(self): self.assertEqual( Everything.test_enum_param(Everything.TestEnum.VALUE1), "value1" ) self.assertEqual( Everything.test_enum_param(Everything.TestEnum.VALUE3), "value3" ) self.assertRaises(TypeError, Everything.test_enum_param, "hello") @pytest.mark.xfail( "32bit" in platform.architecture() or platform.system() == "Windows", reason="Big enum value doesn't convert to 32 bit (signed) long", ) def test_enum_unsigned(self): self.assertEqual( Everything.test_unsigned_enum_param(Everything.TestEnumUnsigned.VALUE1), "value1", ) self.assertEqual( Everything.test_unsigned_enum_param(Everything.TestEnumUnsigned.VALUE2), "value2", ) self.assertRaises(TypeError, Everything.test_unsigned_enum_param, "hello") def test_flags(self): result = Everything.global_get_flags_out() # assert that it's not an int self.assertEqual(type(result), Everything.TestFlags) self.assertEqual( result, Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3 ) def test_floating(self): e = Everything.TestFloating() self.assertEqual(e.__grefcount__, 1) e = GObject.new(Everything.TestFloating) self.assertEqual(e.__grefcount__, 1) e = Everything.TestFloating.new() self.assertEqual(e.__grefcount__, 1) def test_caller_allocates(self): struct_a = Everything.TestStructA() struct_a.some_int = 10 struct_a.some_int8 = 21 struct_a.some_double = 3.14 struct_a.some_enum = Everything.TestEnum.VALUE3 struct_a_clone = struct_a.clone() self.assertTrue(struct_a != struct_a_clone) self.assertEqual(struct_a.some_int, struct_a_clone.some_int) self.assertEqual(struct_a.some_int8, struct_a_clone.some_int8) self.assertEqual(struct_a.some_double, struct_a_clone.some_double) self.assertEqual(struct_a.some_enum, struct_a_clone.some_enum) struct_b = Everything.TestStructB() struct_b.some_int8 = 8 struct_b.nested_a.some_int = 20 struct_b.nested_a.some_int8 = 12 struct_b.nested_a.some_double = 333.3333 struct_b.nested_a.some_enum = Everything.TestEnum.VALUE2 struct_b_clone = struct_b.clone() self.assertTrue(struct_b != struct_b_clone) self.assertEqual(struct_b.some_int8, struct_b_clone.some_int8) self.assertEqual(struct_b.nested_a.some_int, struct_b_clone.nested_a.some_int) self.assertEqual(struct_b.nested_a.some_int8, struct_b_clone.nested_a.some_int8) self.assertEqual( struct_b.nested_a.some_double, struct_b_clone.nested_a.some_double ) self.assertEqual(struct_b.nested_a.some_enum, struct_b_clone.nested_a.some_enum) struct_a = Everything.test_struct_a_parse("ignored") self.assertEqual(struct_a.some_int, 23) def test_wrong_type_of_arguments(self): try: Everything.test_int8() except TypeError: (_e_type, e) = sys.exc_info()[:2] self.assertEqual( e.args, ("Regress.test_int8() takes exactly 1 argument (0 given)",) ) def test_gtypes(self): gchararray_gtype = GObject.type_from_name("gchararray") gtype = Everything.test_gtype(str) self.assertEqual(gchararray_gtype, gtype) gtype = Everything.test_gtype("gchararray") self.assertEqual(gchararray_gtype, gtype) gobject_gtype = GObject.GObject.__gtype__ gtype = Everything.test_gtype(GObject.GObject) self.assertEqual(gobject_gtype, gtype) gtype = Everything.test_gtype("GObject") self.assertEqual(gobject_gtype, gtype) self.assertRaises(TypeError, Everything.test_gtype, "invalidgtype") class NotARegisteredClass: pass self.assertRaises(TypeError, Everything.test_gtype, NotARegisteredClass) class ARegisteredClass(GObject.GObject): __gtype_name__ = "EverythingTestsARegisteredClass" gtype = Everything.test_gtype("EverythingTestsARegisteredClass") self.assertEqual(ARegisteredClass.__gtype__, gtype) gtype = Everything.test_gtype(ARegisteredClass) self.assertEqual(ARegisteredClass.__gtype__, gtype) self.assertRaises(TypeError, Everything.test_gtype, "ARegisteredClass") def test_dir(self): attr_list = dir(Everything) # test that typelib attributes are listed self.assertIn("TestStructA", attr_list) # test that instance members are listed self.assertIn("_namespace", attr_list) self.assertIn("_version", attr_list) # test that there are no duplicates returned self.assertEqual(len(attr_list), len(set(attr_list))) def test_array_int_in_empty(self): self.assertEqual(Everything.test_array_int_in([]), 0) def test_array_int_in(self): self.assertEqual(Everything.test_array_int_in([1, 5, -2]), 4) def test_array_int_out(self): self.assertEqual(Everything.test_array_int_out(), [0, 1, 2, 3, 4]) def test_array_int_full_out(self): self.assertEqual(Everything.test_array_int_full_out(), [0, 1, 2, 3, 4]) def test_array_int_none_out(self): self.assertEqual(Everything.test_array_int_none_out(), [1, 2, 3, 4, 5]) def test_array_int_inout(self): self.assertEqual(Everything.test_array_int_inout([1, 5, 42, -8]), [6, 43, -7]) def test_array_int_inout_empty(self): self.assertEqual(Everything.test_array_int_inout([]), []) def test_array_gint8_in(self): self.assertEqual(Everything.test_array_gint8_in(b"\x01\x03\x05"), 9) self.assertEqual(Everything.test_array_gint8_in([1, 3, 5, -50]), -41) def test_array_gint16_in(self): self.assertEqual( Everything.test_array_gint16_in([256, 257, -1000, 10000]), 9513 ) def test_array_gint32_in(self): self.assertEqual(Everything.test_array_gint32_in([30000, 1, -2]), 29999) def test_array_gint64_in(self): self.assertEqual(Everything.test_array_gint64_in([2**33, 2**34]), 2**33 + 2**34) def test_array_gtype_in(self): self.assertEqual( Everything.test_array_gtype_in( [GObject.TYPE_STRING, GObject.TYPE_UINT64, GObject.TYPE_VARIANT] ), "[gchararray,guint64,GVariant,]", ) def test_array_fixed_size_int_in(self): # fixed length of 5 self.assertEqual(Everything.test_array_fixed_size_int_in([1, 2, -10, 5, 3]), 1) def test_array_fixed_size_int_in_error(self): self.assertRaises( ValueError, Everything.test_array_fixed_size_int_in, [1, 2, 3, 4] ) self.assertRaises( ValueError, Everything.test_array_fixed_size_int_in, [1, 2, 3, 4, 5, 6] ) def test_array_fixed_size_int_out(self): self.assertEqual(Everything.test_array_fixed_size_int_out(), [0, 1, 2, 3, 4]) def test_array_fixed_size_int_return(self): self.assertEqual(Everything.test_array_fixed_size_int_return(), [0, 1, 2, 3, 4]) def test_array_of_non_utf8_strings(self): with pytest.raises(UnicodeDecodeError): Everything.test_array_of_non_utf8_strings() def test_garray_container_return(self): # GPtrArray transfer container result = Everything.test_garray_container_return() self.assertEqual(result, ["regress"]) result = None def test_garray_full_return(self): # GPtrArray transfer full result = Everything.test_garray_full_return() self.assertEqual(result, ["regress"]) result = None def test_strv_out(self): self.assertEqual( Everything.test_strv_out(), ["thanks", "for", "all", "the", "fish"] ) def test_strv_out_c(self): self.assertEqual( Everything.test_strv_out_c(), ["thanks", "for", "all", "the", "fish"] ) def test_strv_out_container(self): self.assertEqual(Everything.test_strv_out_container(), ["1", "2", "3"]) def test_strv_outarg(self): self.assertEqual(Everything.test_strv_outarg(), ["1", "2", "3"]) def test_strv_in_gvalue(self): self.assertEqual(Everything.test_strv_in_gvalue(), ["one", "two", "three"]) def test_strv_in(self): Everything.test_strv_in(["1", "2", "3"]) def test_glist(self): self.assertEqual(Everything.test_glist_nothing_return(), ["1", "2", "3"]) self.assertEqual(Everything.test_glist_nothing_return2(), ["1", "2", "3"]) self.assertEqual(Everything.test_glist_container_return(), ["1", "2", "3"]) self.assertEqual(Everything.test_glist_everything_return(), ["1", "2", "3"]) Everything.test_glist_nothing_in(["1", "2", "3"]) Everything.test_glist_nothing_in2(["1", "2", "3"]) @unittest.skipUnless( hasattr(Everything, "test_glist_gtype_container_in"), "Requires newer version of GI", ) def test_glist_gtype(self): Everything.test_glist_gtype_container_in( [Everything.TestObj, Everything.TestSubObj] ) def test_gslist(self): self.assertEqual(Everything.test_gslist_nothing_return(), ["1", "2", "3"]) self.assertEqual(Everything.test_gslist_nothing_return2(), ["1", "2", "3"]) self.assertEqual(Everything.test_gslist_container_return(), ["1", "2", "3"]) self.assertEqual(Everything.test_gslist_everything_return(), ["1", "2", "3"]) Everything.test_gslist_nothing_in(["1", "2", "3"]) Everything.test_gslist_nothing_in2(["1", "2", "3"]) def test_hash_return(self): expected = {"foo": "bar", "baz": "bat", "qux": "quux"} self.assertEqual(Everything.test_ghash_null_return(), None) self.assertEqual(Everything.test_ghash_nothing_return(), expected) self.assertEqual(Everything.test_ghash_nothing_return(), expected) self.assertEqual(Everything.test_ghash_container_return(), expected) self.assertEqual(Everything.test_ghash_everything_return(), expected) result = Everything.test_ghash_gvalue_return() self.assertEqual(result["integer"], 12) self.assertEqual(result["boolean"], True) self.assertEqual(result["string"], "some text") self.assertEqual(result["strings"], ["first", "second", "third"]) self.assertEqual( result["flags"], Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3 ) self.assertEqual(result["enum"], Everything.TestEnum.VALUE2) result = None # FIXME: CRITICAL **: Unsupported type ghash def disabled_test_hash_return_nested(self): self.assertEqual(Everything.test_ghash_nested_everything_return(), {}) self.assertEqual(Everything.test_ghash_nested_everything_return2(), {}) def test_hash_in(self): expected = {"foo": "bar", "baz": "bat", "qux": "quux"} Everything.test_ghash_nothing_in(expected) Everything.test_ghash_nothing_in2(expected) def test_hash_in_with_typed_strv(self): class GStrv(list): __gtype__ = GObject.TYPE_STRV data = { "integer": 12, "boolean": True, "string": "some text", "strings": GStrv(["first", "second", "third"]), "flags": Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3, "enum": Everything.TestEnum.VALUE2, } Everything.test_ghash_gvalue_in(data) data = None def test_hash_in_with_gvalue_strv(self): data = { "integer": 12, "boolean": True, "string": "some text", "strings": GObject.Value(GObject.TYPE_STRV, ["first", "second", "third"]), "flags": Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3, "enum": Everything.TestEnum.VALUE2, } Everything.test_ghash_gvalue_in(data) data = None @unittest.skipIf(platform.python_implementation() == "PyPy", "CPython only") def test_struct_gpointer(self): glist = GLib.List() raw = RawGList.from_wrapped(glist) # Note that pointer fields use 0 for NULL in PyGObject and None in ctypes self.assertEqual(glist.data, 0) self.assertEqual(raw.contents.data, None) glist.data = 123 self.assertEqual(glist.data, 123) self.assertEqual(raw.contents.data, 123) glist.data = None self.assertEqual(glist.data, 0) self.assertEqual(raw.contents.data, None) # Setting to anything other than an int should raise self.assertRaises(TypeError, setattr, glist.data, "nan") self.assertRaises(TypeError, setattr, glist.data, object()) self.assertRaises(TypeError, setattr, glist.data, 123.321) def test_struct_opaque(self): # we should get a sensible error message try: Everything.TestBoxedPrivate() self.fail( "allocating disguised struct without default constructor unexpectedly succeeded" ) except TypeError: (e_type, e_value, e_tb) = sys.exc_info() self.assertEqual(e_type, TypeError) self.assertTrue("TestBoxedPrivate" in str(e_value), str(e_value)) self.assertTrue("constructor" in str(e_value), str(e_value)) tb = "".join(traceback.format_exception(e_type, e_value, e_tb)) self.assertTrue('test_everything.py", line' in tb, tb) class TestNullableArgs(unittest.TestCase): def test_in_nullable_hash(self): Everything.test_ghash_null_in(None) def test_in_nullable_list(self): Everything.test_gslist_null_in(None) Everything.test_glist_null_in(None) Everything.test_gslist_null_in([]) Everything.test_glist_null_in([]) def test_in_nullable_array(self): Everything.test_array_int_null_in(None) Everything.test_array_int_null_in([]) def test_in_nullable_string(self): Everything.test_utf8_null_in(None) def test_in_nullable_object(self): Everything.func_obj_null_in(None) def test_out_nullable_hash(self): self.assertEqual(None, Everything.test_ghash_null_out()) def test_out_nullable_list(self): self.assertEqual([], Everything.test_gslist_null_out()) self.assertEqual([], Everything.test_glist_null_out()) def test_out_nullable_array(self): self.assertEqual([], Everything.test_array_int_null_out()) def test_out_nullable_string(self): self.assertEqual(None, Everything.test_utf8_null_out()) def test_out_nullable_object(self): self.assertEqual(None, Everything.TestObj.null_out()) class TestCallbacks(unittest.TestCase): called = False main_loop = GLib.MainLoop() def test_callback(self): TestCallbacks.called = False def callback(): TestCallbacks.called = True Everything.test_simple_callback(callback) self.assertTrue(TestCallbacks.called) def test_callback_exception(self): """This test ensures that we get errors from callbacks correctly and in particular that we do not segv when callbacks fail. """ def callback(): x = 1 / 0 self.fail("unexpected surviving zero divsion:" + str(x)) # note that we do NOT expect the ZeroDivisionError to be propagated # through from the callback, as it crosses the Python<->C boundary # twice. (See GNOME #616279) with capture_exceptions() as exc: Everything.test_simple_callback(callback) self.assertTrue(exc) self.assertEqual(exc[0].type, ZeroDivisionError) def test_double_callback_exception(self): """This test ensures that we get errors from callbacks correctly and in particular that we do not segv when callbacks fail. """ def badcallback(): x = 1 / 0 self.fail("unexpected surviving zero divsion:" + str(x)) def callback(): Everything.test_boolean(True) Everything.test_boolean(False) Everything.test_simple_callback(badcallback()) # note that we do NOT expect the ZeroDivisionError to be propagated # through from the callback, as it crosses the Python<->C boundary # twice. (See GNOME #616279) with capture_exceptions() as exc: Everything.test_simple_callback(callback) self.assertTrue(exc) self.assertEqual(exc[0].type, ZeroDivisionError) def test_return_value_callback(self): TestCallbacks.called = False def callback(): TestCallbacks.called = True return 44 self.assertEqual(Everything.test_callback(callback), 44) self.assertTrue(TestCallbacks.called) def test_callback_scope_async(self): TestCallbacks.called = False ud = "Test Value 44" def callback(user_data): self.assertEqual(user_data, ud) TestCallbacks.called = True return 44 if hasattr(sys, "getrefcount"): ud_refcount = sys.getrefcount(ud) callback_refcount = sys.getrefcount(callback) self.assertEqual(Everything.test_callback_async(callback, ud), None) # Callback should not have run and the ref count is increased by 1 self.assertEqual(TestCallbacks.called, False) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(callback), callback_refcount + 1) self.assertEqual(sys.getrefcount(ud), ud_refcount + 1) # test_callback_thaw_async will run the callback previously supplied. # references should be auto decremented after this call. self.assertEqual(Everything.test_callback_thaw_async(), 44) self.assertTrue(TestCallbacks.called) # Make sure refcounts are returned to normal if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(callback), callback_refcount) self.assertEqual(sys.getrefcount(ud), ud_refcount) def test_callback_scope_call_multi(self): # This tests a callback that gets called multiple times from a # single scope call in python. TestCallbacks.called = 0 def callback(): TestCallbacks.called += 1 return TestCallbacks.called if hasattr(sys, "getrefcount"): refcount = sys.getrefcount(callback) result = Everything.test_multi_callback(callback) # first callback should give 1, second 2, and the function sums them up self.assertEqual(result, 3) self.assertEqual(TestCallbacks.called, 2) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(callback), refcount) def test_callback_scope_call_array(self): # This tests a callback that gets called multiple times from a # single scope call in python with array arguments TestCallbacks.callargs = [] # FIXME: would be cleaner without the explicit length args: # def callback(one, two): def callback(one, one_length, two, two_length): TestCallbacks.callargs.append((one, two)) return len(TestCallbacks.callargs) if hasattr(sys, "getrefcount"): refcount = sys.getrefcount(callback) result = Everything.test_array_callback(callback) # first callback should give 1, second 2, and the function sums them up self.assertEqual(result, 3) self.assertEqual( TestCallbacks.callargs, [([-1, 0, 1, 2], ["one", "two", "three"])] * 2 ) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(callback), refcount) @unittest.skipUnless( hasattr(Everything, "test_array_inout_callback"), "Requires newer version of GI" ) def test_callback_scope_call_array_inout(self): # This tests a callback that gets called multiple times from a # single scope call in python with inout array arguments TestCallbacks.callargs = [] def callback(ints, ints_length): TestCallbacks.callargs.append(ints) return ints[1:], len(ints[1:]) if hasattr(sys, "getrefcount"): refcount = sys.getrefcount(callback) result = Everything.test_array_inout_callback(callback) self.assertEqual(TestCallbacks.callargs, [[-2, -1, 0, 1, 2], [-1, 0, 1, 2]]) # first callback should give 4, second 3 self.assertEqual(result, 3) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(callback), refcount) def test_callback_userdata(self): TestCallbacks.called = 0 def callback(userdata): self.assertEqual(userdata, f"Test{TestCallbacks.called:d}") TestCallbacks.called += 1 return TestCallbacks.called for i in range(100): val = Everything.test_callback_user_data(callback, f"Test{i:d}") self.assertEqual(val, i + 1) self.assertEqual(TestCallbacks.called, 100) def test_callback_userdata_no_user_data(self): TestCallbacks.called = 0 def callback(): TestCallbacks.called += 1 return TestCallbacks.called for i in range(100): val = Everything.test_callback_user_data(callback) self.assertEqual(val, i + 1) self.assertEqual(TestCallbacks.called, 100) def test_callback_userdata_varargs(self): TestCallbacks.called = 0 collected_user_data = [] def callback(a, b): collected_user_data.extend([a, b]) TestCallbacks.called += 1 return TestCallbacks.called for i in range(10): val = Everything.test_callback_user_data(callback, 1, 2) self.assertEqual(val, i + 1) self.assertEqual(TestCallbacks.called, 10) self.assertSequenceEqual(collected_user_data, [1, 2] * 10) def test_callback_userdata_as_kwarg_tuple(self): TestCallbacks.called = 0 collected_user_data = [] def callback(user_data): collected_user_data.extend(user_data) TestCallbacks.called += 1 return TestCallbacks.called for i in range(10): val = Everything.test_callback_user_data(callback, user_data=(1, 2)) self.assertEqual(val, i + 1) self.assertEqual(TestCallbacks.called, 10) self.assertSequenceEqual(collected_user_data, [1, 2] * 10) def test_callback_user_data_middle_none(self): cb_info = {} def callback(userdata): cb_info["called"] = True cb_info["userdata"] = userdata return 1 (y, z, q) = Everything.test_torture_signature_2( 42, callback, None, "some string", 3 ) self.assertEqual(y, 42) self.assertEqual(z, 84) self.assertEqual(q, 14) self.assertTrue(cb_info["called"]) self.assertEqual(cb_info["userdata"], None) def test_callback_user_data_middle_single(self): cb_info = {} def callback(userdata): cb_info["called"] = True cb_info["userdata"] = userdata return 1 (y, z, q) = Everything.test_torture_signature_2( 42, callback, "User Data", "some string", 3 ) self.assertEqual(y, 42) self.assertEqual(z, 84) self.assertEqual(q, 14) self.assertTrue(cb_info["called"]) self.assertEqual(cb_info["userdata"], "User Data") def test_callback_user_data_middle_tuple(self): cb_info = {} def callback(userdata): cb_info["called"] = True cb_info["userdata"] = userdata return 1 (y, z, q) = Everything.test_torture_signature_2( 42, callback, (-5, "User Data"), "some string", 3 ) self.assertEqual(y, 42) self.assertEqual(z, 84) self.assertEqual(q, 14) self.assertTrue(cb_info["called"]) self.assertEqual(cb_info["userdata"], (-5, "User Data")) def test_async_ready_callback(self): TestCallbacks.called = False TestCallbacks.main_loop = GLib.MainLoop() def callback(obj, result, user_data): TestCallbacks.main_loop.quit() TestCallbacks.called = True Everything.test_async_ready_callback(callback) TestCallbacks.main_loop.run() self.assertTrue(TestCallbacks.called) def test_callback_scope_notified_with_destroy(self): TestCallbacks.called = 0 ud = "Test scope notified data 33" def callback(user_data): self.assertEqual(user_data, ud) TestCallbacks.called += 1 return 33 if hasattr(sys, "getrefcount"): value_refcount = sys.getrefcount(ud) callback_refcount = sys.getrefcount(callback) # Callback is immediately called. for i in range(100): res = Everything.test_callback_destroy_notify(callback, ud) self.assertEqual(res, 33) self.assertEqual(TestCallbacks.called, 100) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(callback), callback_refcount + 100) self.assertEqual(sys.getrefcount(ud), value_refcount + 100) # thaw will call the callback again, this time resources should be freed self.assertEqual(Everything.test_callback_thaw_notifications(), 33 * 100) self.assertEqual(TestCallbacks.called, 200) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(callback), callback_refcount) self.assertEqual(sys.getrefcount(ud), value_refcount) def test_callback_scope_notified_with_destroy_no_user_data(self): TestCallbacks.called = 0 def callback(user_data): self.assertEqual(user_data, None) TestCallbacks.called += 1 return 34 if hasattr(sys, "getrefcount"): callback_refcount = sys.getrefcount(callback) # Run with warning as exception with warnings.catch_warnings(record=True) as w: warnings.simplefilter("error") self.assertRaises( RuntimeWarning, Everything.test_callback_destroy_notify_no_user_data, callback, ) self.assertEqual(TestCallbacks.called, 0) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(callback), callback_refcount) # Run with warning as warning with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("default") # Trigger a warning. res = Everything.test_callback_destroy_notify_no_user_data(callback) # Verify some things self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, RuntimeWarning)) self.assertTrue("Callables passed to" in str(w[-1].message)) self.assertEqual(res, 34) self.assertEqual(TestCallbacks.called, 1) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(callback), callback_refcount + 1) # thaw will call the callback again, # refcount will not go down without user_data parameter self.assertEqual(Everything.test_callback_thaw_notifications(), 34) self.assertEqual(TestCallbacks.called, 2) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(callback), callback_refcount + 1) def test_callback_in_methods(self): object_ = Everything.TestObj() def callback(): TestCallbacks.called = True return 42 TestCallbacks.called = False object_.instance_method_callback(callback) self.assertTrue(TestCallbacks.called) TestCallbacks.called = False Everything.TestObj.static_method_callback(callback) self.assertTrue(TestCallbacks.called) def callbackWithUserData(user_data): TestCallbacks.called += 1 return 42 TestCallbacks.called = 0 Everything.TestObj.new_callback(callbackWithUserData, None) self.assertEqual(TestCallbacks.called, 1) # Note: using "new_callback" adds the notification to the same global # list as Everything.test_callback_destroy_notify, so thaw the list # so we don't get confusion between tests. self.assertEqual(Everything.test_callback_thaw_notifications(), 42) self.assertEqual(TestCallbacks.called, 2) def test_callback_none(self): # make sure this doesn't assert or crash Everything.test_simple_callback(None) def test_callback_gerror(self): def callback(error): self.assertEqual(error.message, "regression test error") self.assertTrue("g-io" in error.domain) self.assertEqual(error.code, Gio.IOErrorEnum.NOT_SUPPORTED) TestCallbacks.called = True TestCallbacks.called = False Everything.test_gerror_callback(callback) self.assertTrue(TestCallbacks.called) def test_callback_null_gerror(self): def callback(error): self.assertEqual(error, None) TestCallbacks.called = True TestCallbacks.called = False Everything.test_null_gerror_callback(callback) self.assertTrue(TestCallbacks.called) def test_callback_owned_gerror(self): def callback(error): self.assertEqual(error.message, "regression test owned error") self.assertTrue("g-io" in error.domain) self.assertEqual(error.code, Gio.IOErrorEnum.PERMISSION_DENIED) TestCallbacks.called = True TestCallbacks.called = False Everything.test_owned_gerror_callback(callback) self.assertTrue(TestCallbacks.called) def test_callback_hashtable(self): def callback(data): self.assertEqual(data, mydict) mydict["new"] = 42 TestCallbacks.called = True mydict = {"foo": 1, "bar": 2} TestCallbacks.called = False Everything.test_hash_table_callback(mydict, callback) self.assertTrue(TestCallbacks.called) self.assertEqual(mydict, {"foo": 1, "bar": 2, "new": 42}) class TestClosures(unittest.TestCase): def test_no_arg(self): def callback(): self.called = True return 42 self.called = False result = Everything.test_closure(callback) self.assertTrue(self.called) self.assertEqual(result, 42) def test_int_arg(self): def callback(num): self.called = True return num + 1 self.called = False result = Everything.test_closure_one_arg(callback, 42) self.assertTrue(self.called) self.assertEqual(result, 43) def test_variant(self): def callback(variant): self.called = True if variant is None: return None self.assertEqual(variant.get_type_string(), "i") return GLib.Variant("i", variant.get_int32() + 1) self.called = False result = Everything.test_closure_variant(callback, GLib.Variant("i", 42)) self.assertTrue(self.called) self.assertEqual(result.get_type_string(), "i") self.assertEqual(result.get_int32(), 43) self.called = False result = Everything.test_closure_variant(callback, None) self.assertTrue(self.called) self.assertEqual(result, None) self.called = False self.assertRaises(TypeError, Everything.test_closure_variant, callback, "foo") self.assertFalse(self.called) def test_variant_wrong_return_type(self): def callback(variant): return "no_variant" with capture_exceptions() as exc: # this does not directly raise an exception (see # https://bugzilla.gnome.org/show_bug.cgi?id=616279) result = Everything.test_closure_variant(callback, GLib.Variant("i", 42)) # ... but the result shouldn't be a string self.assertEqual(result, None) # and the error should be shown self.assertEqual(len(exc), 1) self.assertEqual(exc[0].type, TypeError) self.assertTrue("return value" in str(exc[0].value), exc[0].value) class TestBoxed(unittest.TestCase): def test_boxed(self): object_ = Everything.TestObj() self.assertEqual(object_.props.boxed, None) boxed = Everything.TestBoxed() boxed.some_int8 = 42 object_.props.boxed = boxed self.assertTrue(isinstance(object_.props.boxed, Everything.TestBoxed)) self.assertEqual(object_.props.boxed.some_int8, 42) def test_boxed_alternative_constructor(self): boxed = Everything.TestBoxed.new_alternative_constructor1(5) self.assertEqual(boxed.some_int8, 5) boxed = Everything.TestBoxed.new_alternative_constructor2(5, 3) self.assertEqual(boxed.some_int8, 8) boxed = Everything.TestBoxed.new_alternative_constructor3("-3") self.assertEqual(boxed.some_int8, -3) def test_boxed_equality(self): boxed42 = Everything.TestBoxed.new_alternative_constructor1(42) boxed5 = Everything.TestBoxed.new_alternative_constructor1(5) boxed42_2 = Everything.TestBoxed.new_alternative_constructor2(41, 1) self.assertFalse(boxed42.equals(boxed5)) self.assertTrue(boxed42.equals(boxed42_2)) self.assertTrue(boxed42_2.equals(boxed42)) self.assertTrue(boxed42.equals(boxed42)) def test_boxed_b_constructor(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") boxed = Everything.TestBoxedB(42, 47) self.assertTrue(issubclass(warn[0].category, DeprecationWarning)) self.assertEqual(boxed.some_int8, 0) self.assertEqual(boxed.some_long, 0) def test_boxed_c_equality(self): boxed = Everything.TestBoxedC() # TestBoxedC uses refcounting, so we know that # the pointer is the same when copied copy = boxed.copy() self.assertEqual(boxed, copy) self.assertNotEqual(id(boxed), id(copy)) def test_boxed_c_wrapper(self): wrapper = Everything.TestBoxedCWrapper() obj = wrapper.get() # TestBoxedC uses refcounting, so we know that # it should be 2 at this point: # - one owned by @wrapper # - another owned by @obj self.assertEqual(obj.refcount, 2) del wrapper gc.collect() gc.collect() self.assertEqual(obj.refcount, 1) def test_boxed_c_wrapper_copy(self): wrapper = Everything.TestBoxedCWrapper() wrapper_copy = wrapper.copy() obj = wrapper.get() # TestBoxedC uses refcounting, so we know that # it should be 3 at this point: # - one owned by @wrapper # - one owned by @wrapper_copy # - another owned by @obj self.assertEqual(obj.refcount, 3) del wrapper gc.collect() gc.collect() self.assertEqual(obj.refcount, 2) del wrapper_copy gc.collect() gc.collect() self.assertEqual(obj.refcount, 1) del obj gc.collect() gc.collect() def test_array_fixed_boxed_none_out(self): arr = Everything.test_array_fixed_boxed_none_out() assert len(arr) == 2 assert arr[0].refcount == 2 assert arr[1].refcount == 2 def test_gvalue_out_boxed(self): # As corruption is random data, check several times. for i in range(10): int8 = random.randint(GLib.MININT8, GLib.MAXINT8) assert Everything.test_gvalue_out_boxed(int8).some_int8 == int8 def test_glist_boxed_none_return(self): assert len(Everything.test_glist_boxed_none_return(0)) == 0 list_ = Everything.test_glist_boxed_none_return(2) assert len(list_) == 2 assert list_[0].refcount == 2 assert list_[1].refcount == 2 def test_glist_boxed_full_return(self): assert len(Everything.test_glist_boxed_full_return(0)) == 0 list_ = Everything.test_glist_boxed_full_return(2) assert len(list_) == 2 assert list_[0].refcount == 1 assert list_[1].refcount == 1 class TestTortureProfile(unittest.TestCase): def test_torture_profile(self): total_time = 0 object_ = Everything.TestObj() sys.stdout.write("\ttorture test 1 (10000 iterations): ") start_time = timeit.default_timer() for i in range(10000): (_y, _z, _q) = object_.torture_signature_0(5000, "Torture Test 1", 12345) end_time = timeit.default_timer() delta_time = end_time - start_time total_time += delta_time sys.stdout.write("\ttorture test 2 (10000 iterations): ") start_time = timeit.default_timer() for i in range(10000): (_y, _z, _q) = Everything.TestObj().torture_signature_0( 5000, "Torture Test 2", 12345 ) end_time = timeit.default_timer() delta_time = end_time - start_time total_time += delta_time sys.stdout.write("\ttorture test 3 (10000 iterations): ") start_time = timeit.default_timer() for i in range(10000): with contextlib.suppress(Exception): (_y, _z, _q) = object_.torture_signature_1( 5000, "Torture Test 3", 12345 ) end_time = timeit.default_timer() delta_time = end_time - start_time total_time += delta_time sys.stdout.write("\ttorture test 4 (10000 iterations): ") def callback(userdata): return 0 userdata = [1, 2, 3, 4] start_time = timeit.default_timer() for i in range(10000): (_y, _z, _q) = Everything.test_torture_signature_2( 5000, callback, userdata, "Torture Test 4", 12345 ) end_time = timeit.default_timer() delta_time = end_time - start_time total_time += delta_time class TestAdvancedInterfaces(unittest.TestCase): def test_array_objs(self): obj1, obj2 = Everything.test_array_fixed_out_objects() self.assertTrue(isinstance(obj1, Everything.TestObj)) self.assertTrue(isinstance(obj2, Everything.TestObj)) self.assertNotEqual(obj1, obj2) def test_obj_skip_return_val(self): obj = Everything.TestObj() ret = obj.skip_return_val(50, 42.0, 60, 2, 3) self.assertEqual(len(ret), 3) self.assertEqual(ret[0], 51) self.assertEqual(ret[1], 61) self.assertEqual(ret[2], 32) def test_obj_skip_return_val_no_out(self): obj = Everything.TestObj() # raises an error for 0, succeeds for any other value self.assertRaises(GLib.GError, obj.skip_return_val_no_out, 0) ret = obj.skip_return_val_no_out(1) self.assertEqual(ret, None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_fields.py0000664000000000000000000001224115074673150016367 0ustar00rootrootimport math import unittest from gi.repository import GLib from gi.repository import Regress from gi.repository import GIMarshallingTests class Number: def __init__(self, value): self.value = value def __int__(self): return int(self.value) def __float__(self): return float(self.value) class TestFields(unittest.TestCase): def test_int8(self): s = Regress.TestStructA() s.some_int8 = 21 self.assertEqual(s.some_int8, 21) s.some_int8 = b"\x42" self.assertEqual(s.some_int8, 0x42) self.assertRaises(TypeError, setattr, s, "some_int8", b"ab") self.assertRaises(TypeError, setattr, s, "some_int8", None) self.assertRaises(OverflowError, setattr, s, "some_int8", 128) self.assertRaises(OverflowError, setattr, s, "some_int8", -129) s.some_int8 = 3.6 self.assertEqual(s.some_int8, 3) s.some_int8 = Number(55) self.assertEqual(s.some_int8, 55) def test_int(self): s = Regress.TestStructA() s.some_int = GLib.MAXINT self.assertEqual(s.some_int, GLib.MAXINT) self.assertRaises(TypeError, setattr, s, "some_int", b"a") self.assertRaises(TypeError, setattr, s, "some_int", None) self.assertRaises(OverflowError, setattr, s, "some_int", GLib.MAXINT + 1) self.assertRaises(OverflowError, setattr, s, "some_int", GLib.MININT - 1) s.some_int = 3.6 self.assertEqual(s.some_int, 3) s.some_int = Number(GLib.MININT) self.assertEqual(s.some_int, GLib.MININT) def test_long(self): s = GIMarshallingTests.SimpleStruct() s.long_ = GLib.MAXLONG self.assertEqual(s.long_, GLib.MAXLONG) self.assertRaises(TypeError, setattr, s, "long_", b"a") self.assertRaises(TypeError, setattr, s, "long_", None) self.assertRaises(OverflowError, setattr, s, "long_", GLib.MAXLONG + 1) self.assertRaises(OverflowError, setattr, s, "long_", GLib.MINLONG - 1) s.long_ = 3.6 self.assertEqual(s.long_, 3) s.long_ = Number(GLib.MINLONG) self.assertEqual(s.long_, GLib.MINLONG) def test_double(self): s = Regress.TestStructA() s.some_double = GLib.MAXDOUBLE self.assertEqual(s.some_double, GLib.MAXDOUBLE) s.some_double = GLib.MINDOUBLE self.assertEqual(s.some_double, GLib.MINDOUBLE) s.some_double = float("nan") self.assertTrue(math.isnan(s.some_double)) self.assertRaises(TypeError, setattr, s, "some_double", b"a") self.assertRaises(TypeError, setattr, s, "some_double", None) def test_gtype(self): s = Regress.TestStructE() s.some_type = Regress.TestObj self.assertEqual(s.some_type, Regress.TestObj.__gtype__) self.assertRaises(TypeError, setattr, s, "some_type", 42) def test_unichar(self): # I can't find a unichar field.. pass def test_utf8(self): s = GIMarshallingTests.BoxedStruct() s.string_ = "hello" self.assertEqual(s.string_, "hello") s.string_ = "hello" self.assertEqual(s.string_, "hello") s.string_ = None self.assertEqual(s.string_, None) self.assertRaises(TypeError, setattr, s, "string_", 42) def test_array_of_structs(self): s = Regress.TestStructD() self.assertEqual(s.array1, []) self.assertEqual(s.array2, []) def test_interface(self): s = Regress.TestStructC() obj = Regress.TestObj() s.obj = obj self.assertTrue(s.obj is obj) s.obj = None self.assertTrue(s.obj is None) self.assertRaises(TypeError, setattr, s, "obj", object()) def test_glist(self): s = Regress.TestStructD() self.assertEqual(s.list, []) self.assertRaises(TypeError, setattr, s, "list", [object()]) def test_gpointer(self): glist = GLib.List() glist.data = 123 self.assertEqual(glist.data, 123) glist.data = None self.assertEqual(glist.data, 0) def test_gptrarray(self): s = Regress.TestStructD() self.assertEqual(s.garray, []) self.assertRaises(TypeError, setattr, s, "garray", [object()]) def test_enum(self): s = Regress.TestStructA() s.some_enum = Regress.TestEnum.VALUE3 self.assertEqual(s.some_enum, Regress.TestEnum.VALUE3) self.assertRaises(TypeError, setattr, s, "some_enum", object()) s.some_enum = 0 self.assertEqual(s.some_enum, Regress.TestEnum.VALUE1) def test_union(self): s = Regress.TestStructE() self.assertEqual(s.some_union, [None, None]) def test_struct(self): s = GIMarshallingTests.NestedStruct() # FIXME: segfaults # https://bugzilla.gnome.org/show_bug.cgi?id=747002 # s.simple_struct = None self.assertRaises(TypeError, setattr, s, "simple_struct", object()) sub = GIMarshallingTests.SimpleStruct() sub.long_ = 42 s.simple_struct = sub self.assertEqual(s.simple_struct.long_, 42) def test_ghashtable(self): obj = Regress.TestObj() self.assertTrue(obj.hash_table is None) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_fundamental.py0000664000000000000000000001141515074673150017421 0ustar00rootrootimport gc import weakref import pytest from gi.repository import GObject, Regress try: from gi.repository import Gtk GTK4 = Gtk._version == "4.0" except ImportError: Gtk = None GTK4 = False def test_constructor_no_data(): obj = Regress.TestFundamentalSubObject() assert isinstance(obj, Regress.TestFundamentalSubObject) assert isinstance(obj, Regress.TestFundamentalObject) assert obj.refcount == 1 assert obj.data is None def test_constructor_with_data(): with pytest.raises(TypeError): Regress.TestFundamentalSubObject(data="foo") def test_create_fundamental_new_with_data(): obj = Regress.TestFundamentalSubObject.new("foo") assert isinstance(obj, Regress.TestFundamentalSubObject) assert isinstance(obj, Regress.TestFundamentalObject) assert obj.refcount == 1 assert obj.data == "foo" @pytest.mark.skipif( not hasattr(Regress, "TestFundamentalObjectNoGetSetFunc"), reason="Old versions do not have this type", ) def test_change_field(): obj = Regress.TestFundamentalObjectNoGetSetFunc.new("foo") obj.data = "bar" assert obj.get_data() == "bar" @pytest.mark.skipif( not hasattr(Regress, "TestFundamentalObjectNoGetSetFunc"), reason="Old versions do not have this type", ) def test_call_method(): obj = Regress.TestFundamentalObjectNoGetSetFunc.new("foo") assert obj.get_data() == "foo" def test_create_fundamental_hidden_class_instance(): obj = Regress.test_create_fundamental_hidden_class_instance() assert isinstance(obj, Regress.TestFundamentalObject) def test_create_fundamental_refcount(): obj = Regress.TestFundamentalSubObject.new("foo") assert obj.refcount == 1 def test_delete_fundamental_refcount(): obj = Regress.TestFundamentalSubObject.new("foo") del obj gc.collect() def test_value_set_fundamental_object(): val = GObject.Value(Regress.TestFundamentalSubObject.__gtype__) obj = Regress.TestFundamentalSubObject() val.set_value(obj) assert val.get_value() == obj def test_value_set_wrong_value(): val = GObject.Value(Regress.TestFundamentalSubObject.__gtype__) with pytest.raises(TypeError, match="Fundamental type is required"): val.set_value(1) def test_value_set_wrong_fundamental(): val = GObject.Value(Regress.TestFundamentalSubObject.__gtype__) with pytest.raises(TypeError, match="Invalid fundamental type for assignment"): val.set_value(MyCustomFundamentalObject()) def test_array_of_fundamental_objects_in(): assert Regress.test_array_of_fundamental_objects_in( [Regress.TestFundamentalSubObject()] ) def test_array_of_fundamental_objects_out(): objs = Regress.test_array_of_fundamental_objects_out() assert len(objs) == 2 assert all(isinstance(o, Regress.TestFundamentalObject) for o in objs) def test_fundamental_argument_in(): obj = Regress.TestFundamentalSubObject() assert Regress.test_fundamental_argument_in(obj) def test_abstract_fundamental_type(): with pytest.raises(TypeError): Regress.TestFundamentalObject() def test_fundamental_argument_out(): obj = Regress.TestFundamentalSubObject.new("data") other = Regress.test_fundamental_argument_out(obj) assert type(obj) is type(other) assert obj is not other assert obj.data == other.data def test_multiple_objects(): obj1 = Regress.TestFundamentalSubObject() obj2 = Regress.TestFundamentalSubObject() assert obj1 != obj2 def test_fundamental_weak_ref(): obj = Regress.TestFundamentalSubObject() weak = weakref.ref(obj) assert weak() == obj del obj gc.collect() assert weak() is None def test_fundamental_primitive_object(): bitmask = Regress.Bitmask(2) assert bitmask.v == 2 def test_custom_fundamental_type_vfunc_override(capsys): obj = MyCustomFundamentalObject() del obj gc.collect() out = capsys.readouterr().out assert "MyCustomFundamentalObject.__init__" in out assert "MyCustomFundamentalObject.do_finalize" in out @pytest.mark.skipif(not GTK4, reason="requires GTK 4") def test_gtk_expression(): obj = object() con = Gtk.ConstantExpression.new_for_value(obj) assert con.get_value() is obj @pytest.mark.skipif(not GTK4, reason="requires GTK 4") def test_gtk_string_filter_fundamental_property(): expr = Gtk.ConstantExpression.new_for_value("one") filter = Gtk.StringFilter.new(expr) filter.props.expression = expr assert filter.get_expression() == expr assert filter.props.expression == expr class MyCustomFundamentalObject(Regress.TestFundamentalObject): def __init__(self): print("MyCustomFundamentalObject.__init__") # noqa T20 super().__init__() def do_finalize(self): print("MyCustomFundamentalObject.do_finalize") # noqa T20 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_gdbus.py0000664000000000000000000003470715074673150016240 0ustar00rootrootimport asyncio import unittest import pytest from gi.events import GLibEventLoopPolicy from gi.repository import GLib from gi.repository import Gio try: Gio.bus_get_sync(Gio.BusType.SESSION, None) except GLib.Error: has_dbus = False else: has_dbus = True class TestDBusNodeInfo(unittest.TestCase): def test_new_for_xml(self): info = Gio.DBusNodeInfo.new_for_xml(""" """) interfaces = info.interfaces del info assert len(interfaces) == 1 assert interfaces[0].name == "org.freedesktop.DBus.Introspectable" methods = interfaces[0].methods del interfaces assert len(methods) == 1 assert methods[0].name == "Introspect" out_args = methods[0].out_args assert len(out_args) del methods assert out_args[0].name == "data" @unittest.skipUnless(has_dbus, "no dbus running") class TestGDBusClient(unittest.TestCase): def setUp(self): self.bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) self.dbus_proxy = Gio.DBusProxy.new_sync( self.bus, Gio.DBusProxyFlags.NONE, None, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", None, ) def test_native_calls_sync(self): result = self.dbus_proxy.call_sync( "ListNames", None, Gio.DBusCallFlags.NO_AUTO_START, 500, None ) self.assertTrue(isinstance(result, GLib.Variant)) result = result.unpack()[0] # result is always a tuple self.assertTrue(len(result) > 1) self.assertTrue("org.freedesktop.DBus" in result) result = self.dbus_proxy.call_sync( "GetNameOwner", GLib.Variant("(s)", ("org.freedesktop.DBus",)), Gio.DBusCallFlags.NO_AUTO_START, 500, None, ) self.assertTrue(isinstance(result, GLib.Variant)) self.assertEqual(type(result.unpack()[0]), str) def test_native_calls_sync_errors(self): # error case: invalid argument types try: self.dbus_proxy.call_sync( "GetConnectionUnixProcessID", None, Gio.DBusCallFlags.NO_AUTO_START, 500, None, ) self.fail("call with invalid arguments should raise an exception") except Exception as e: self.assertTrue("InvalidArgs" in str(e)) # error case: invalid argument try: self.dbus_proxy.call_sync( "GetConnectionUnixProcessID", GLib.Variant("(s)", (" unknown",)), Gio.DBusCallFlags.NO_AUTO_START, 500, None, ) self.fail("call with invalid arguments should raise an exception") except Exception as e: self.assertTrue("NameHasNoOwner" in str(e)) # error case: unknown method try: self.dbus_proxy.call_sync( "UnknownMethod", None, Gio.DBusCallFlags.NO_AUTO_START, 500, None ) self.fail("call for unknown method should raise an exception") except Exception as e: self.assertTrue("UnknownMethod" in str(e)) def test_native_calls_async(self): def call_done(obj, result, user_data): try: user_data["result"] = obj.call_finish(result) finally: user_data["main_loop"].quit() main_loop = GLib.MainLoop() data = {"main_loop": main_loop} self.dbus_proxy.call( "ListNames", None, Gio.DBusCallFlags.NO_AUTO_START, 500, None, call_done, data, ) main_loop.run() self.assertTrue(isinstance(data["result"], GLib.Variant)) result = data["result"].unpack()[0] # result is always a tuple self.assertTrue(len(result) > 1) self.assertTrue("org.freedesktop.DBus" in result) def test_native_calls_async_errors(self): def call_done(obj, result, user_data): try: obj.call_finish(result) self.fail("call_finish() for unknown method should raise an exception") except Exception as e: self.assertTrue("UnknownMethod" in str(e)) finally: user_data["main_loop"].quit() main_loop = GLib.MainLoop() data = {"main_loop": main_loop} self.dbus_proxy.call( "UnknownMethod", None, Gio.DBusCallFlags.NO_AUTO_START, 500, None, call_done, data, ) main_loop.run() def test_python_calls_sync(self): # single value return tuples get unboxed to the one element result = self.dbus_proxy.ListNames("()") self.assertTrue(isinstance(result, list)) self.assertTrue(len(result) > 1) self.assertTrue("org.freedesktop.DBus" in result) result = self.dbus_proxy.GetNameOwner("(s)", "org.freedesktop.DBus") self.assertEqual(type(result), str) # empty return tuples get unboxed to None self.assertEqual(self.dbus_proxy.ReloadConfig("()"), None) # multiple return values remain a tuple; unfortunately D-BUS itself # does not have any method returning multiple results, so try talking # to notification-daemon (and don't fail the test if it does not exist) try: nd = Gio.DBusProxy.new_sync( self.bus, Gio.DBusProxyFlags.NONE, None, "org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", None, ) result = nd.GetServerInformation("()") self.assertTrue(isinstance(result, tuple)) self.assertEqual(len(result), 4) for i in result: self.assertEqual(type(i), str) except Exception as e: if "Error.ServiceUnknown" not in str(e): raise # test keyword argument; timeout=0 will fail immediately try: self.dbus_proxy.GetConnectionUnixProcessID("(s)", "1", timeout=0) self.fail("call with timeout=0 should raise an exception") except Exception as e: # FIXME: this is not very precise, but in some environments we # do not always get an actual timeout self.assertTrue(isinstance(e, GLib.GError), str(e)) def test_python_calls_sync_noargs(self): # methods without arguments don't need an explicit signature result = self.dbus_proxy.ListNames() self.assertTrue(isinstance(result, list)) self.assertTrue(len(result) > 1) self.assertTrue("org.freedesktop.DBus" in result) def test_python_calls_sync_errors(self): # error case: invalid argument types try: self.dbus_proxy.GetConnectionUnixProcessID("()") self.fail("call with invalid arguments should raise an exception") except Exception as e: self.assertTrue("InvalidArgs" in str(e), str(e)) try: self.dbus_proxy.GetConnectionUnixProcessID(None, "foo") self.fail("call with None signature should raise an exception") except TypeError as e: self.assertTrue("signature" in str(e), str(e)) def test_python_calls_async(self): def call_done(obj, result, user_data): user_data["result"] = result user_data["main_loop"].quit() main_loop = GLib.MainLoop() data = {"main_loop": main_loop} self.dbus_proxy.ListNames("()", result_handler=call_done, user_data=data) main_loop.run() result = data["result"] self.assertEqual(type(result), type([])) self.assertTrue(len(result) > 1) self.assertTrue("org.freedesktop.DBus" in result) def test_python_calls_async_error_result(self): # when only specifying a result handler, this will get the error def call_done(obj, result, user_data): user_data["result"] = result user_data["main_loop"].quit() main_loop = GLib.MainLoop() data = {"main_loop": main_loop} self.dbus_proxy.ListNames( "(s)", "invalid_argument", result_handler=call_done, user_data=data ) main_loop.run() self.assertTrue(isinstance(data["result"], Exception)) self.assertTrue("InvalidArgs" in str(data["result"]), str(data["result"])) def test_python_calls_async_error(self): # when specifying an explicit error handler, this will get the error def call_done(obj, result, user_data): user_data["main_loop"].quit() self.fail("result handler should not be called") def call_error(obj, error, user_data): user_data["error"] = error user_data["main_loop"].quit() main_loop = GLib.MainLoop() data = {"main_loop": main_loop} self.dbus_proxy.ListNames( "(s)", "invalid_argument", result_handler=call_done, error_handler=call_error, user_data=data, ) main_loop.run() self.assertTrue(isinstance(data["error"], Exception)) self.assertTrue("InvalidArgs" in str(data["error"]), str(data["error"])) def test_instantiate_custom_proxy(self): class SomeProxy(Gio.DBusProxy): def __init__(self): Gio.DBusProxy.__init__(self) SomeProxy() class TestDBusConnection: @unittest.skipUnless(has_dbus, "no dbus running") def test_register_object(self): object_path = "/pygobject/Test" interface_xml = """ """ interface_info = Gio.DBusNodeInfo.new_for_xml(interface_xml).interfaces[0] bus = Gio.bus_get_sync(Gio.BusType.SESSION) for args in ( (object_path, interface_info), (object_path, interface_info, None, None, None), ): reg_id = bus.register_object(*args) bus.unregister_object(reg_id) for kwargs in ( {"object_path": object_path, "interface_info": interface_info}, { "object_path": object_path, "interface_info": interface_info, "method_call_closure": None, "get_property_closure": None, "set_property_closure": None, }, ): reg_id = bus.register_object(**kwargs) bus.unregister_object(reg_id) @unittest.skipUnless(has_dbus, "no dbus running") @pytest.mark.xfail() def test_connection_invocation_ref_count(self): """Invocation object should not leak a reference.""" invocation, errors = self.run_server(self.client_call) assert not errors assert invocation assert invocation.ref_count == 1 def run_server(self, client_callback): self.invocation = None self.errors = [] self.loop = GLib.MainLoop() def on_name_acquired(bus, name): client_callback(bus) self.reg_id = None bus = Gio.bus_get_sync(Gio.BusType.SESSION) owner_id = Gio.bus_own_name( Gio.BusType.SESSION, "org.pygobject.Test", Gio.BusNameOwnerFlags.NONE, self.on_bus_acquired, on_name_acquired, self.on_name_lost, ) try: self.loop.run() finally: Gio.bus_unown_name(owner_id) if self.reg_id: bus.unregister_object(self.reg_id) return (self.invocation, self.errors) def on_name_lost(self, _bus, name): self.errors.append(f"Name {name} lost") self.loop.quit() def on_bus_acquired(self, bus, name): interface_xml = """ """ self.reg_id = bus.register_object( "/pygobject/Test", Gio.DBusNodeInfo.new_for_xml(interface_xml).interfaces[0], self.on_incoming_method_call, None, None, ) def on_incoming_method_call( self, bus, sender, object_path, interface_name, method_name, parameters, invocation, ): invocation.return_value(GLib.Variant("()", ())) self.invocation = invocation def client_call(self, bus): def call_done(obj, result): try: obj.call_finish(result) finally: self.loop.quit() bus.call( "org.pygobject.Test", "/pygobject/Test", "org.pygobject.Test", "test", parameters=None, reply_type=None, flags=Gio.DBusCallFlags.NONE, timeout_msec=5000, callback=call_done, ) @unittest.skipUnless(has_dbus, "no dbus running") class AsyncDBusTests(unittest.TestCase): def setUp(self): policy = GLibEventLoopPolicy() asyncio.set_event_loop_policy(policy) self.addCleanup(asyncio.set_event_loop_policy, None) self.loop = policy.get_event_loop() self.addCleanup(self.loop.close) def test_async_bus_get(self): async def run(): bus = await Gio.bus_get(Gio.BusType.SESSION) self.assertIsInstance(bus, Gio.DBusConnection) self.loop.run_until_complete(run()) def test_async_proxy(self): async def run(): proxy = await Gio.DBusProxy.new_for_bus( Gio.BusType.SESSION, Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES, None, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", ) self.assertIsInstance(proxy, Gio.DBusProxy) self.loop.run_until_complete(run()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_gi.py0000664000000000000000000040034415074673150015525 0ustar00rootrootimport sys import unittest import tempfile import types import shutil import os import gc import weakref import warnings import pickle import platform import enum import gi import gi.overrides from gi import PyGIWarning from gi import PyGIDeprecationWarning from gi.repository import GObject, GLib, Gio from gi.repository import GIMarshallingTests import pytest from .helper import capture_exceptions, capture_output import contextlib CONSTANT_UTF8 = "const ♥ utf8" CONSTANT_UCS4 = "const ♥ utf8" class Number: def __init__(self, value): self.value = value def __int__(self): return int(self.value) def __float__(self): return float(self.value) class Sequence: def __init__(self, sequence): self.sequence = sequence def __len__(self): return len(self.sequence) def __getitem__(self, key): return self.sequence[key] class TestConstant(unittest.TestCase): def test_constant_utf8(self): self.assertEqual(CONSTANT_UTF8, GIMarshallingTests.CONSTANT_UTF8) def test_constant_number(self): self.assertEqual(42, GIMarshallingTests.CONSTANT_NUMBER) def test_min_max_int(self): self.assertEqual(GLib.MAXINT32, 2**31 - 1) self.assertEqual(GLib.MININT32, -(2**31)) self.assertEqual(GLib.MAXUINT32, 2**32 - 1) self.assertEqual(GLib.MAXINT64, 2**63 - 1) self.assertEqual(GLib.MININT64, -(2**63)) self.assertEqual(GLib.MAXUINT64, 2**64 - 1) class TestBoolean(unittest.TestCase): def test_boolean_return(self): self.assertEqual(True, GIMarshallingTests.boolean_return_true()) self.assertEqual(False, GIMarshallingTests.boolean_return_false()) def test_boolean_in(self): GIMarshallingTests.boolean_in_true(True) GIMarshallingTests.boolean_in_false(False) GIMarshallingTests.boolean_in_true(1) GIMarshallingTests.boolean_in_false(0) def test_boolean_in_other_types(self): GIMarshallingTests.boolean_in_true([""]) GIMarshallingTests.boolean_in_false([]) GIMarshallingTests.boolean_in_false(None) def test_boolean_out(self): self.assertEqual(True, GIMarshallingTests.boolean_out_true()) self.assertEqual(False, GIMarshallingTests.boolean_out_false()) def test_boolean_inout(self): self.assertEqual(False, GIMarshallingTests.boolean_inout_true_false(True)) self.assertEqual(True, GIMarshallingTests.boolean_inout_false_true(False)) class TestInt8(unittest.TestCase): MAX = GLib.MAXINT8 MIN = GLib.MININT8 def test_int8_return(self): self.assertEqual(self.MAX, GIMarshallingTests.int8_return_max()) self.assertEqual(self.MIN, GIMarshallingTests.int8_return_min()) def test_int8_in(self): max = Number(self.MAX) min = Number(self.MIN) GIMarshallingTests.int8_in_max(max) GIMarshallingTests.int8_in_min(min) max.value += 1 min.value -= 1 self.assertRaises(OverflowError, GIMarshallingTests.int8_in_max, max) self.assertRaises(OverflowError, GIMarshallingTests.int8_in_min, min) self.assertRaises(TypeError, GIMarshallingTests.int8_in_max, "self.MAX") def test_int8_out(self): self.assertEqual(self.MAX, GIMarshallingTests.int8_out_max()) self.assertEqual(self.MIN, GIMarshallingTests.int8_out_min()) def test_int8_inout(self): self.assertEqual( self.MIN, GIMarshallingTests.int8_inout_max_min(Number(self.MAX)) ) self.assertEqual( self.MAX, GIMarshallingTests.int8_inout_min_max(Number(self.MIN)) ) class TestUInt8(unittest.TestCase): MAX = GLib.MAXUINT8 def test_uint8_return(self): self.assertEqual(self.MAX, GIMarshallingTests.uint8_return()) def test_uint8_in(self): number = Number(self.MAX) GIMarshallingTests.uint8_in(number) GIMarshallingTests.uint8_in(b"\xff") number.value += 1 self.assertRaises(OverflowError, GIMarshallingTests.uint8_in, number) self.assertRaises(OverflowError, GIMarshallingTests.uint8_in, Number(-1)) self.assertRaises(TypeError, GIMarshallingTests.uint8_in, "self.MAX") def test_uint8_out(self): self.assertEqual(self.MAX, GIMarshallingTests.uint8_out()) def test_uint8_inout(self): self.assertEqual(0, GIMarshallingTests.uint8_inout(Number(self.MAX))) class TestInt16(unittest.TestCase): MAX = GLib.MAXINT16 MIN = GLib.MININT16 def test_int16_return(self): self.assertEqual(self.MAX, GIMarshallingTests.int16_return_max()) self.assertEqual(self.MIN, GIMarshallingTests.int16_return_min()) def test_int16_in(self): max = Number(self.MAX) min = Number(self.MIN) GIMarshallingTests.int16_in_max(max) GIMarshallingTests.int16_in_min(min) max.value += 1 min.value -= 1 self.assertRaises(OverflowError, GIMarshallingTests.int16_in_max, max) self.assertRaises(OverflowError, GIMarshallingTests.int16_in_min, min) self.assertRaises(TypeError, GIMarshallingTests.int16_in_max, "self.MAX") def test_int16_out(self): self.assertEqual(self.MAX, GIMarshallingTests.int16_out_max()) self.assertEqual(self.MIN, GIMarshallingTests.int16_out_min()) def test_int16_inout(self): self.assertEqual( self.MIN, GIMarshallingTests.int16_inout_max_min(Number(self.MAX)) ) self.assertEqual( self.MAX, GIMarshallingTests.int16_inout_min_max(Number(self.MIN)) ) class TestUInt16(unittest.TestCase): MAX = GLib.MAXUINT16 def test_uint16_return(self): self.assertEqual(self.MAX, GIMarshallingTests.uint16_return()) def test_uint16_in(self): number = Number(self.MAX) GIMarshallingTests.uint16_in(number) number.value += 1 self.assertRaises(OverflowError, GIMarshallingTests.uint16_in, number) self.assertRaises(OverflowError, GIMarshallingTests.uint16_in, Number(-1)) self.assertRaises(TypeError, GIMarshallingTests.uint16_in, "self.MAX") def test_uint16_out(self): self.assertEqual(self.MAX, GIMarshallingTests.uint16_out()) def test_uint16_inout(self): self.assertEqual(0, GIMarshallingTests.uint16_inout(Number(self.MAX))) class TestInt32(unittest.TestCase): MAX = GLib.MAXINT32 MIN = GLib.MININT32 def test_int32_return(self): self.assertEqual(self.MAX, GIMarshallingTests.int32_return_max()) self.assertEqual(self.MIN, GIMarshallingTests.int32_return_min()) def test_int32_in(self): max = Number(self.MAX) min = Number(self.MIN) GIMarshallingTests.int32_in_max(max) GIMarshallingTests.int32_in_min(min) max.value += 1 min.value -= 1 self.assertRaises(OverflowError, GIMarshallingTests.int32_in_max, max) self.assertRaises(OverflowError, GIMarshallingTests.int32_in_min, min) self.assertRaises(TypeError, GIMarshallingTests.int32_in_max, "self.MAX") def test_int32_out(self): self.assertEqual(self.MAX, GIMarshallingTests.int32_out_max()) self.assertEqual(self.MIN, GIMarshallingTests.int32_out_min()) def test_int32_inout(self): self.assertEqual( self.MIN, GIMarshallingTests.int32_inout_max_min(Number(self.MAX)) ) self.assertEqual( self.MAX, GIMarshallingTests.int32_inout_min_max(Number(self.MIN)) ) class TestUInt32(unittest.TestCase): MAX = GLib.MAXUINT32 def test_uint32_return(self): self.assertEqual(self.MAX, GIMarshallingTests.uint32_return()) def test_uint32_in(self): number = Number(self.MAX) GIMarshallingTests.uint32_in(number) number.value += 1 self.assertRaises(OverflowError, GIMarshallingTests.uint32_in, number) self.assertRaises(OverflowError, GIMarshallingTests.uint32_in, Number(-1)) self.assertRaises(TypeError, GIMarshallingTests.uint32_in, "self.MAX") def test_uint32_out(self): self.assertEqual(self.MAX, GIMarshallingTests.uint32_out()) def test_uint32_inout(self): self.assertEqual(0, GIMarshallingTests.uint32_inout(Number(self.MAX))) class TestInt64(unittest.TestCase): MAX = 2**63 - 1 MIN = -(2**63) def test_int64_return(self): self.assertEqual(self.MAX, GIMarshallingTests.int64_return_max()) self.assertEqual(self.MIN, GIMarshallingTests.int64_return_min()) def test_int64_in(self): max = Number(self.MAX) min = Number(self.MIN) GIMarshallingTests.int64_in_max(max) GIMarshallingTests.int64_in_min(min) max.value += 1 min.value -= 1 self.assertRaises(OverflowError, GIMarshallingTests.int64_in_max, max) self.assertRaises(OverflowError, GIMarshallingTests.int64_in_min, min) self.assertRaises(TypeError, GIMarshallingTests.int64_in_max, "self.MAX") def test_int64_out(self): self.assertEqual(self.MAX, GIMarshallingTests.int64_out_max()) self.assertEqual(self.MIN, GIMarshallingTests.int64_out_min()) def test_int64_inout(self): self.assertEqual( self.MIN, GIMarshallingTests.int64_inout_max_min(Number(self.MAX)) ) self.assertEqual( self.MAX, GIMarshallingTests.int64_inout_min_max(Number(self.MIN)) ) class TestUInt64(unittest.TestCase): MAX = 2**64 - 1 def test_uint64_return(self): self.assertEqual(self.MAX, GIMarshallingTests.uint64_return()) def test_uint64_in(self): number = Number(self.MAX) GIMarshallingTests.uint64_in(number) number.value += 1 self.assertRaises(OverflowError, GIMarshallingTests.uint64_in, number) self.assertRaises(OverflowError, GIMarshallingTests.uint64_in, Number(-1)) self.assertRaises(TypeError, GIMarshallingTests.uint64_in, "self.MAX") def test_uint64_out(self): self.assertEqual(self.MAX, GIMarshallingTests.uint64_out()) def test_uint64_inout(self): self.assertEqual(0, GIMarshallingTests.uint64_inout(Number(self.MAX))) class TestShort(unittest.TestCase): MAX = GLib.MAXSHORT MIN = GLib.MINSHORT def test_short_return(self): self.assertEqual(self.MAX, GIMarshallingTests.short_return_max()) self.assertEqual(self.MIN, GIMarshallingTests.short_return_min()) def test_short_in(self): max = Number(self.MAX) min = Number(self.MIN) GIMarshallingTests.short_in_max(max) GIMarshallingTests.short_in_min(min) max.value += 1 min.value -= 1 self.assertRaises(OverflowError, GIMarshallingTests.short_in_max, max) self.assertRaises(OverflowError, GIMarshallingTests.short_in_min, min) self.assertRaises(TypeError, GIMarshallingTests.short_in_max, "self.MAX") def test_short_out(self): self.assertEqual(self.MAX, GIMarshallingTests.short_out_max()) self.assertEqual(self.MIN, GIMarshallingTests.short_out_min()) def test_short_inout(self): self.assertEqual( self.MIN, GIMarshallingTests.short_inout_max_min(Number(self.MAX)) ) self.assertEqual( self.MAX, GIMarshallingTests.short_inout_min_max(Number(self.MIN)) ) class TestUShort(unittest.TestCase): MAX = GLib.MAXUSHORT def test_ushort_return(self): self.assertEqual(self.MAX, GIMarshallingTests.ushort_return()) def test_ushort_in(self): number = Number(self.MAX) GIMarshallingTests.ushort_in(number) number.value += 1 self.assertRaises(OverflowError, GIMarshallingTests.ushort_in, number) self.assertRaises(OverflowError, GIMarshallingTests.ushort_in, Number(-1)) self.assertRaises(TypeError, GIMarshallingTests.ushort_in, "self.MAX") def test_ushort_out(self): self.assertEqual(self.MAX, GIMarshallingTests.ushort_out()) def test_ushort_inout(self): self.assertEqual(0, GIMarshallingTests.ushort_inout(Number(self.MAX))) class TestInt(unittest.TestCase): MAX = GLib.MAXINT MIN = GLib.MININT def test_int_return(self): self.assertEqual(self.MAX, GIMarshallingTests.int_return_max()) self.assertEqual(self.MIN, GIMarshallingTests.int_return_min()) def test_int_in(self): max = Number(self.MAX) min = Number(self.MIN) GIMarshallingTests.int_in_max(max) GIMarshallingTests.int_in_min(min) max.value += 1 min.value -= 1 self.assertRaises(OverflowError, GIMarshallingTests.int_in_max, max) self.assertRaises(OverflowError, GIMarshallingTests.int_in_min, min) self.assertRaises(TypeError, GIMarshallingTests.int_in_max, "self.MAX") def test_int_out(self): self.assertEqual(self.MAX, GIMarshallingTests.int_out_max()) self.assertEqual(self.MIN, GIMarshallingTests.int_out_min()) def test_int_inout(self): self.assertEqual( self.MIN, GIMarshallingTests.int_inout_max_min(Number(self.MAX)) ) self.assertEqual( self.MAX, GIMarshallingTests.int_inout_min_max(Number(self.MIN)) ) self.assertRaises( TypeError, GIMarshallingTests.int_inout_min_max, Number(self.MIN), 42 ) class TestUInt(unittest.TestCase): MAX = GLib.MAXUINT def test_uint_return(self): self.assertEqual(self.MAX, GIMarshallingTests.uint_return()) def test_uint_in(self): number = Number(self.MAX) GIMarshallingTests.uint_in(number) number.value += 1 self.assertRaises(OverflowError, GIMarshallingTests.uint_in, number) self.assertRaises(OverflowError, GIMarshallingTests.uint_in, Number(-1)) self.assertRaises(TypeError, GIMarshallingTests.uint_in, "self.MAX") def test_uint_out(self): self.assertEqual(self.MAX, GIMarshallingTests.uint_out()) def test_uint_inout(self): self.assertEqual(0, GIMarshallingTests.uint_inout(Number(self.MAX))) class TestLong(unittest.TestCase): MAX = GLib.MAXLONG MIN = GLib.MINLONG def test_long_return(self): self.assertEqual(self.MAX, GIMarshallingTests.long_return_max()) self.assertEqual(self.MIN, GIMarshallingTests.long_return_min()) def test_long_in(self): max = Number(self.MAX) min = Number(self.MIN) GIMarshallingTests.long_in_max(max) GIMarshallingTests.long_in_min(min) max.value += 1 min.value -= 1 self.assertRaises(OverflowError, GIMarshallingTests.long_in_max, max) self.assertRaises(OverflowError, GIMarshallingTests.long_in_min, min) self.assertRaises(TypeError, GIMarshallingTests.long_in_max, "self.MAX") def test_long_out(self): self.assertEqual(self.MAX, GIMarshallingTests.long_out_max()) self.assertEqual(self.MIN, GIMarshallingTests.long_out_min()) def test_long_inout(self): self.assertEqual( self.MIN, GIMarshallingTests.long_inout_max_min(Number(self.MAX)) ) self.assertEqual( self.MAX, GIMarshallingTests.long_inout_min_max(Number(self.MIN)) ) class TestULong(unittest.TestCase): MAX = GLib.MAXULONG def test_ulong_return(self): self.assertEqual(self.MAX, GIMarshallingTests.ulong_return()) def test_ulong_in(self): number = Number(self.MAX) GIMarshallingTests.ulong_in(number) number.value += 1 self.assertRaises(OverflowError, GIMarshallingTests.ulong_in, number) self.assertRaises(OverflowError, GIMarshallingTests.ulong_in, Number(-1)) self.assertRaises(TypeError, GIMarshallingTests.ulong_in, "self.MAX") def test_ulong_out(self): self.assertEqual(self.MAX, GIMarshallingTests.ulong_out()) def test_ulong_inout(self): self.assertEqual(0, GIMarshallingTests.ulong_inout(Number(self.MAX))) class TestSSize(unittest.TestCase): MAX = GLib.MAXSSIZE MIN = GLib.MINSSIZE def test_ssize_return(self): self.assertEqual(self.MAX, GIMarshallingTests.ssize_return_max()) self.assertEqual(self.MIN, GIMarshallingTests.ssize_return_min()) def test_ssize_in(self): max = Number(self.MAX) min = Number(self.MIN) GIMarshallingTests.ssize_in_max(max) GIMarshallingTests.ssize_in_min(min) max.value += 1 min.value -= 1 self.assertRaises(OverflowError, GIMarshallingTests.ssize_in_max, max) self.assertRaises(OverflowError, GIMarshallingTests.ssize_in_min, min) self.assertRaises(TypeError, GIMarshallingTests.ssize_in_max, "self.MAX") def test_ssize_out(self): self.assertEqual(self.MAX, GIMarshallingTests.ssize_out_max()) self.assertEqual(self.MIN, GIMarshallingTests.ssize_out_min()) def test_ssize_inout(self): self.assertEqual( self.MIN, GIMarshallingTests.ssize_inout_max_min(Number(self.MAX)) ) self.assertEqual( self.MAX, GIMarshallingTests.ssize_inout_min_max(Number(self.MIN)) ) class TestSize(unittest.TestCase): MAX = GLib.MAXSIZE def test_size_return(self): self.assertEqual(self.MAX, GIMarshallingTests.size_return()) def test_size_in(self): number = Number(self.MAX) GIMarshallingTests.size_in(number) number.value += 1 self.assertRaises(OverflowError, GIMarshallingTests.size_in, number) self.assertRaises(OverflowError, GIMarshallingTests.size_in, Number(-1)) self.assertRaises(TypeError, GIMarshallingTests.size_in, "self.MAX") def test_size_out(self): self.assertEqual(self.MAX, GIMarshallingTests.size_out()) def test_size_inout(self): self.assertEqual(0, GIMarshallingTests.size_inout(Number(self.MAX))) class TestTimet(unittest.TestCase): def test_time_t_return(self): self.assertEqual(1234567890, GIMarshallingTests.time_t_return()) def test_time_t_in(self): GIMarshallingTests.time_t_in(1234567890) self.assertRaises(TypeError, GIMarshallingTests.time_t_in, "hello") def test_time_t_out(self): self.assertEqual(1234567890, GIMarshallingTests.time_t_out()) def test_time_t_inout(self): self.assertEqual(0, GIMarshallingTests.time_t_inout(1234567890)) class TestFloat(unittest.TestCase): MAX = GLib.MAXFLOAT MIN = GLib.MINFLOAT def test_float_return(self): self.assertAlmostEqual(self.MAX, GIMarshallingTests.float_return()) def test_float_in(self): GIMarshallingTests.float_in(Number(self.MAX)) self.assertRaises(TypeError, GIMarshallingTests.float_in, "self.MAX") def test_float_out(self): self.assertAlmostEqual(self.MAX, GIMarshallingTests.float_out()) def test_float_inout(self): self.assertAlmostEqual( self.MIN, GIMarshallingTests.float_inout(Number(self.MAX)) ) class TestDouble(unittest.TestCase): MAX = GLib.MAXDOUBLE MIN = GLib.MINDOUBLE def test_double_return(self): self.assertAlmostEqual(self.MAX, GIMarshallingTests.double_return()) def test_double_in(self): GIMarshallingTests.double_in(Number(self.MAX)) self.assertRaises(TypeError, GIMarshallingTests.double_in, "self.MAX") def test_double_out(self): self.assertAlmostEqual(self.MAX, GIMarshallingTests.double_out()) def test_double_inout(self): self.assertAlmostEqual( self.MIN, GIMarshallingTests.double_inout(Number(self.MAX)) ) class TestGType(unittest.TestCase): def test_gtype_name(self): self.assertEqual("void", GObject.TYPE_NONE.name) self.assertEqual("gchararray", GObject.TYPE_STRING.name) def check_readonly(gtype): gtype.name = "foo" errors = (AttributeError,) if platform.python_implementation() == "PyPy": # https://foss.heptapod.net/pypy/pypy/-/issues/2788 errors = (AttributeError, TypeError) self.assertRaises(errors, check_readonly, GObject.TYPE_NONE) self.assertRaises(errors, check_readonly, GObject.TYPE_STRING) def test_gtype_return(self): self.assertEqual(GObject.TYPE_NONE, GIMarshallingTests.gtype_return()) self.assertEqual(GObject.TYPE_STRING, GIMarshallingTests.gtype_string_return()) def test_gtype_in(self): GIMarshallingTests.gtype_in(GObject.TYPE_NONE) GIMarshallingTests.gtype_string_in(GObject.TYPE_STRING) self.assertRaises(TypeError, GIMarshallingTests.gtype_in, "foo") self.assertRaises(TypeError, GIMarshallingTests.gtype_string_in, "foo") def test_gtype_out(self): self.assertEqual(GObject.TYPE_NONE, GIMarshallingTests.gtype_out()) self.assertEqual(GObject.TYPE_STRING, GIMarshallingTests.gtype_string_out()) def test_gtype_inout(self): self.assertEqual( GObject.TYPE_INT, GIMarshallingTests.gtype_inout(GObject.TYPE_NONE) ) class TestUtf8(unittest.TestCase): def test_utf8_as_uint8array_in(self): data = CONSTANT_UTF8 if not isinstance(data, bytes): data = data.encode("utf-8") GIMarshallingTests.utf8_as_uint8array_in(data) def test_utf8_none_return(self): self.assertEqual(CONSTANT_UTF8, GIMarshallingTests.utf8_none_return()) def test_utf8_full_return(self): self.assertEqual(CONSTANT_UTF8, GIMarshallingTests.utf8_full_return()) def test_extra_utf8_full_return_invalid(self): with pytest.raises(UnicodeDecodeError): GIMarshallingTests.extra_utf8_full_return_invalid() def test_extra_utf8_full_out_invalid(self): with pytest.raises(UnicodeDecodeError): GIMarshallingTests.extra_utf8_full_out_invalid() def test_utf8_none_in(self): GIMarshallingTests.utf8_none_in(CONSTANT_UTF8) self.assertRaises(TypeError, GIMarshallingTests.utf8_none_in, 42) self.assertRaises(TypeError, GIMarshallingTests.utf8_none_in, None) def test_utf8_none_out(self): self.assertEqual(CONSTANT_UTF8, GIMarshallingTests.utf8_none_out()) def test_utf8_full_out(self): self.assertEqual(CONSTANT_UTF8, GIMarshallingTests.utf8_full_out()) def test_utf8_dangling_out(self): GIMarshallingTests.utf8_dangling_out() def test_utf8_none_inout(self): self.assertEqual("", GIMarshallingTests.utf8_none_inout(CONSTANT_UTF8)) def test_utf8_full_inout(self): self.assertEqual("", GIMarshallingTests.utf8_full_inout(CONSTANT_UTF8)) class TestFilename(unittest.TestCase): def setUp(self): self.workdir = tempfile.mkdtemp() def tearDown(self): shutil.rmtree(self.workdir) def tests_filename_list_return(self): assert GIMarshallingTests.filename_list_return() == [] @unittest.skipIf(os.name == "nt", "fixme") def test_filename_in(self): fname = os.path.join(self.workdir, "testäø.txt") try: os.path.exists(fname) except ValueError: # non-unicode fs encoding return self.assertRaises(GLib.GError, GLib.file_get_contents, fname) with open(fname.encode("UTF-8"), "wb") as f: f.write(b"hello world!\n\x01\x02") (result, contents) = GLib.file_get_contents(fname) self.assertEqual(result, True) self.assertEqual(contents, b"hello world!\n\x01\x02") def test_filename_in_nullable(self): self.assertTrue(GIMarshallingTests.filename_copy(None) is None) self.assertRaises(TypeError, GIMarshallingTests.filename_exists, None) @unittest.skipIf(os.name == "nt", "fixme") def test_filename_out(self): self.assertRaises(GLib.GError, GLib.Dir.make_tmp, "test") name = "testäø.XXXXXX" try: os.path.exists(name) except ValueError: # non-unicode fs encoding return dirname = GLib.Dir.make_tmp(name) self.assertTrue(os.path.sep + "testäø." in dirname, dirname) self.assertTrue(os.path.isdir(dirname)) os.rmdir(dirname) def test_wrong_types(self): self.assertRaises(TypeError, GIMarshallingTests.filename_copy, 23) self.assertRaises(TypeError, GIMarshallingTests.filename_copy, []) def test_null(self): self.assertTrue(GIMarshallingTests.filename_copy(None) is None) self.assertRaises(TypeError, GIMarshallingTests.filename_exists, None) def test_round_trip(self): self.assertEqual(GIMarshallingTests.filename_copy("foo"), "foo") self.assertEqual(GIMarshallingTests.filename_copy(b"foo"), "foo") def test_contains_null(self): self.assertRaises( (ValueError, TypeError), GIMarshallingTests.filename_copy, b"foo\x00" ) self.assertRaises( (ValueError, TypeError), GIMarshallingTests.filename_copy, "foo\x00" ) def test_win32_surrogates(self): if os.name != "nt": return copy = GIMarshallingTests.filename_copy glib_repr = GIMarshallingTests.filename_to_glib_repr self.assertEqual(copy("\ud83d"), "\ud83d") self.assertEqual(copy("\x61\udc00"), "\x61\udc00") self.assertEqual(copy("\ud800\udc01"), "\U00010001") self.assertEqual(copy("\ud83d\x20\udca9"), "\ud83d\x20\udca9") self.assertEqual(glib_repr("\ud83d"), b"\xed\xa0\xbd") self.assertEqual(glib_repr("\ud800\udc01"), b"\xf0\x90\x80\x81") self.assertEqual(glib_repr("\ud800\udbff"), b"\xed\xa0\x80\xed\xaf\xbf") self.assertEqual(glib_repr("\ud800\ue000"), b"\xed\xa0\x80\xee\x80\x80") self.assertEqual(glib_repr("\ud7ff\udc00"), b"\xed\x9f\xbf\xed\xb0\x80") self.assertEqual(glib_repr("\x61\udc00"), b"\x61\xed\xb0\x80") self.assertEqual(glib_repr("\udc00"), b"\xed\xb0\x80") def test_win32_bytes_py3(self): if os.name != "nt": return values = [ b"foo", b"\xff\xff", b"\xc3\xb6\xc3\xa4\xc3\xbc", b"\xed\xa0\xbd", b"\xf0\x90\x80\x81", ] for v in values: try: uni = v.decode(sys.getfilesystemencoding(), "surrogatepass") except UnicodeDecodeError: continue self.assertEqual(GIMarshallingTests.filename_copy(v), uni) def test_unix_various(self): if os.name == "nt": return copy = GIMarshallingTests.filename_copy glib_repr = GIMarshallingTests.filename_to_glib_repr try: os.fsdecode(b"\xff\xfe") except UnicodeDecodeError: self.assertRaises(UnicodeDecodeError, copy, b"\xff\xfe") else: str_path = copy(b"\xff\xfe") self.assertTrue(isinstance(str_path, str)) self.assertEqual(str_path, os.fsdecode(b"\xff\xfe")) self.assertEqual(copy(str_path), str_path) self.assertEqual(glib_repr(b"\xff\xfe"), b"\xff\xfe") self.assertEqual(glib_repr(str_path), b"\xff\xfe") # if getfilesystemencoding is ASCII, then we should fail like # os.fsencode try: byte_path = os.fsencode("ä") except UnicodeEncodeError: self.assertRaises(UnicodeEncodeError, copy, "ä") else: self.assertEqual(copy("ä"), "ä") self.assertEqual(glib_repr("ä"), byte_path) @unittest.skip("glib can't handle non-unicode paths") def test_win32_surrogates_exists(self): if os.name != "nt": return path = os.path.join(self.workdir, "\ud83d") with open(path, "wb"): self.assertTrue(os.path.exists(path)) self.assertTrue(GIMarshallingTests.filename_exists(path)) os.unlink(path) def test_path_exists_various_types(self): wd = self.workdir wdb = os.fsencode(wd) paths = [(wdb, b"foo-1"), (wd, "foo-2"), (wd, "öäü-3")] if sys.platform != "darwin": with contextlib.suppress(UnicodeDecodeError): # depends on the code page paths.append((wd, os.fsdecode(b"\xff\xfe-4"))) if os.name != "nt": paths.append((wdb, b"\xff\xfe-5")) def valid_path(p): try: os.path.exists(p) except ValueError: return False return True for d, path in paths: if not valid_path(path): continue path = os.path.join(d, path) with open(path, "wb"): self.assertTrue(GIMarshallingTests.filename_exists(path)) class TestArray(unittest.TestCase): @unittest.skipUnless(hasattr(GIMarshallingTests, "array_bool_in"), "too old gi") def test_array_bool_in(self): GIMarshallingTests.array_bool_in([True, False, True, True]) @unittest.skipUnless(hasattr(GIMarshallingTests, "array_bool_out"), "too old gi") def test_array_bool_out(self): assert GIMarshallingTests.array_bool_out() == [True, False, True, True] @unittest.skipUnless(hasattr(GIMarshallingTests, "array_int64_in"), "too old gi") def test_array_int64_in(self): GIMarshallingTests.array_int64_in([-1, 0, 1, 2]) @unittest.skipUnless(hasattr(GIMarshallingTests, "array_uint64_in"), "too old gi") def test_array_uint64_in(self): GIMarshallingTests.array_uint64_in([GLib.MAXUINT64, 0, 1, 2]) @unittest.skipUnless(hasattr(GIMarshallingTests, "array_unichar_in"), "too old gi") def test_array_unichar_in(self): GIMarshallingTests.array_unichar_in(list(CONSTANT_UCS4)) GIMarshallingTests.array_unichar_in(CONSTANT_UCS4) @unittest.skipUnless(hasattr(GIMarshallingTests, "array_unichar_out"), "too old gi") def test_array_unichar_out(self): result = list(CONSTANT_UCS4) assert GIMarshallingTests.array_unichar_out() == result def test_array_zero_terminated_return_unichar(self): assert GIMarshallingTests.array_zero_terminated_return_unichar() == list( CONSTANT_UCS4 ) def test_array_fixed_int_return(self): self.assertEqual([-1, 0, 1, 2], GIMarshallingTests.array_fixed_int_return()) def test_array_fixed_short_return(self): self.assertEqual([-1, 0, 1, 2], GIMarshallingTests.array_fixed_short_return()) def test_array_fixed_int_in(self): GIMarshallingTests.array_fixed_int_in(Sequence([-1, 0, 1, 2])) self.assertRaises( TypeError, GIMarshallingTests.array_fixed_int_in, Sequence([-1, "0", 1, 2]) ) self.assertRaises(TypeError, GIMarshallingTests.array_fixed_int_in, 42) self.assertRaises(TypeError, GIMarshallingTests.array_fixed_int_in, None) def test_array_fixed_short_in(self): GIMarshallingTests.array_fixed_short_in(Sequence([-1, 0, 1, 2])) def test_array_fixed_out(self): self.assertEqual([-1, 0, 1, 2], GIMarshallingTests.array_fixed_out()) def test_array_fixed_inout(self): self.assertEqual( [2, 1, 0, -1], GIMarshallingTests.array_fixed_inout([-1, 0, 1, 2]) ) def test_array_return(self): self.assertEqual([-1, 0, 1, 2], GIMarshallingTests.array_return()) def test_array_return_etc(self): self.assertEqual(([5, 0, 1, 9], 14), GIMarshallingTests.array_return_etc(5, 9)) def test_array_in(self): GIMarshallingTests.array_in(Sequence([-1, 0, 1, 2])) GIMarshallingTests.array_in_guint64_len(Sequence([-1, 0, 1, 2])) GIMarshallingTests.array_in_guint8_len(Sequence([-1, 0, 1, 2])) def test_array_in_len_before(self): GIMarshallingTests.array_in_len_before(Sequence([-1, 0, 1, 2])) def test_array_in_len_zero_terminated(self): GIMarshallingTests.array_in_len_zero_terminated(Sequence([-1, 0, 1, 2])) def test_array_uint8_in(self): GIMarshallingTests.array_uint8_in(Sequence([97, 98, 99, 100])) GIMarshallingTests.array_uint8_in(b"abcd") def test_array_string_in(self): GIMarshallingTests.array_string_in(["foo", "bar"]) def test_array_out(self): self.assertEqual([-1, 0, 1, 2], GIMarshallingTests.array_out()) def test_array_out_etc(self): self.assertEqual(([-5, 0, 1, 9], 4), GIMarshallingTests.array_out_etc(-5, 9)) def test_array_inout(self): self.assertEqual( [-2, -1, 0, 1, 2], GIMarshallingTests.array_inout(Sequence([-1, 0, 1, 2])) ) def test_array_inout_etc(self): self.assertEqual( ([-5, -1, 0, 1, 9], 4), GIMarshallingTests.array_inout_etc(-5, Sequence([-1, 0, 1, 2]), 9), ) def test_method_array_in(self): object_ = GIMarshallingTests.Object() object_.method_array_in(Sequence([-1, 0, 1, 2])) def test_method_array_out(self): object_ = GIMarshallingTests.Object() self.assertEqual([-1, 0, 1, 2], object_.method_array_out()) def test_method_array_inout(self): object_ = GIMarshallingTests.Object() self.assertEqual( [-2, -1, 0, 1, 2], object_.method_array_inout(Sequence([-1, 0, 1, 2])) ) def test_method_array_return(self): object_ = GIMarshallingTests.Object() self.assertEqual([-1, 0, 1, 2], object_.method_array_return()) def test_array_enum_in(self): GIMarshallingTests.array_enum_in( [ GIMarshallingTests.Enum.VALUE1, GIMarshallingTests.Enum.VALUE2, GIMarshallingTests.Enum.VALUE3, ] ) def test_array_boxed_struct_in(self): struct1 = GIMarshallingTests.BoxedStruct() struct1.long_ = 1 struct2 = GIMarshallingTests.BoxedStruct() struct2.long_ = 2 struct3 = GIMarshallingTests.BoxedStruct() struct3.long_ = 3 GIMarshallingTests.array_struct_in([struct1, struct2, struct3]) def test_array_boxed_struct_in_item_marshal_failure(self): struct1 = GIMarshallingTests.BoxedStruct() struct1.long_ = 1 struct2 = GIMarshallingTests.BoxedStruct() struct2.long_ = 2 self.assertRaises( TypeError, GIMarshallingTests.array_struct_in, [struct1, struct2, "not_a_struct"], ) def test_array_boxed_struct_value_in(self): struct1 = GIMarshallingTests.BoxedStruct() struct1.long_ = 1 struct2 = GIMarshallingTests.BoxedStruct() struct2.long_ = 2 struct3 = GIMarshallingTests.BoxedStruct() struct3.long_ = 3 GIMarshallingTests.array_struct_value_in([struct1, struct2, struct3]) def test_array_boxed_struct_value_in_item_marshal_failure(self): struct1 = GIMarshallingTests.BoxedStruct() struct1.long_ = 1 struct2 = GIMarshallingTests.BoxedStruct() struct2.long_ = 2 self.assertRaises( TypeError, GIMarshallingTests.array_struct_value_in, [struct1, struct2, "not_a_struct"], ) def test_array_boxed_struct_take_in(self): struct1 = GIMarshallingTests.BoxedStruct() struct1.long_ = 1 struct2 = GIMarshallingTests.BoxedStruct() struct2.long_ = 2 struct3 = GIMarshallingTests.BoxedStruct() struct3.long_ = 3 GIMarshallingTests.array_struct_take_in([struct1, struct2, struct3]) self.assertEqual(1, struct1.long_) def test_array_boxed_struct_return(self): (struct1, struct2, struct3) = ( GIMarshallingTests.array_zero_terminated_return_struct() ) self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct1)) self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct2)) self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct3)) self.assertEqual(42, struct1.long_) self.assertEqual(43, struct2.long_) self.assertEqual(44, struct3.long_) def test_array_simple_struct_in(self): struct1 = GIMarshallingTests.SimpleStruct() struct1.long_ = 1 struct2 = GIMarshallingTests.SimpleStruct() struct2.long_ = 2 struct3 = GIMarshallingTests.SimpleStruct() struct3.long_ = 3 GIMarshallingTests.array_simple_struct_in([struct1, struct2, struct3]) def test_array_simple_struct_in_item_marshal_failure(self): struct1 = GIMarshallingTests.SimpleStruct() struct1.long_ = 1 struct2 = GIMarshallingTests.SimpleStruct() struct2.long_ = 2 self.assertRaises( TypeError, GIMarshallingTests.array_simple_struct_in, [struct1, struct2, "not_a_struct"], ) def test_array_multi_array_key_value_in(self): GIMarshallingTests.multi_array_key_value_in(["one", "two", "three"], [1, 2, 3]) def test_array_in_nonzero_nonlen(self): GIMarshallingTests.array_in_nonzero_nonlen(1, b"abcd") def test_array_fixed_out_struct(self): struct1, struct2 = GIMarshallingTests.array_fixed_out_struct() self.assertEqual(7, struct1.long_) self.assertEqual(6, struct1.int8) self.assertEqual(6, struct2.long_) self.assertEqual(7, struct2.int8) def test_array_zero_terminated_return(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.array_zero_terminated_return() ) def test_array_zero_terminated_return_null(self): self.assertEqual([], GIMarshallingTests.array_zero_terminated_return_null()) def test_array_zero_terminated_in(self): GIMarshallingTests.array_zero_terminated_in(Sequence(["0", "1", "2"])) def test_array_zero_terminated_out(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.array_zero_terminated_out() ) def test_array_zero_terminated_inout(self): self.assertEqual( ["-1", "0", "1", "2"], GIMarshallingTests.array_zero_terminated_inout(["0", "1", "2"]), ) def test_init_function(self): self.assertEqual((True, []), GIMarshallingTests.init_function([])) self.assertEqual((True, []), GIMarshallingTests.init_function(["hello"])) self.assertEqual( (True, ["hello"]), GIMarshallingTests.init_function(["hello", "world"]) ) def test_enum_array_return_type(self): self.assertEqual( GIMarshallingTests.enum_array_return_type(), [ GIMarshallingTests.ExtraEnum.VALUE1, GIMarshallingTests.ExtraEnum.VALUE2, GIMarshallingTests.ExtraEnum.VALUE3, ], ) class TestLengthArray(unittest.TestCase): def test_length_array_utf8_none_inout(self): assert GIMarshallingTests.length_array_utf8_none_inout( ["🅰", "β", "c", "d"] ) == ["a", "b", "¢", "🔠"] def test_length_array_utf8_full_inout(self): assert GIMarshallingTests.length_array_utf8_full_inout( ["🅰", "β", "c", "d"] ) == ["a", "b", "¢", "🔠"] def test_length_array_utf8_optional_inout(self): assert GIMarshallingTests.length_array_utf8_optional_inout( ["🅰", "β", "c", "d"] ) == ["a", "b", "¢", "🔠"] def test_length_array_utf8_optional_inout_none_arg(self): assert GIMarshallingTests.length_array_utf8_optional_inout(None) == ["a", "b"] def test_length_array_utf8_optional_inout_no_arg(self): assert GIMarshallingTests.length_array_utf8_optional_inout() == ["a", "b"] class TestGStrv(unittest.TestCase): def test_gstrv_return(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.gstrv_return()) def test_gstrv_in(self): GIMarshallingTests.gstrv_in(Sequence(["0", "1", "2"])) def test_gstrv_out(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.gstrv_out()) def test_gstrv_inout(self): self.assertEqual( ["-1", "0", "1", "2"], GIMarshallingTests.gstrv_inout(["0", "1", "2"]) ) class TestArrayGVariant(unittest.TestCase): def test_array_gvariant_none_in(self): v = [GLib.Variant("i", 27), GLib.Variant("s", "Hello")] returned = [ GLib.Variant.unpack(r) for r in GIMarshallingTests.array_gvariant_none_in(v) ] self.assertEqual([27, "Hello"], returned) def test_array_gvariant_container_in(self): v = [GLib.Variant("i", 27), GLib.Variant("s", "Hello")] returned = [ GLib.Variant.unpack(r) for r in GIMarshallingTests.array_gvariant_container_in(v) ] self.assertEqual([27, "Hello"], returned) def test_array_gvariant_full_in(self): v = [GLib.Variant("i", 27), GLib.Variant("s", "Hello")] returned = [ GLib.Variant.unpack(r) for r in GIMarshallingTests.array_gvariant_full_in(v) ] self.assertEqual([27, "Hello"], returned) def test_bytearray_gvariant(self): v = GLib.Variant.new_bytestring(b"foo") self.assertEqual(v.get_bytestring(), b"foo") class TestGArray(unittest.TestCase): @unittest.skipUnless( hasattr(GIMarshallingTests, "garray_bool_none_in"), "too old gi" ) def test_garray_bool_none_in(self): GIMarshallingTests.garray_bool_none_in([True, False, True, True]) @unittest.skipUnless( hasattr(GIMarshallingTests, "garray_unichar_none_in"), "too old gi" ) def test_garray_unichar_none_in(self): GIMarshallingTests.garray_unichar_none_in(CONSTANT_UCS4) GIMarshallingTests.garray_unichar_none_in(list(CONSTANT_UCS4)) def test_garray_int_none_return(self): self.assertEqual([-1, 0, 1, 2], GIMarshallingTests.garray_int_none_return()) def test_garray_uint64_none_return(self): self.assertEqual( [0, GLib.MAXUINT64], GIMarshallingTests.garray_uint64_none_return() ) def test_garray_utf8_none_return(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.garray_utf8_none_return()) def test_garray_utf8_container_return(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.garray_utf8_container_return() ) def test_garray_utf8_full_return(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.garray_utf8_full_return()) def test_garray_int_none_in(self): GIMarshallingTests.garray_int_none_in(Sequence([-1, 0, 1, 2])) self.assertRaises( TypeError, GIMarshallingTests.garray_int_none_in, Sequence([-1, "0", 1, 2]) ) self.assertRaises(TypeError, GIMarshallingTests.garray_int_none_in, 42) self.assertRaises(TypeError, GIMarshallingTests.garray_int_none_in, None) def test_garray_uint64_none_in(self): GIMarshallingTests.garray_uint64_none_in(Sequence([0, GLib.MAXUINT64])) def test_garray_utf8_none_in(self): GIMarshallingTests.garray_utf8_none_in(Sequence(["0", "1", "2"])) def test_garray_utf8_none_out(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.garray_utf8_none_out()) def test_garray_utf8_container_out(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.garray_utf8_container_out() ) def test_garray_utf8_full_out(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.garray_utf8_full_out()) def test_garray_utf8_full_out_caller_allocated(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.garray_utf8_full_out_caller_allocated() ) def test_garray_utf8_none_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.garray_utf8_none_inout(Sequence(("0", "1", "2"))), ) def test_garray_utf8_container_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.garray_utf8_container_inout(["0", "1", "2"]), ) def test_garray_utf8_full_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.garray_utf8_full_inout(["0", "1", "2"]), ) class TestGPtrArray(unittest.TestCase): def test_gptrarray_utf8_none_return(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.gptrarray_utf8_none_return() ) def test_gptrarray_utf8_container_return(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.gptrarray_utf8_container_return() ) def test_gptrarray_utf8_full_return(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.gptrarray_utf8_full_return() ) def test_gptrarray_utf8_none_in(self): GIMarshallingTests.gptrarray_utf8_none_in(Sequence(["0", "1", "2"])) def test_gptrarray_utf8_none_out(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.gptrarray_utf8_none_out()) def test_gptrarray_utf8_container_out(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.gptrarray_utf8_container_out() ) def test_gptrarray_utf8_full_out(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.gptrarray_utf8_full_out()) def test_gptrarray_utf8_none_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.gptrarray_utf8_none_inout(Sequence(("0", "1", "2"))), ) def test_gptrarray_utf8_container_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.gptrarray_utf8_container_inout(["0", "1", "2"]), ) def test_gptrarray_utf8_full_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.gptrarray_utf8_full_inout(["0", "1", "2"]), ) class TestGBytes(unittest.TestCase): def test_gbytes_create(self): b = GLib.Bytes.new(b"\x00\x01\xff") self.assertEqual(3, b.get_size()) self.assertEqual(b"\x00\x01\xff", b.get_data()) def test_gbytes_create_take(self): b = GLib.Bytes.new_take(b"\x00\x01\xff") self.assertEqual(3, b.get_size()) self.assertEqual(b"\x00\x01\xff", b.get_data()) def test_gbytes_full_return(self): b = GIMarshallingTests.gbytes_full_return() self.assertEqual(4, b.get_size()) self.assertEqual(b"\x00\x31\xff\x33", b.get_data()) def test_gbytes_none_in(self): b = GIMarshallingTests.gbytes_full_return() GIMarshallingTests.gbytes_none_in(b) def test_compare(self): a1 = GLib.Bytes.new(b"\x00\x01\xff") a2 = GLib.Bytes.new(b"\x00\x01\xff") b = GLib.Bytes.new(b"\x00\x01\xfe") self.assertTrue(a1.equal(a2)) self.assertTrue(a2.equal(a1)) self.assertFalse(a1.equal(b)) self.assertFalse(b.equal(a2)) self.assertEqual(0, a1.compare(a2)) self.assertLess(0, a1.compare(b)) self.assertGreater(0, b.compare(a1)) class TestGByteArray(unittest.TestCase): def test_new(self): ba = GLib.ByteArray.new() self.assertEqual(b"", ba) ba = GLib.ByteArray.new_take(b"\x01\x02\xff") self.assertEqual(b"\x01\x02\xff", ba) def test_bytearray_full_return(self): self.assertEqual(b"\x001\xff3", GIMarshallingTests.bytearray_full_return()) def test_bytearray_none_in(self): b = b"\x00\x31\xff\x33" ba = GLib.ByteArray.new_take(b) # b should always have the same value even # though the generated GByteArray is being modified GIMarshallingTests.bytearray_none_in(b) GIMarshallingTests.bytearray_none_in(b) # The GByteArray is just a bytes # thus it will not reflect any changes GIMarshallingTests.bytearray_none_in(ba) GIMarshallingTests.bytearray_none_in(ba) class TestGList(unittest.TestCase): def test_glist_int_none_return(self): self.assertEqual([-1, 0, 1, 2], GIMarshallingTests.glist_int_none_return()) def test_glist_uint32_none_return(self): self.assertEqual( [0, GLib.MAXUINT32], GIMarshallingTests.glist_uint32_none_return() ) def test_glist_utf8_none_return(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.glist_utf8_none_return()) def test_glist_utf8_container_return(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.glist_utf8_container_return() ) def test_glist_utf8_full_return(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.glist_utf8_full_return()) def test_glist_int_none_in(self): GIMarshallingTests.glist_int_none_in(Sequence((-1, 0, 1, 2))) self.assertRaises( TypeError, GIMarshallingTests.glist_int_none_in, Sequence((-1, "0", 1, 2)) ) self.assertRaises(TypeError, GIMarshallingTests.glist_int_none_in, 42) self.assertRaises(TypeError, GIMarshallingTests.glist_int_none_in, None) def test_glist_int_none_in_error_getitem(self): class FailingSequence(Sequence): def __getitem__(self, key): raise Exception self.assertRaises( Exception, GIMarshallingTests.glist_int_none_in, FailingSequence((-1, 0, 1, 2)), ) def test_glist_uint32_none_in(self): GIMarshallingTests.glist_uint32_none_in(Sequence((0, GLib.MAXUINT32))) def test_glist_utf8_none_in(self): GIMarshallingTests.glist_utf8_none_in(Sequence(("0", "1", "2"))) def test_glist_utf8_none_out(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.glist_utf8_none_out()) def test_glist_utf8_container_out(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.glist_utf8_container_out()) def test_glist_utf8_full_out(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.glist_utf8_full_out()) def test_glist_utf8_none_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.glist_utf8_none_inout(Sequence(("0", "1", "2"))), ) def test_glist_utf8_container_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.glist_utf8_container_inout(("0", "1", "2")), ) def test_glist_utf8_full_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.glist_utf8_full_inout(("0", "1", "2")), ) class TestGSList(unittest.TestCase): def test_gslist_int_none_return(self): self.assertEqual([-1, 0, 1, 2], GIMarshallingTests.gslist_int_none_return()) def test_gslist_utf8_none_return(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.gslist_utf8_none_return()) def test_gslist_utf8_container_return(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.gslist_utf8_container_return() ) def test_gslist_utf8_full_return(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.gslist_utf8_full_return()) def test_gslist_int_none_in(self): GIMarshallingTests.gslist_int_none_in(Sequence((-1, 0, 1, 2))) self.assertRaises( TypeError, GIMarshallingTests.gslist_int_none_in, Sequence((-1, "0", 1, 2)) ) self.assertRaises(TypeError, GIMarshallingTests.gslist_int_none_in, 42) self.assertRaises(TypeError, GIMarshallingTests.gslist_int_none_in, None) def test_gslist_int_none_in_error_getitem(self): class FailingSequence(Sequence): def __getitem__(self, key): raise Exception self.assertRaises( Exception, GIMarshallingTests.gslist_int_none_in, FailingSequence((-1, 0, 1, 2)), ) def test_gslist_utf8_none_in(self): GIMarshallingTests.gslist_utf8_none_in(Sequence(("0", "1", "2"))) def test_gslist_utf8_none_out(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.gslist_utf8_none_out()) def test_gslist_utf8_container_out(self): self.assertEqual( ["0", "1", "2"], GIMarshallingTests.gslist_utf8_container_out() ) def test_gslist_utf8_full_out(self): self.assertEqual(["0", "1", "2"], GIMarshallingTests.gslist_utf8_full_out()) def test_gslist_utf8_none_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.gslist_utf8_none_inout(Sequence(("0", "1", "2"))), ) def test_gslist_utf8_container_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.gslist_utf8_container_inout(("0", "1", "2")), ) def test_gslist_utf8_full_inout(self): self.assertEqual( ["-2", "-1", "0", "1"], GIMarshallingTests.gslist_utf8_full_inout(("0", "1", "2")), ) class TestGHashTable(unittest.TestCase): @unittest.skip("broken") def test_ghashtable_double_in(self): GIMarshallingTests.ghashtable_double_in( {"-1": -0.1, "0": 0.0, "1": 0.1, "2": 0.2} ) @unittest.skip("broken") def test_ghashtable_float_in(self): GIMarshallingTests.ghashtable_float_in( {"-1": -0.1, "0": 0.0, "1": 0.1, "2": 0.2} ) @unittest.skip("broken") def test_ghashtable_int64_in(self): GIMarshallingTests.ghashtable_int64_in( {"-1": GLib.MAXUINT32 + 1, "0": 0, "1": 1, "2": 2} ) @unittest.skip("broken") def test_ghashtable_uint64_in(self): GIMarshallingTests.ghashtable_uint64_in( {"-1": GLib.MAXUINT32 + 1, "0": 0, "1": 1, "2": 2} ) def test_ghashtable_int_none_return(self): self.assertEqual( {-1: 1, 0: 0, 1: -1, 2: -2}, GIMarshallingTests.ghashtable_int_none_return() ) def test_ghashtable_int_none_return2(self): self.assertEqual( {"-1": "1", "0": "0", "1": "-1", "2": "-2"}, GIMarshallingTests.ghashtable_utf8_none_return(), ) def test_ghashtable_int_container_return(self): self.assertEqual( {"-1": "1", "0": "0", "1": "-1", "2": "-2"}, GIMarshallingTests.ghashtable_utf8_container_return(), ) def test_ghashtable_int_full_return(self): self.assertEqual( {"-1": "1", "0": "0", "1": "-1", "2": "-2"}, GIMarshallingTests.ghashtable_utf8_full_return(), ) def test_ghashtable_int_none_in(self): GIMarshallingTests.ghashtable_int_none_in({-1: 1, 0: 0, 1: -1, 2: -2}) self.assertRaises( TypeError, GIMarshallingTests.ghashtable_int_none_in, {-1: 1, "0": 0, 1: -1, 2: -2}, ) self.assertRaises( TypeError, GIMarshallingTests.ghashtable_int_none_in, {-1: 1, 0: "0", 1: -1, 2: -2}, ) self.assertRaises( TypeError, GIMarshallingTests.ghashtable_int_none_in, "{-1: 1, 0: 0, 1: -1, 2: -2}", ) self.assertRaises(TypeError, GIMarshallingTests.ghashtable_int_none_in, None) def test_ghashtable_utf8_none_in(self): GIMarshallingTests.ghashtable_utf8_none_in( {"-1": "1", "0": "0", "1": "-1", "2": "-2"} ) def test_ghashtable_utf8_none_out(self): self.assertEqual( {"-1": "1", "0": "0", "1": "-1", "2": "-2"}, GIMarshallingTests.ghashtable_utf8_none_out(), ) def test_ghashtable_utf8_container_out(self): self.assertEqual( {"-1": "1", "0": "0", "1": "-1", "2": "-2"}, GIMarshallingTests.ghashtable_utf8_container_out(), ) def test_ghashtable_utf8_full_out(self): self.assertEqual( {"-1": "1", "0": "0", "1": "-1", "2": "-2"}, GIMarshallingTests.ghashtable_utf8_full_out(), ) def test_ghashtable_utf8_none_inout(self): i = {"-1": "1", "0": "0", "1": "-1", "2": "-2"} self.assertEqual( {"-1": "1", "0": "0", "1": "1"}, GIMarshallingTests.ghashtable_utf8_none_inout(i), ) def test_ghashtable_utf8_container_inout(self): i = {"-1": "1", "0": "0", "1": "-1", "2": "-2"} self.assertEqual( {"-1": "1", "0": "0", "1": "1"}, GIMarshallingTests.ghashtable_utf8_container_inout(i), ) def test_ghashtable_utf8_full_inout(self): i = {"-1": "1", "0": "0", "1": "-1", "2": "-2"} self.assertEqual( {"-1": "1", "0": "0", "1": "1"}, GIMarshallingTests.ghashtable_utf8_full_inout(i), ) def test_ghashtable_enum_none_in(self): GIMarshallingTests.ghashtable_enum_none_in( { 1: GIMarshallingTests.ExtraEnum.VALUE1, 2: GIMarshallingTests.ExtraEnum.VALUE2, 3: GIMarshallingTests.ExtraEnum.VALUE3, } ) def test_ghashtable_enum_none_return(self): self.assertEqual( { 1: GIMarshallingTests.ExtraEnum.VALUE1, 2: GIMarshallingTests.ExtraEnum.VALUE2, 3: GIMarshallingTests.ExtraEnum.VALUE3, }, GIMarshallingTests.ghashtable_enum_none_return(), ) class TestGValue(unittest.TestCase): def test_gvalue_return(self): self.assertEqual(42, GIMarshallingTests.gvalue_return()) def test_gvalue_in(self): GIMarshallingTests.gvalue_in(42) value = GObject.Value(GObject.TYPE_INT, 42) GIMarshallingTests.gvalue_in(value) def test_gvalue_in_with_modification(self): value = GObject.Value(GObject.TYPE_INT, 42) GIMarshallingTests.gvalue_in_with_modification(value) self.assertEqual(value.get_int(), 24) def test_gvalue_int64_in(self): value = GObject.Value(GObject.TYPE_INT64, GLib.MAXINT64) GIMarshallingTests.gvalue_int64_in(value) def test_gvalue_in_with_type(self): value = GObject.Value(GObject.TYPE_STRING, "foo") GIMarshallingTests.gvalue_in_with_type(value, GObject.TYPE_STRING) value = GObject.Value( GIMarshallingTests.Flags.__gtype__, GIMarshallingTests.Flags.VALUE1 ) GIMarshallingTests.gvalue_in_with_type(value, GObject.TYPE_FLAGS) def test_gvalue_in_enum(self): # It is unclear what GIMarshallingTests expects here, since # GIMarshallingTests.Enum is an unregistered type. # https://gitlab.gnome.org/GNOME/gobject-introspection-tests/-/issues/8 value = GObject.Value( GIMarshallingTests.GEnum.__gtype__, GIMarshallingTests.GEnum.VALUE3 ) GIMarshallingTests.gvalue_in_enum(value) def test_gvalue_out(self): self.assertEqual(42, GIMarshallingTests.gvalue_out()) def test_gvalue_int64_out(self): self.assertEqual(GLib.MAXINT64, GIMarshallingTests.gvalue_int64_out()) def test_gvalue_out_caller_allocates(self): self.assertEqual(42, GIMarshallingTests.gvalue_out_caller_allocates()) def test_gvalue_inout(self): self.assertEqual("42", GIMarshallingTests.gvalue_inout(42)) value = GObject.Value(int, 42) self.assertEqual("42", GIMarshallingTests.gvalue_inout(value)) def test_gvalue_flat_array_in(self): # the function already asserts the correct values GIMarshallingTests.gvalue_flat_array([42, "42", True]) def test_gvalue_flat_array_in_item_marshal_failure(self): # Tests the failure to marshal 2^256 to a GValue mid-way through the array marshaling. self.assertRaises( OverflowError, GIMarshallingTests.gvalue_flat_array, [42, 2**256, True] ) self.assertRaises( OverflowError, GIMarshallingTests.gvalue_flat_array, [GLib.MAXINT + 1, "42", True], ) self.assertRaises( OverflowError, GIMarshallingTests.gvalue_flat_array, [GLib.MININT - 1, "42", True], ) # FIXME: https://gitlab.gnome.org/GNOME/pygobject/-/issues/582#note_1764164 exc_prefix = "Item 0: " if sys.version_info[:2] < (3, 12) else "" with pytest.raises( OverflowError, match=exc_prefix + f"{GLib.MAXINT + 1:d} not in range {GLib.MININT:d} to {GLib.MAXINT:d}", ): GIMarshallingTests.gvalue_flat_array([GLib.MAXINT + 1, "42", True]) min_, max_ = GLib.MININT, GLib.MAXINT with pytest.raises( OverflowError, match=exc_prefix + f"{GLib.MAXUINT64 * 2:d} not in range {min_:d} to {max_:d}", ): GIMarshallingTests.gvalue_flat_array([GLib.MAXUINT64 * 2, "42", True]) def test_gvalue_flat_array_out(self): values = GIMarshallingTests.return_gvalue_flat_array() self.assertEqual(values, [42, "42", True]) def test_gvalue_gobject_ref_counts_simple(self): obj = GObject.Object() grefcount = obj.__grefcount__ value = GObject.Value(GObject.TYPE_OBJECT, obj) del value gc.collect() gc.collect() assert obj.__grefcount__ == grefcount def test_gvalue_gobject_ref_counts(self): # Tests a GObject held by a GValue obj = GObject.Object() ref = weakref.ref(obj) grefcount = obj.__grefcount__ value = GObject.Value() value.init(GObject.TYPE_OBJECT) # TYPE_OBJECT will inc ref count as it should value.set_object(obj) self.assertEqual(obj.__grefcount__, grefcount + 1) # multiple set_object should not inc ref count value.set_object(obj) self.assertEqual(obj.__grefcount__, grefcount + 1) # get_object will re-use the same wrapper as obj res = value.get_object() self.assertEqual(obj, res) self.assertEqual(obj.__grefcount__, grefcount + 1) # multiple get_object should not inc ref count res = value.get_object() self.assertEqual(obj.__grefcount__, grefcount + 1) # deletion of the result and value holder should bring the # refcount back to where we started del res del value gc.collect() gc.collect() self.assertEqual(obj.__grefcount__, grefcount) del obj gc.collect() self.assertEqual(ref(), None) @unittest.skipUnless(hasattr(sys, "getrefcount"), "no sys.getrefcount") def test_gvalue_boxed_ref_counts(self): # Tests a boxed type wrapping a python object pointer (TYPE_PYOBJECT) # held by a GValue class Obj: pass obj = Obj() ref = weakref.ref(obj) refcount = sys.getrefcount(obj) value = GObject.Value() value.init(GObject.TYPE_PYOBJECT) # boxed TYPE_PYOBJECT will inc ref count as it should value.set_boxed(obj) self.assertEqual(sys.getrefcount(obj), refcount + 1) # multiple set_boxed should not inc ref count value.set_boxed(obj) self.assertEqual(sys.getrefcount(obj), refcount + 1) res = value.get_boxed() self.assertEqual(obj, res) self.assertEqual(sys.getrefcount(obj), refcount + 2) # multiple get_boxed should not inc ref count res = value.get_boxed() self.assertEqual(sys.getrefcount(obj), refcount + 2) # deletion of the result and value holder should bring the # refcount back to where we started del res del value gc.collect() self.assertEqual(sys.getrefcount(obj), refcount) del obj gc.collect() self.assertEqual(ref(), None) @unittest.skip("broken") def test_gvalue_flat_array_round_trip(self): self.assertEqual( [42, "42", True], GIMarshallingTests.gvalue_flat_array_round_trip(42, "42", True), ) def test_gvalue_float(self): GIMarshallingTests.gvalue_float(GObject.Float(3.14), 3.14) class TestGClosure(unittest.TestCase): def test_in(self): GIMarshallingTests.gclosure_in(lambda: 42) def test_in_partial(self): from functools import partial called_args = [] called_kwargs = {} def callback(*args, **kwargs): called_args.extend(args) called_kwargs.update(kwargs) return 42 func = partial(callback, 1, 2, 3, foo=42) GIMarshallingTests.gclosure_in(func) assert called_args == [1, 2, 3] assert called_kwargs["foo"] == 42 def test_pass(self): # test passing a closure between two C calls closure = GIMarshallingTests.gclosure_return() GIMarshallingTests.gclosure_in(closure) def test_type_error(self): self.assertRaises(TypeError, GIMarshallingTests.gclosure_in, 42) self.assertRaises(TypeError, GIMarshallingTests.gclosure_in, None) class TestCallbacks(unittest.TestCase): def test_return_value_only(self): def cb(): return 5 self.assertEqual(GIMarshallingTests.callback_return_value_only(cb), 5) def test_one_out_arg(self): def cb(): return 5.5 self.assertAlmostEqual(GIMarshallingTests.callback_one_out_parameter(cb), 5.5) def test_multiple_out_args(self): def cb(): return (5.5, 42.0) res = GIMarshallingTests.callback_multiple_out_parameters(cb) self.assertAlmostEqual(res[0], 5.5) self.assertAlmostEqual(res[1], 42.0) def test_return_and_one_out_arg(self): def cb(): return (5, 42.0) res = GIMarshallingTests.callback_return_value_and_one_out_parameter(cb) self.assertEqual(res[0], 5) self.assertAlmostEqual(res[1], 42.0) def test_return_and_multiple_out_arg(self): def cb(): return (5, 42, -1000) self.assertEqual( GIMarshallingTests.callback_return_value_and_multiple_out_parameters(cb), (5, 42, -1000), ) class TestPointer(unittest.TestCase): def test_pointer_in_return(self): self.assertEqual(GIMarshallingTests.pointer_in_return(42), 42) class TestEnum(unittest.TestCase): def test_enum(self): self.assertTrue(issubclass(GIMarshallingTests.Enum, int)) self.assertTrue( isinstance(GIMarshallingTests.Enum.VALUE1, GIMarshallingTests.Enum) ) self.assertTrue( isinstance(GIMarshallingTests.Enum.VALUE2, GIMarshallingTests.Enum) ) self.assertTrue( isinstance(GIMarshallingTests.Enum.VALUE3, GIMarshallingTests.Enum) ) self.assertEqual(42, GIMarshallingTests.Enum.VALUE3) def test_enum_in(self): GIMarshallingTests.enum_in(GIMarshallingTests.Enum.VALUE3) GIMarshallingTests.enum_in(42) self.assertRaises(TypeError, GIMarshallingTests.enum_in, 43) self.assertRaises( TypeError, GIMarshallingTests.enum_in, "GIMarshallingTests.Enum.VALUE3" ) def test_enum_return(self): enum = GIMarshallingTests.enum_returnv() self.assertTrue(isinstance(enum, GIMarshallingTests.Enum)) self.assertEqual(enum, GIMarshallingTests.Enum.VALUE3) def test_enum_out(self): enum = GIMarshallingTests.enum_out() self.assertTrue(isinstance(enum, GIMarshallingTests.Enum)) self.assertEqual(enum, GIMarshallingTests.Enum.VALUE3) def test_enum_inout(self): enum = GIMarshallingTests.enum_inout(GIMarshallingTests.Enum.VALUE3) self.assertTrue(isinstance(enum, GIMarshallingTests.Enum)) self.assertEqual(enum, GIMarshallingTests.Enum.VALUE1) def test_enum_second(self): # check for the bug where different non-gtype enums share the same class self.assertNotEqual(GIMarshallingTests.Enum, GIMarshallingTests.SecondEnum) # check that values are not being shared between different enums self.assertTrue(hasattr(GIMarshallingTests.SecondEnum, "SECONDVALUE1")) self.assertRaises( AttributeError, getattr, GIMarshallingTests.Enum, "SECONDVALUE1" ) self.assertTrue(hasattr(GIMarshallingTests.Enum, "VALUE1")) self.assertRaises( AttributeError, getattr, GIMarshallingTests.SecondEnum, "VALUE1" ) def test_enum_has_no_gtype(self): # GIMarshallingTests.Enum is not registered with the GType system self.assertFalse(hasattr(GIMarshallingTests.Enum, "__gtype__")) self.assertFalse(isinstance(GIMarshallingTests.Enum, GObject.GEnum)) def test_enum_add_type_error(self): with self.assertRaises(TypeError): gi._gi.enum_add( self, "Flags", GIMarshallingTests.Flags.__gtype__, GIMarshallingTests.Flags.__info__, ) def test_enum_add_module_type_error(self): with self.assertRaises(TypeError): gi._gi.flags_add( "self", "GEnum", GIMarshallingTests.GEnum.__gtype__, GIMarshallingTests.GEnum.__info__, ) def test_type_module_name(self): self.assertEqual(GIMarshallingTests.Enum.__name__, "Enum") self.assertEqual( GIMarshallingTests.Enum.__module__, "gi.repository.GIMarshallingTests" ) def test_hash(self): assert hash(GIMarshallingTests.Enum.VALUE1) == hash( GIMarshallingTests.Enum(GIMarshallingTests.Enum.VALUE1) ) def test_repr(self): self.assertEqual(repr(GIMarshallingTests.Enum.VALUE3), "") def test_enum_field_set(self): option = GLib.OptionEntry() # GLib.OptionEntry.arg is of type GLib.OptionArg, which is not # registered with the GObject type system by libglib. option.arg = GLib.OptionArg.NONE class TestEnumVFuncResults(unittest.TestCase): class EnumTester(GIMarshallingTests.Object): def do_vfunc_return_enum(self): return GIMarshallingTests.Enum.VALUE2 def do_vfunc_out_enum(self): return GIMarshallingTests.Enum.VALUE3 def test_vfunc_return_enum(self): tester = self.EnumTester() self.assertEqual(tester.vfunc_return_enum(), GIMarshallingTests.Enum.VALUE2) def test_vfunc_out_enum(self): tester = self.EnumTester() self.assertEqual(tester.vfunc_out_enum(), GIMarshallingTests.Enum.VALUE3) class TestGEnum(unittest.TestCase): def test_genum(self): self.assertTrue(issubclass(GIMarshallingTests.GEnum, GObject.GEnum)) self.assertTrue( isinstance(GIMarshallingTests.GEnum.VALUE1, GIMarshallingTests.GEnum) ) self.assertTrue( isinstance(GIMarshallingTests.GEnum.VALUE2, GIMarshallingTests.GEnum) ) self.assertTrue( isinstance(GIMarshallingTests.GEnum.VALUE3, GIMarshallingTests.GEnum) ) self.assertEqual(42, GIMarshallingTests.GEnum.VALUE3) def test_pickle(self): v = GIMarshallingTests.GEnum.VALUE3 new_v = pickle.loads(pickle.dumps(v)) assert new_v == v assert isinstance(new_v, GIMarshallingTests.GEnum) def test_value_nick_and_name(self): self.assertEqual(GIMarshallingTests.GEnum.VALUE1.value_nick, "value1") self.assertEqual(GIMarshallingTests.GEnum.VALUE2.value_nick, "value2") self.assertEqual(GIMarshallingTests.GEnum.VALUE3.value_nick, "value3") self.assertEqual( GIMarshallingTests.GEnum.VALUE1.value_name, "GI_MARSHALLING_TESTS_GENUM_VALUE1", ) self.assertEqual( GIMarshallingTests.GEnum.VALUE2.value_name, "GI_MARSHALLING_TESTS_GENUM_VALUE2", ) self.assertEqual( GIMarshallingTests.GEnum.VALUE3.value_name, "GI_MARSHALLING_TESTS_GENUM_VALUE3", ) def test_genum_in(self): GIMarshallingTests.genum_in(GIMarshallingTests.GEnum.VALUE3) GIMarshallingTests.genum_in(42) GIMarshallingTests.GEnum.in_(42) self.assertRaises(TypeError, GIMarshallingTests.genum_in, 43) self.assertRaises( TypeError, GIMarshallingTests.genum_in, "GIMarshallingTests.GEnum.VALUE3" ) def test_genum_return(self): genum = GIMarshallingTests.genum_returnv() self.assertTrue(isinstance(genum, GIMarshallingTests.GEnum)) self.assertEqual(genum, GIMarshallingTests.GEnum.VALUE3) def test_genum_out(self): genum = GIMarshallingTests.genum_out() genum = GIMarshallingTests.GEnum.out() self.assertTrue(isinstance(genum, GIMarshallingTests.GEnum)) self.assertEqual(genum, GIMarshallingTests.GEnum.VALUE3) def test_genum_inout(self): genum = GIMarshallingTests.genum_inout(GIMarshallingTests.GEnum.VALUE3) self.assertTrue(isinstance(genum, GIMarshallingTests.GEnum)) self.assertEqual(genum, GIMarshallingTests.GEnum.VALUE1) def test_type_module_name(self): self.assertEqual(GIMarshallingTests.GEnum.__name__, "GEnum") self.assertEqual( GIMarshallingTests.GEnum.__module__, "gi.repository.GIMarshallingTests" ) def test_enum_values_property(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", PyGIDeprecationWarning) assert GIMarshallingTests.GEnum.__enum_values__ == { 0: GIMarshallingTests.GEnum.VALUE1, 1: GIMarshallingTests.GEnum.VALUE2, 42: GIMarshallingTests.GEnum.VALUE3, } def test_hash(self): assert hash(GIMarshallingTests.GEnum.VALUE3) == hash( GIMarshallingTests.GEnum(GIMarshallingTests.GEnum.VALUE3) ) def test_repr(self): self.assertEqual(repr(GIMarshallingTests.GEnum.VALUE3), "") class TestGFlags(unittest.TestCase): def test_flags(self): self.assertTrue(issubclass(GIMarshallingTests.Flags, GObject.GFlags)) self.assertTrue( isinstance(GIMarshallingTests.Flags.VALUE1, GIMarshallingTests.Flags) ) self.assertTrue( isinstance(GIMarshallingTests.Flags.VALUE2, GIMarshallingTests.Flags) ) self.assertTrue( isinstance(GIMarshallingTests.Flags.VALUE3, GIMarshallingTests.Flags) ) # __or__() operation should still return an instance, not an int. self.assertTrue( isinstance( GIMarshallingTests.Flags.VALUE1 | GIMarshallingTests.Flags.VALUE2, GIMarshallingTests.Flags, ) ) self.assertEqual(1 << 1, GIMarshallingTests.Flags.VALUE2) def test_value_nick_and_name(self): self.assertEqual(GIMarshallingTests.Flags.VALUE1.first_value_nick, "value1") self.assertEqual(GIMarshallingTests.Flags.VALUE2.first_value_nick, "value2") self.assertEqual(GIMarshallingTests.Flags.VALUE3.first_value_nick, "value3") self.assertEqual( GIMarshallingTests.Flags.VALUE1.first_value_name, "GI_MARSHALLING_TESTS_FLAGS_VALUE1", ) self.assertEqual( GIMarshallingTests.Flags.VALUE2.first_value_name, "GI_MARSHALLING_TESTS_FLAGS_VALUE2", ) self.assertEqual( GIMarshallingTests.Flags.VALUE3.first_value_name, "GI_MARSHALLING_TESTS_FLAGS_VALUE3", ) def test_flags_in(self): GIMarshallingTests.flags_in(GIMarshallingTests.Flags.VALUE2) GIMarshallingTests.Flags.in_(GIMarshallingTests.Flags.VALUE2) # result of __or__() operation should still be valid instance, not an int. GIMarshallingTests.flags_in( GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE2 ) GIMarshallingTests.flags_in_zero(Number(0)) GIMarshallingTests.Flags.in_zero(Number(0)) self.assertRaises(TypeError, GIMarshallingTests.flags_in, 1 << 1) self.assertRaises( TypeError, GIMarshallingTests.flags_in, "GIMarshallingTests.Flags.VALUE2" ) def test_flags_return(self): flags = GIMarshallingTests.flags_returnv() self.assertTrue(isinstance(flags, GIMarshallingTests.Flags)) self.assertEqual(flags, GIMarshallingTests.Flags.VALUE2) def test_flags_return_method(self): flags = GIMarshallingTests.Flags.returnv() self.assertTrue(isinstance(flags, GIMarshallingTests.Flags)) self.assertEqual(flags, GIMarshallingTests.Flags.VALUE2) def test_flags_out(self): flags = GIMarshallingTests.flags_out() self.assertTrue(isinstance(flags, GIMarshallingTests.Flags)) self.assertEqual(flags, GIMarshallingTests.Flags.VALUE2) def test_flags_inout(self): flags = GIMarshallingTests.flags_inout(GIMarshallingTests.Flags.VALUE2) self.assertTrue(isinstance(flags, GIMarshallingTests.Flags)) self.assertEqual(flags, GIMarshallingTests.Flags.VALUE1) def test_type_module_name(self): self.assertEqual(GIMarshallingTests.Flags.__name__, "Flags") self.assertEqual( GIMarshallingTests.Flags.__module__, "gi.repository.GIMarshallingTests" ) def test_flags_values_property(self): flags_values = { 1: GIMarshallingTests.Flags.VALUE1, 2: GIMarshallingTests.Flags.VALUE2, 4: GIMarshallingTests.Flags.VALUE3, } # Since Python 3.11 only primary values are considered. # See https://docs.python.org/3/whatsnew/3.11.html#enum if sys.version_info[:2] < (3, 11): flags_values[3] = GIMarshallingTests.Flags.MASK with warnings.catch_warnings(): warnings.simplefilter("ignore", PyGIDeprecationWarning) assert GIMarshallingTests.Flags.__flags_values__ == flags_values def test_repr(self): self.assertEqual(repr(GIMarshallingTests.Flags.VALUE2), "") self.assertIn( repr(GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3), {"", ""}, ) def test_hash(self): assert hash(GIMarshallingTests.Flags.VALUE2) == hash( GIMarshallingTests.Flags(GIMarshallingTests.Flags.VALUE2) ) def test_flags_large_in(self): GIMarshallingTests.extra_flags_large_in(GIMarshallingTests.ExtraFlags.VALUE2) class TestNoTypeFlags(unittest.TestCase): def test_flags(self): self.assertTrue(issubclass(GIMarshallingTests.NoTypeFlags, enum.IntFlag)) self.assertTrue( isinstance( GIMarshallingTests.NoTypeFlags.VALUE1, GIMarshallingTests.NoTypeFlags ) ) self.assertTrue( isinstance( GIMarshallingTests.NoTypeFlags.VALUE2, GIMarshallingTests.NoTypeFlags ) ) self.assertTrue( isinstance( GIMarshallingTests.NoTypeFlags.VALUE3, GIMarshallingTests.NoTypeFlags ) ) # __or__() operation should still return an instance, not an int. self.assertTrue( isinstance( GIMarshallingTests.NoTypeFlags.VALUE1 | GIMarshallingTests.NoTypeFlags.VALUE2, GIMarshallingTests.NoTypeFlags, ) ) self.assertEqual(1 << 1, GIMarshallingTests.NoTypeFlags.VALUE2) def test_flags_in(self): GIMarshallingTests.no_type_flags_in(GIMarshallingTests.NoTypeFlags.VALUE2) GIMarshallingTests.no_type_flags_in( GIMarshallingTests.NoTypeFlags.VALUE2 | GIMarshallingTests.NoTypeFlags.VALUE2 ) GIMarshallingTests.no_type_flags_in_zero(Number(0)) self.assertRaises(TypeError, GIMarshallingTests.no_type_flags_in, 1 << 1) self.assertRaises( TypeError, GIMarshallingTests.no_type_flags_in, "GIMarshallingTests.NoTypeFlags.VALUE2", ) def test_flags_return(self): flags = GIMarshallingTests.no_type_flags_returnv() self.assertTrue(isinstance(flags, GIMarshallingTests.NoTypeFlags)) self.assertEqual(flags, GIMarshallingTests.NoTypeFlags.VALUE2) def test_flags_out(self): flags = GIMarshallingTests.no_type_flags_out() self.assertTrue(isinstance(flags, GIMarshallingTests.NoTypeFlags)) self.assertEqual(flags, GIMarshallingTests.NoTypeFlags.VALUE2) def test_flags_inout(self): flags = GIMarshallingTests.no_type_flags_inout( GIMarshallingTests.NoTypeFlags.VALUE2 ) self.assertTrue(isinstance(flags, GIMarshallingTests.NoTypeFlags)) self.assertEqual(flags, GIMarshallingTests.NoTypeFlags.VALUE1) def test_flags_has_no_gtype(self): self.assertFalse(hasattr(GIMarshallingTests.NoTypeFlags, "__gtype__")) self.assertFalse(issubclass(GIMarshallingTests.NoTypeFlags, GObject.GFlags)) def test_type_module_name(self): self.assertEqual(GIMarshallingTests.NoTypeFlags.__name__, "NoTypeFlags") self.assertEqual( GIMarshallingTests.NoTypeFlags.__module__, "gi.repository.GIMarshallingTests", ) def test_repr(self): self.assertEqual( repr(GIMarshallingTests.NoTypeFlags.VALUE2), "" ) def test_flags_add_module_type_error(self): with self.assertRaises(TypeError): gi._gi.flags_add( "self", "Flags", GIMarshallingTests.Flags.__gtype__, GIMarshallingTests.Flags.__info__, ) class TestStructure(unittest.TestCase): def test_simple_struct(self): self.assertTrue(issubclass(GIMarshallingTests.SimpleStruct, GObject.GPointer)) struct = GIMarshallingTests.SimpleStruct() self.assertTrue(isinstance(struct, GIMarshallingTests.SimpleStruct)) self.assertEqual(0, struct.long_) self.assertEqual(0, struct.int8) struct.long_ = 6 struct.int8 = 7 self.assertEqual(6, struct.long_) self.assertEqual(7, struct.int8) del struct def test_nested_struct(self): struct = GIMarshallingTests.NestedStruct() self.assertTrue( isinstance(struct.simple_struct, GIMarshallingTests.SimpleStruct) ) struct.simple_struct.long_ = 42 self.assertEqual(42, struct.simple_struct.long_) del struct def test_not_simple_struct(self): struct = GIMarshallingTests.NotSimpleStruct() self.assertEqual(None, struct.pointer) def test_simple_struct_return(self): struct = GIMarshallingTests.simple_struct_returnv() self.assertTrue(isinstance(struct, GIMarshallingTests.SimpleStruct)) self.assertEqual(6, struct.long_) self.assertEqual(7, struct.int8) del struct def test_simple_struct_in(self): struct = GIMarshallingTests.SimpleStruct() struct.long_ = 6 struct.int8 = 7 GIMarshallingTests.SimpleStruct.inv(struct) del struct struct = GIMarshallingTests.NestedStruct() self.assertRaises(TypeError, GIMarshallingTests.SimpleStruct.inv, struct) del struct self.assertRaises(TypeError, GIMarshallingTests.SimpleStruct.inv, None) def test_simple_struct_method(self): struct = GIMarshallingTests.SimpleStruct() struct.long_ = 6 struct.int8 = 7 struct.method() del struct self.assertRaises(TypeError, GIMarshallingTests.SimpleStruct.method) def test_pointer_struct(self): self.assertTrue(issubclass(GIMarshallingTests.PointerStruct, GObject.GPointer)) struct = GIMarshallingTests.PointerStruct() self.assertTrue(isinstance(struct, GIMarshallingTests.PointerStruct)) del struct def test_pointer_struct_return(self): struct = GIMarshallingTests.pointer_struct_returnv() self.assertTrue(isinstance(struct, GIMarshallingTests.PointerStruct)) self.assertEqual(42, struct.long_) del struct def test_pointer_struct_in(self): struct = GIMarshallingTests.PointerStruct() struct.long_ = 42 struct.inv() del struct def test_boxed_struct(self): self.assertTrue(issubclass(GIMarshallingTests.BoxedStruct, GObject.GBoxed)) struct = GIMarshallingTests.BoxedStruct() self.assertTrue(isinstance(struct, GIMarshallingTests.BoxedStruct)) self.assertEqual(0, struct.long_) self.assertEqual(None, struct.string_) self.assertEqual([], struct.g_strv) del struct def test_boxed_struct_new(self): struct = GIMarshallingTests.BoxedStruct.new() self.assertTrue(isinstance(struct, GIMarshallingTests.BoxedStruct)) self.assertEqual(struct.long_, 0) self.assertEqual(struct.string_, None) del struct def test_boxed_struct_copy(self): struct = GIMarshallingTests.BoxedStruct() struct.long_ = 42 struct.string_ = "hello" new_struct = struct.copy() self.assertTrue(isinstance(new_struct, GIMarshallingTests.BoxedStruct)) self.assertEqual(new_struct.long_, 42) self.assertEqual(new_struct.string_, "hello") del new_struct del struct def test_boxed_struct_return(self): struct = GIMarshallingTests.boxed_struct_returnv() self.assertTrue(isinstance(struct, GIMarshallingTests.BoxedStruct)) self.assertEqual(42, struct.long_) self.assertEqual("hello", struct.string_) self.assertEqual(["0", "1", "2"], struct.g_strv) del struct def test_boxed_struct_in(self): struct = GIMarshallingTests.BoxedStruct() struct.long_ = 42 struct.inv() del struct def test_boxed_struct_out(self): struct = GIMarshallingTests.boxed_struct_out() self.assertTrue(isinstance(struct, GIMarshallingTests.BoxedStruct)) self.assertEqual(42, struct.long_) del struct def test_boxed_struct_inout(self): in_struct = GIMarshallingTests.BoxedStruct() in_struct.long_ = 42 out_struct = GIMarshallingTests.boxed_struct_inout(in_struct) self.assertTrue(isinstance(out_struct, GIMarshallingTests.BoxedStruct)) self.assertEqual(0, out_struct.long_) del in_struct del out_struct def test_struct_field_assignment(self): struct = GIMarshallingTests.BoxedStruct() struct.long_ = 42 struct.string_ = "hello" self.assertEqual(struct.long_, 42) self.assertEqual(struct.string_, "hello") def test_union_init(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") GIMarshallingTests.Union(42) self.assertTrue(issubclass(warn[0].category, DeprecationWarning)) with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") GIMarshallingTests.Union(f=42) self.assertTrue(issubclass(warn[0].category, DeprecationWarning)) def test_union(self): union = GIMarshallingTests.Union() self.assertTrue(isinstance(union, GIMarshallingTests.Union)) new_union = union.copy() self.assertTrue(isinstance(new_union, GIMarshallingTests.Union)) del union del new_union def test_union_return(self): union = GIMarshallingTests.union_returnv() self.assertTrue(isinstance(union, GIMarshallingTests.Union)) self.assertEqual(42, union.long_) del union def test_union_in(self): union = GIMarshallingTests.Union() union.long_ = 42 union.inv() del union def test_union_method(self): union = GIMarshallingTests.Union() union.long_ = 42 union.method() del union self.assertRaises(TypeError, GIMarshallingTests.Union.method) def test_repr(self): self.assertRegex( repr(GIMarshallingTests.PointerStruct()), r"", ) self.assertRegex( repr(GIMarshallingTests.SimpleStruct()), r"", ) self.assertRegex( repr(GIMarshallingTests.Union()), r"", ) self.assertRegex( repr(GIMarshallingTests.BoxedStruct()), r"", ) class TestGObject(unittest.TestCase): def test_object(self): self.assertTrue(issubclass(GIMarshallingTests.Object, GObject.GObject)) object_ = GIMarshallingTests.Object() self.assertTrue(isinstance(object_, GIMarshallingTests.Object)) self.assertEqual(object_.__grefcount__, 1) def test_object_new(self): object_ = GIMarshallingTests.Object.new(42) self.assertTrue(isinstance(object_, GIMarshallingTests.Object)) self.assertEqual(object_.__grefcount__, 1) def test_object_int(self): object_ = GIMarshallingTests.Object(int=42) self.assertEqual(object_.int_, 42) # FIXME: Don't work yet. # object_.int_ = 0 # self.assertEqual(object_.int_, 0) def test_object_static_method(self): GIMarshallingTests.Object.static_method() def test_object_method(self): GIMarshallingTests.Object(int=42).method() self.assertRaises( TypeError, GIMarshallingTests.Object.method, GObject.GObject() ) self.assertRaises(TypeError, GIMarshallingTests.Object.method) def test_sub_object(self): self.assertTrue( issubclass(GIMarshallingTests.SubObject, GIMarshallingTests.Object) ) object_ = GIMarshallingTests.SubObject() self.assertTrue(isinstance(object_, GIMarshallingTests.SubObject)) def test_sub_object_new(self): self.assertRaises(TypeError, GIMarshallingTests.SubObject.new, 42) def test_sub_object_static_method(self): object_ = GIMarshallingTests.SubObject() object_.static_method() def test_sub_object_method(self): object_ = GIMarshallingTests.SubObject(int=42) object_.method() def test_sub_object_sub_method(self): object_ = GIMarshallingTests.SubObject() object_.sub_method() def test_sub_object_overwritten_method(self): object_ = GIMarshallingTests.SubObject() object_.overwritten_method() self.assertRaises( TypeError, GIMarshallingTests.SubObject.overwritten_method, GIMarshallingTests.Object(), ) def test_sub_object_int(self): object_ = GIMarshallingTests.SubObject() self.assertEqual(object_.int_, 0) # FIXME: Don't work yet. # object_.int_ = 42 # self.assertEqual(object_.int_, 42) def test_object_none_return(self): object_ = GIMarshallingTests.Object.none_return() self.assertTrue(isinstance(object_, GIMarshallingTests.Object)) self.assertEqual(object_.__grefcount__, 2) def test_object_full_return(self): object_ = GIMarshallingTests.Object.full_return() self.assertTrue(isinstance(object_, GIMarshallingTests.Object)) self.assertEqual(object_.__grefcount__, 1) def test_object_none_in(self): object_ = GIMarshallingTests.Object(int=42) GIMarshallingTests.Object.none_in(object_) self.assertEqual(object_.__grefcount__, 1) object_ = GIMarshallingTests.SubObject(int=42) GIMarshallingTests.Object.none_in(object_) object_ = GObject.GObject() self.assertRaises(TypeError, GIMarshallingTests.Object.none_in, object_) self.assertRaises(TypeError, GIMarshallingTests.Object.none_in, None) def test_object_none_out(self): object_ = GIMarshallingTests.Object.none_out() self.assertTrue(isinstance(object_, GIMarshallingTests.Object)) self.assertEqual(object_.__grefcount__, 2) new_object = GIMarshallingTests.Object.none_out() self.assertTrue(new_object is object_) def test_object_full_out(self): object_ = GIMarshallingTests.Object.full_out() self.assertTrue(isinstance(object_, GIMarshallingTests.Object)) self.assertEqual(object_.__grefcount__, 1) def test_object_none_inout(self): object_ = GIMarshallingTests.Object(int=42) new_object = GIMarshallingTests.Object.none_inout(object_) self.assertTrue(isinstance(new_object, GIMarshallingTests.Object)) self.assertFalse(object_ is new_object) self.assertEqual(object_.__grefcount__, 1) self.assertEqual(new_object.__grefcount__, 2) new_new_object = GIMarshallingTests.Object.none_inout(object_) self.assertTrue(new_new_object is new_object) GIMarshallingTests.Object.none_inout(GIMarshallingTests.SubObject(int=42)) def test_object_full_inout(self): # Using gimarshallingtests.c from GI versions > 1.38.0 will show this # test as an "unexpected success" due to reference leak fixes in that file. # TODO: remove the expectedFailure once PyGI relies on GI > 1.38.0. object_ = GIMarshallingTests.Object(int=42) new_object = GIMarshallingTests.Object.full_inout(object_) self.assertTrue(isinstance(new_object, GIMarshallingTests.Object)) self.assertFalse(object_ is new_object) self.assertEqual(object_.__grefcount__, 1) self.assertEqual(new_object.__grefcount__, 1) def test_repr(self): self.assertRegex( repr(GIMarshallingTests.Object(int=42)), r"", ) def test_nongir_repr(self): self.assertRegex( repr(Gio.File.new_for_path("/")), r"<__gi__.GLocalFile object at 0x[^\s]+ " r"\(GLocalFile at 0x[^\s]+\)>", ) def test_constructor_bad_cls_arg(self): # Get the unbound version of a constructor newv = GObject.GObject.newv.__func__ class Foo: pass with self.assertRaisesRegex(AttributeError, r"has no attribute '__name__'"): foo = Foo() newv(foo) with self.assertRaisesRegex(TypeError, r"attribute is not a string"): foo = Foo() foo.__name__ = 42 newv(foo) # FIXME: Doesn't actually return the same object. # def test_object_inout_same(self): # object_ = GIMarshallingTests.Object() # new_object = GIMarshallingTests.object_full_inout(object_) # self.assertTrue(object_ is new_object) # self.assertEqual(object_.__grefcount__, 1) class TestPythonGObject(unittest.TestCase): class Object(GIMarshallingTests.Object): return_for_caller_allocated_out_parameter = "test caller alloc return" def __init__(self, int): GIMarshallingTests.Object.__init__(self) self.val = None def method(self): # Don't call super, which asserts that self.int == 42. pass def do_method_int8_in(self, int8): self.val = int8 def do_method_int8_out(self): return 42 def do_method_int8_arg_and_out_caller(self, arg): return arg + 1 def do_method_int8_arg_and_out_callee(self, arg): return arg + 1 def do_method_str_arg_out_ret(self, arg): return (arg.upper(), len(arg)) def do_method_with_default_implementation(self, int8): GIMarshallingTests.Object.do_method_with_default_implementation(self, int8) self.props.int += int8 def do_vfunc_return_value_only(self): return 4242 def do_vfunc_one_out_parameter(self): return 42.42 def do_vfunc_multiple_out_parameters(self): return (42.42, 3.14) def do_vfunc_return_value_and_one_out_parameter(self): return (5, 42) def do_vfunc_return_value_and_multiple_out_parameters(self): return (5, 42, 99) def do_vfunc_caller_allocated_out_parameter(self): return self.return_for_caller_allocated_out_parameter class SubObject(GIMarshallingTests.SubObject): def __init__(self, int): GIMarshallingTests.SubObject.__init__(self) self.val = None def do_method_with_default_implementation(self, int8): self.val = int8 def do_vfunc_return_value_only(self): return 2121 class Interface3Impl(GObject.Object, GIMarshallingTests.Interface3): def __init__(self): GObject.Object.__init__(self) self.variants = None self.n_variants = None def do_test_variant_array_in(self, variants, n_variants): self.variants = variants self.n_variants = n_variants class ErrorObject(GIMarshallingTests.Object): def do_vfunc_return_value_only(self): raise ValueError("Return value should be 0") def test_object(self): self.assertTrue(issubclass(self.Object, GIMarshallingTests.Object)) object_ = self.Object(int=42) self.assertTrue(isinstance(object_, self.Object)) @unittest.skipUnless( hasattr(GIMarshallingTests.Object, "new_fail"), "Requires newer version of GI" ) def test_object_fail(self): with self.assertRaises(GLib.Error): GIMarshallingTests.Object.new_fail(int_=42) def test_object_method(self): self.Object(int=0).method() def test_object_vfuncs(self): object_ = self.Object(int=42) object_.method_int8_in(84) self.assertEqual(object_.val, 84) self.assertEqual(object_.method_int8_out(), 42) # can be dropped when bumping g-i dependencies to >= 1.35.2 if hasattr(object_, "method_int8_arg_and_out_caller"): self.assertEqual(object_.method_int8_arg_and_out_caller(42), 43) self.assertEqual(object_.method_int8_arg_and_out_callee(42), 43) self.assertEqual(object_.method_str_arg_out_ret("hello"), ("HELLO", 5)) object_.method_with_default_implementation(42) self.assertEqual(object_.props.int, 84) self.assertEqual(object_.vfunc_return_value_only(), 4242) self.assertAlmostEqual(object_.vfunc_one_out_parameter(), 42.42, places=5) (a, b) = object_.vfunc_multiple_out_parameters() self.assertAlmostEqual(a, 42.42, places=5) self.assertAlmostEqual(b, 3.14, places=5) self.assertEqual(object_.vfunc_return_value_and_one_out_parameter(), (5, 42)) self.assertEqual( object_.vfunc_return_value_and_multiple_out_parameters(), (5, 42, 99) ) self.assertEqual( object_.vfunc_caller_allocated_out_parameter(), object_.return_for_caller_allocated_out_parameter, ) class ObjectWithoutVFunc(GIMarshallingTests.Object): def __init__(self, int): GIMarshallingTests.Object.__init__(self) object_ = ObjectWithoutVFunc(int=42) object_.method_with_default_implementation(84) self.assertEqual(object_.props.int, 84) @unittest.skipUnless(hasattr(sys, "getrefcount"), "no sys.getrefcount") def test_vfunc_return_ref_count(self): obj = self.Object(int=42) ref_count = sys.getrefcount(obj.return_for_caller_allocated_out_parameter) ret = obj.vfunc_caller_allocated_out_parameter() gc.collect() # Make sure the return and what the vfunc returned # are equal but not the same object. self.assertEqual(ret, obj.return_for_caller_allocated_out_parameter) self.assertFalse(ret is obj.return_for_caller_allocated_out_parameter) self.assertEqual( sys.getrefcount(obj.return_for_caller_allocated_out_parameter), ref_count ) def test_vfunc_return_no_ref_count(self): obj = self.Object(int=42) ret = obj.vfunc_caller_allocated_out_parameter() self.assertEqual(ret, obj.return_for_caller_allocated_out_parameter) self.assertFalse(ret is obj.return_for_caller_allocated_out_parameter) def test_subobject_parent_vfunc(self): object_ = self.SubObject(int=81) object_.method_with_default_implementation(87) self.assertEqual(object_.val, 87) def test_subobject_child_vfunc(self): object_ = self.SubObject(int=1) self.assertEqual(object_.vfunc_return_value_only(), 2121) def test_subobject_non_vfunc_do_method(self): class PythonObjectWithNonVFuncDoMethod: def do_not_a_vfunc(self): return 5 class ObjectOverrideNonVFuncDoMethod( GIMarshallingTests.Object, PythonObjectWithNonVFuncDoMethod ): def do_not_a_vfunc(self): value = super().do_not_a_vfunc() return 13 + value object_ = ObjectOverrideNonVFuncDoMethod() self.assertEqual(18, object_.do_not_a_vfunc()) def test_native_function_not_set_in_subclass_dict(self): # Previously, GI was setting virtual functions on the class as well # as any *native* class that subclasses it. Here we check that it is only # set on the class that the method is originally from. self.assertTrue( "do_method_with_default_implementation" in GIMarshallingTests.Object.__dict__ ) self.assertTrue( "do_method_with_default_implementation" not in GIMarshallingTests.SubObject.__dict__ ) def test_subobject_with_interface_and_non_vfunc_do_method(self): # There was a bug for searching for vfuncs in interfaces. It was # triggered by having a do_* method that wasn't overriding # a native vfunc, as well as inheriting from an interface. class GObjectSubclassWithInterface( GObject.GObject, GIMarshallingTests.Interface ): def do_method_not_a_vfunc(self): pass def test_subsubobject(self): class SubSubSubObject(GIMarshallingTests.SubSubObject): def do_method_deep_hierarchy(self, num): self.props.int = num * 2 sub_sub_sub_object = SubSubSubObject() GIMarshallingTests.SubSubObject.do_method_deep_hierarchy(sub_sub_sub_object, 5) self.assertEqual(sub_sub_sub_object.props.int, 5) def test_interface3impl(self): iface3 = self.Interface3Impl() variants = [GLib.Variant("i", 27), GLib.Variant("s", "Hello")] iface3.test_variant_array_in(variants) self.assertEqual(iface3.n_variants, 2) self.assertEqual(iface3.variants[0].unpack(), 27) self.assertEqual(iface3.variants[1].unpack(), "Hello") def test_python_subsubobject_vfunc(self): class PySubObject(GIMarshallingTests.Object): def __init__(self): GIMarshallingTests.Object.__init__(self) self.sub_method_int8_called = 0 def do_method_int8_in(self, int8): self.sub_method_int8_called += 1 class PySubSubObject(PySubObject): def __init__(self): PySubObject.__init__(self) self.subsub_method_int8_called = 0 def do_method_int8_in(self, int8): self.subsub_method_int8_called += 1 so = PySubObject() so.method_int8_in(1) self.assertEqual(so.sub_method_int8_called, 1) # it should call the method on the SubSub object only sso = PySubSubObject() sso.method_int8_in(1) self.assertEqual(sso.subsub_method_int8_called, 1) self.assertEqual(sso.sub_method_int8_called, 0) def test_callback_in_vfunc(self): class SubObject(GIMarshallingTests.Object): def __init__(self): GObject.GObject.__init__(self) self.worked = False def do_vfunc_with_callback(self, callback): self.worked = callback(42) == 42 object_ = SubObject() object_.call_vfunc_with_callback() self.assertTrue(object_.worked) object_.worked = False object_.call_vfunc_with_callback() self.assertTrue(object_.worked) def test_exception_in_vfunc_return_value(self): obj = self.ErrorObject() with capture_exceptions() as exc: self.assertEqual(obj.vfunc_return_value_only(), 0) self.assertEqual(len(exc), 1) self.assertEqual(exc[0].type, ValueError) @unittest.skipUnless( hasattr(GIMarshallingTests, "callback_owned_boxed"), "requires newer version of GI", ) def test_callback_owned_box(self): def callback(box, data): self.box = box def nop_callback(box, data): pass GIMarshallingTests.callback_owned_boxed(callback, None) GIMarshallingTests.callback_owned_boxed(nop_callback, None) self.assertEqual(self.box.long_, 1) class TestMultiOutputArgs(unittest.TestCase): def test_int_out_out(self): self.assertEqual((6, 7), GIMarshallingTests.int_out_out()) def test_int_return_out(self): self.assertEqual((6, 7), GIMarshallingTests.int_return_out()) # Interface class TestInterfaces(unittest.TestCase): class TestInterfaceImpl(GObject.GObject, GIMarshallingTests.Interface): def __init__(self): GObject.GObject.__init__(self) self.val = None def do_test_int8_in(self, int8): self.val = int8 def setUp(self): self.instance = self.TestInterfaceImpl() def test_iface_impl(self): instance = GIMarshallingTests.InterfaceImpl() assert instance.get_as_interface() is instance instance.test_int8_in(42) def test_wrapper(self): self.assertTrue(issubclass(GIMarshallingTests.Interface, GObject.GInterface)) self.assertEqual( GIMarshallingTests.Interface.__gtype__.name, "GIMarshallingTestsInterface" ) self.assertRaises(NotImplementedError, GIMarshallingTests.Interface) def test_implementation(self): self.assertTrue( issubclass(self.TestInterfaceImpl, GIMarshallingTests.Interface) ) self.assertTrue(isinstance(self.instance, GIMarshallingTests.Interface)) def test_int8_int(self): GIMarshallingTests.test_interface_test_int8_in(self.instance, 42) self.assertEqual(self.instance.val, 42) def test_subclass(self): class TestInterfaceImplA(self.TestInterfaceImpl): pass class TestInterfaceImplB(TestInterfaceImplA): pass instance = TestInterfaceImplA() GIMarshallingTests.test_interface_test_int8_in(instance, 42) self.assertEqual(instance.val, 42) def test_subclass_override(self): class TestInterfaceImplD(TestInterfaces.TestInterfaceImpl): val2 = None def do_test_int8_in(self, int8): self.val2 = int8 instance = TestInterfaceImplD() self.assertEqual(instance.val, None) self.assertEqual(instance.val2, None) GIMarshallingTests.test_interface_test_int8_in(instance, 42) self.assertEqual(instance.val, None) self.assertEqual(instance.val2, 42) def test_type_mismatch(self): obj = GIMarshallingTests.Object() # wrong type for first argument: interface enum = Gio.File.new_for_path(".").enumerate_children( "", Gio.FileQueryInfoFlags.NONE, None ) try: enum.next_file(obj) self.fail("call with wrong type argument unexpectedly succeeded") except TypeError as e: # should have argument name self.assertTrue("cancellable" in str(e), e) # should have expected type self.assertTrue("xpected Gio.Cancellable" in str(e), e) # should have actual type self.assertTrue("GIMarshallingTests.Object" in str(e), e) # wrong type for self argument: interface try: Gio.FileEnumerator.next_file(obj, None) self.fail("call with wrong type argument unexpectedly succeeded") except TypeError as e: # should have argument name self.assertTrue("self" in str(e), e) # should have expected type self.assertTrue("xpected Gio.FileEnumerator" in str(e), e) # should have actual type self.assertTrue("GIMarshallingTests.Object" in str(e), e) # wrong type for first argument: GObject var = GLib.Variant("s", "mystring") action = Gio.SimpleAction.new("foo", var.get_type()) try: action.activate(obj) self.fail("call with wrong type argument unexpectedly succeeded") except TypeError as e: # should have argument name self.assertTrue("parameter" in str(e), e) # should have expected type self.assertTrue("xpected GLib.Variant" in str(e), e) # should have actual type self.assertTrue("GIMarshallingTests.Object" in str(e), e) # wrong type for self argument: GObject try: Gio.SimpleAction.activate(obj, obj) self.fail("call with wrong type argument unexpectedly succeeded") except TypeError as e: # should have argument name self.assertTrue("self" in str(e), e) # should have expected type self.assertTrue("xpected Gio.Action" in str(e), e) # should have actual type self.assertTrue("GIMarshallingTests.Object" in str(e), e) class TestMRO(unittest.TestCase): def test_mro(self): # check that our own MRO calculation matches what we would expect # from Python's own C3 calculations class A: pass class B(A): pass class C(A): pass class D(B, C): pass class E(D, GIMarshallingTests.Object): pass expected = ( E, D, B, C, A, GIMarshallingTests.Object, GObject.Object, GObject.Object.__base__, gi._gi.GObject, object, ) self.assertEqual(expected, E.__mro__) @unittest.skipIf( sys.implementation.name == "pypy", "PyPy 3.11 causes cycle among base classes" ) def test_interface_collision(self): # there was a problem with Python bailing out because of # http://en.wikipedia.org/wiki/Diamond_problem with interfaces, # which shouldn't really be a problem. class TestInterfaceImpl(GObject.GObject, GIMarshallingTests.Interface): pass class TestInterfaceImpl2(GIMarshallingTests.Interface, TestInterfaceImpl): pass class TestInterfaceImpl3(TestInterfaceImpl, GIMarshallingTests.Interface2): pass def test_old_style_mixin(self): # Note: Old style classes don't exist in Python 3 class Mixin: pass with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") # Dynamically create a new gi based class with an old # style mixin. type("GIWithOldStyleMixin", (GIMarshallingTests.Object, Mixin), {}) self.assertEqual(len(warn), 0) class TestInterfaceClash(unittest.TestCase): def test_clash(self): def create_clash(): class TestClash( GObject.GObject, GIMarshallingTests.Interface, GIMarshallingTests.Interface2, ): def do_test_int8_in(self, int8): pass TestClash() self.assertRaises(TypeError, create_clash) class TestOverrides(unittest.TestCase): def test_constant(self): self.assertEqual(GIMarshallingTests.OVERRIDES_CONSTANT, 7) def test_struct(self): # Test that the constructor has been overridden. struct = GIMarshallingTests.OverridesStruct(42) self.assertTrue(isinstance(struct, GIMarshallingTests.OverridesStruct)) # Test that the method has been overridden. self.assertEqual(6, struct.method()) del struct # Test that the overrides wrapper has been registered. struct = GIMarshallingTests.overrides_struct_returnv() self.assertTrue(isinstance(struct, GIMarshallingTests.OverridesStruct)) del struct def test_object(self): # Test that the constructor has been overridden. object_ = GIMarshallingTests.OverridesObject(42) self.assertTrue(isinstance(object_, GIMarshallingTests.OverridesObject)) # Test that the alternate constructor has been overridden. object_ = GIMarshallingTests.OverridesObject.new(42) self.assertTrue(isinstance(object_, GIMarshallingTests.OverridesObject)) # Test that the method has been overridden. self.assertEqual(6, object_.method()) # Test that the overrides wrapper has been registered. object_ = GIMarshallingTests.OverridesObject.returnv() self.assertTrue(isinstance(object_, GIMarshallingTests.OverridesObject)) def test_module_name(self): # overridden types self.assertEqual( GIMarshallingTests.OverridesStruct.__module__, "gi.overrides.GIMarshallingTests", ) self.assertEqual( GIMarshallingTests.OverridesObject.__module__, "gi.overrides.GIMarshallingTests", ) self.assertEqual(GObject.Object.__module__, "gi.overrides.GObject") # not overridden self.assertEqual( GIMarshallingTests.SubObject.__module__, "gi.repository.GIMarshallingTests" ) self.assertEqual(GObject.InitiallyUnowned.__module__, "gi.repository.GObject") class TestDir(unittest.TestCase): def test_members_list(self): list = dir(GIMarshallingTests) self.assertTrue("OverridesStruct" in list) self.assertTrue("BoxedStruct" in list) self.assertTrue("OVERRIDES_CONSTANT" in list) self.assertTrue("GEnum" in list) self.assertTrue("int32_return_max" in list) def test_modules_list(self): import gi.repository list = dir(gi.repository) self.assertTrue("GIMarshallingTests" in list) # FIXME: test to see if a module which was not imported is in the list # we should be listing every typelib we find, not just the ones # which are imported # # to test this I recommend we compile a fake module which # our tests would never import and check to see if it is # in the list: # # self.assertTrue('DoNotImportDummyTests' in list) class TestParamSpec(unittest.TestCase): def test_param_spec_in_bool(self): ps = GObject.param_spec_boolean( "mybool", "test-bool", "boolblurb", True, GObject.ParamFlags.READABLE ) GIMarshallingTests.param_spec_in_bool(ps) def test_param_spec_return(self): obj = GIMarshallingTests.param_spec_return() self.assertEqual(obj.name, "test-param") self.assertEqual(obj.nick, "test") self.assertEqual(obj.value_type, GObject.TYPE_STRING) def test_param_spec_out(self): obj = GIMarshallingTests.param_spec_out() self.assertEqual(obj.name, "test-param") self.assertEqual(obj.nick, "test") self.assertEqual(obj.value_type, GObject.TYPE_STRING) class TestKeywordArgs(unittest.TestCase): def test_calling(self): kw_func = GIMarshallingTests.int_three_in_three_out self.assertEqual(kw_func(1, 2, 3), (1, 2, 3)) self.assertEqual(kw_func(**{"a": 4, "b": 5, "c": 6}), (4, 5, 6)) self.assertEqual(kw_func(1, **{"b": 7, "c": 8}), (1, 7, 8)) self.assertEqual(kw_func(1, 7, **{"c": 8}), (1, 7, 8)) self.assertEqual(kw_func(1, c=8, **{"b": 7}), (1, 7, 8)) self.assertEqual(kw_func(2, c=4, b=3), (2, 3, 4)) self.assertEqual(kw_func(a=2, c=4, b=3), (2, 3, 4)) def assertRaisesMessage(self, exception, message, func, *args, **kwargs): try: func(*args, **kwargs) except exception: (_e_type, e) = sys.exc_info()[:2] if message is not None: self.assertEqual(str(e), message) except: raise else: msg = f"{func.__name__}() did not raise {exception.__name__}" raise AssertionError(msg) def test_type_errors(self): # test too few args self.assertRaisesMessage( TypeError, "GIMarshallingTests.int_three_in_three_out() takes exactly 3 arguments (0 given)", GIMarshallingTests.int_three_in_three_out, ) self.assertRaisesMessage( TypeError, "GIMarshallingTests.int_three_in_three_out() takes exactly 3 arguments (1 given)", GIMarshallingTests.int_three_in_three_out, 1, ) self.assertRaisesMessage( TypeError, "GIMarshallingTests.int_three_in_three_out() takes exactly 3 arguments (0 given)", GIMarshallingTests.int_three_in_three_out, *(), ) self.assertRaisesMessage( TypeError, "GIMarshallingTests.int_three_in_three_out() takes exactly 3 arguments (0 given)", GIMarshallingTests.int_three_in_three_out, *(), **{}, ) self.assertRaisesMessage( TypeError, "GIMarshallingTests.int_three_in_three_out() takes exactly 3 non-keyword arguments (0 given)", GIMarshallingTests.int_three_in_three_out, *(), **{"c": 4}, ) # test too many args self.assertRaisesMessage( TypeError, "GIMarshallingTests.int_three_in_three_out() takes exactly 3 arguments (4 given)", GIMarshallingTests.int_three_in_three_out, *(1, 2, 3, 4), ) self.assertRaisesMessage( TypeError, "GIMarshallingTests.int_three_in_three_out() takes exactly 3 non-keyword arguments (4 given)", GIMarshallingTests.int_three_in_three_out, *(1, 2, 3, 4), c=6, ) # test too many keyword args self.assertRaisesMessage( TypeError, "GIMarshallingTests.int_three_in_three_out() got multiple values for keyword argument 'a'", GIMarshallingTests.int_three_in_three_out, 1, 2, 3, **{"a": 4, "b": 5}, ) self.assertRaisesMessage( TypeError, "GIMarshallingTests.int_three_in_three_out() got an unexpected keyword argument 'd'", GIMarshallingTests.int_three_in_three_out, d=4, ) self.assertRaisesMessage( TypeError, "GIMarshallingTests.int_three_in_three_out() got an unexpected keyword argument 'e'", GIMarshallingTests.int_three_in_three_out, **{"e": 2}, ) def test_kwargs_are_not_modified(self): d = {"b": 2} d2 = d.copy() GIMarshallingTests.int_three_in_three_out(1, c=4, **d) self.assertEqual(d, d2) @unittest.skipUnless( hasattr(GIMarshallingTests, "int_one_in_utf8_two_in_one_allows_none"), "Requires newer GIMarshallingTests", ) def test_allow_none_as_default(self): GIMarshallingTests.int_two_in_utf8_two_in_with_allow_none(1, 2, "3", "4") GIMarshallingTests.int_two_in_utf8_two_in_with_allow_none(1, 2, "3") GIMarshallingTests.int_two_in_utf8_two_in_with_allow_none(1, 2) GIMarshallingTests.int_two_in_utf8_two_in_with_allow_none(1, 2, d="4") GIMarshallingTests.array_in_utf8_two_in_out_of_order("1", [-1, 0, 1, 2]) GIMarshallingTests.array_in_utf8_two_in_out_of_order("1", [-1, 0, 1, 2], "2") self.assertRaises( TypeError, GIMarshallingTests.array_in_utf8_two_in_out_of_order, [-1, 0, 1, 2], a="1", ) self.assertRaises( TypeError, GIMarshallingTests.array_in_utf8_two_in_out_of_order, [-1, 0, 1, 2], ) GIMarshallingTests.array_in_utf8_two_in([-1, 0, 1, 2], "1", "2") GIMarshallingTests.array_in_utf8_two_in([-1, 0, 1, 2], "1") GIMarshallingTests.array_in_utf8_two_in([-1, 0, 1, 2]) GIMarshallingTests.array_in_utf8_two_in([-1, 0, 1, 2], b="2") GIMarshallingTests.int_one_in_utf8_two_in_one_allows_none(1, "2", "3") GIMarshallingTests.int_one_in_utf8_two_in_one_allows_none(1, c="3") self.assertRaises( TypeError, GIMarshallingTests.int_one_in_utf8_two_in_one_allows_none, 1, "3" ) class TestKeywords(unittest.TestCase): def test_method(self): # g_variant_print() v = GLib.Variant("i", 1) self.assertEqual(v.print_(False), "1") def test_function(self): # g_thread_yield() self.assertEqual(GLib.Thread.yield_(), None) def test_struct_method(self): # g_timer_continue() # we cannot currently instantiate GLib.Timer objects, so just ensure # the method exists self.assertTrue(callable(GLib.Timer.continue_)) def test_uppercase(self): self.assertEqual(GLib.IOCondition.IN.value_nicks, ["in"]) class TestModule(unittest.TestCase): def test_type(self): self.assertIsInstance(GIMarshallingTests, types.ModuleType) def test_path(self): path = GIMarshallingTests.__path__ assert isinstance(path, list) assert len(path) == 1 assert path[0].endswith("GIMarshallingTests-1.0.typelib") def test_str(self): self.assertTrue( "'GIMarshallingTests' from '" in str(GIMarshallingTests), str(GIMarshallingTests), ) def test_dir(self): dir_ = dir(GIMarshallingTests) self.assertGreater(len(dir_), 10) self.assertTrue("SimpleStruct" in dir_) self.assertTrue("Interface2" in dir_) self.assertTrue("CONSTANT_GERROR_CODE" in dir_) self.assertTrue("array_zero_terminated_inout" in dir_) # assert that dir() does not contain garbage for item_name in dir_: item = getattr(GIMarshallingTests, item_name) self.assertTrue(hasattr(item, "__class__")) def test_help(self): with capture_output() as (stdout, _stderr): help(GIMarshallingTests) output = stdout.getvalue() self.assertTrue("SimpleStruct" in output, output) self.assertTrue("Interface2" in output, output) self.assertTrue("method_array_inout" in output, output) class TestProjectVersion(unittest.TestCase): def test_version_str(self): self.assertGreater(gi.__version__, "3.") def test_version_info(self): self.assertEqual(len(gi.version_info), 3) self.assertGreaterEqual(gi.version_info, (3, 3, 5)) def test_check_version(self): self.assertRaises(ValueError, gi.check_version, (99, 0, 0)) self.assertRaises(ValueError, gi.check_version, "99.0.0") gi.check_version((3, 3, 5)) gi.check_version("3.3.5") class TestGIWarning(unittest.TestCase): def test_warning(self): ignored_by_default = ( DeprecationWarning, PendingDeprecationWarning, ImportWarning, ) with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") warnings.warn("test", PyGIWarning) self.assertTrue(issubclass(warn[0].category, Warning)) # We don't want PyGIWarning get ignored by default self.assertFalse(issubclass(warn[0].category, ignored_by_default)) class TestDeprecation(unittest.TestCase): def test_method(self): d = GLib.Date.new() with self.assertWarns(DeprecationWarning) as w: d.set_time(1) self.assertEqual(str(w.warning), "GLib.Date.set_time is deprecated") self.assertIn("test_gi.py", w.filename) def test_function(self): with self.assertWarns(DeprecationWarning) as w: GLib.strcasecmp("foo", "bar") self.assertEqual(str(w.warning), "GLib.strcasecmp is deprecated") self.assertIn("test_gi.py", w.filename) def test_deprecated_attribute_compat(self): # test that deprecatied attributes behave like instance attributes # save the deprecation deprecation = GLib._deprecations["IO_STATUS_ERROR"] with self.assertWarns(PyGIDeprecationWarning) as w: self.assertTrue(hasattr(GLib, "IO_STATUS_ERROR")) self.assertEqual( str(w.warning), "GLib.IO_STATUS_ERROR is deprecated; use GLib.IOStatus.ERROR instead", ) self.assertIn("test_gi.py", w.filename) # deprecated attributes appear in dir() self.assertIn("IO_STATUS_ERROR", dir(GLib)) try: # check if replacing works GLib.IO_STATUS_ERROR = "foo" self.assertEqual(GLib.IO_STATUS_ERROR, "foo") finally: # restore deprecation with contextlib.suppress(AttributeError): del GLib.IO_STATUS_ERROR GLib._deprecations["IO_STATUS_ERROR"] = deprecation try: # check if deleting works del GLib.IO_STATUS_ERROR self.assertFalse(hasattr(GLib, "IO_STATUS_ERROR")) finally: # restore deprecation with contextlib.suppress(AttributeError): del GLib.IO_STATUS_ERROR GLib._deprecations["IO_STATUS_ERROR"] = deprecation def test_deprecated_attribute_warning(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") self.assertEqual(GLib.IO_STATUS_ERROR, GLib.IOStatus.ERROR) GLib.IO_STATUS_ERROR GLib.IO_STATUS_ERROR self.assertEqual(len(warn), 3) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) self.assertRegex( str(warn[0].message), ".*GLib.IO_STATUS_ERROR.*GLib.IOStatus.ERROR.*" ) def test_deprecated_attribute_warning_coverage(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") GObject.markup_escape_text GObject.PRIORITY_DEFAULT GObject.GError GObject.PARAM_CONSTRUCT GObject.SIGNAL_ACTION GObject.property GObject.IO_STATUS_ERROR GObject.G_MAXUINT64 GLib.IO_STATUS_ERROR GLib.SPAWN_SEARCH_PATH GLib.OPTION_FLAG_HIDDEN GLib.IO_FLAG_IS_WRITEABLE GLib.IO_FLAG_NONBLOCK GLib.USER_DIRECTORY_DESKTOP GLib.OPTION_ERROR_BAD_VALUE GLib.glib_version GLib.pyglib_version self.assertEqual(len(warn), 17) def test_deprecated_init_no_keywords(self): def init(self, **kwargs): self.assertDictEqual(kwargs, {"a": 1, "b": 2, "c": 3}) fn = gi.overrides.deprecated_init(init, arg_names=("a", "b", "c")) with self.assertWarns(PyGIDeprecationWarning) as w: fn(self, 1, 2, 3) self.assertRegex(str(w.warning), ".*keyword.*a, b, c.*") self.assertIn("test_gi.py", w.filename) def test_deprecated_init_no_keywords_out_of_order(self): def init(self, **kwargs): self.assertDictEqual(kwargs, {"a": 1, "b": 2, "c": 3}) fn = gi.overrides.deprecated_init(init, arg_names=("b", "a", "c")) with self.assertWarns(PyGIDeprecationWarning) as w: fn(self, 2, 1, 3) self.assertRegex(str(w.warning), ".*keyword.*b, a, c.*") self.assertIn("test_gi.py", w.filename) def test_deprecated_init_ignored_keyword(self): def init(self, **kwargs): self.assertDictEqual(kwargs, {"a": 1, "c": 3}) fn = gi.overrides.deprecated_init( init, arg_names=("a", "b", "c"), ignore=("b",) ) with self.assertWarns(PyGIDeprecationWarning) as w: fn(self, 1, 2, 3) self.assertRegex(str(w.warning), ".*keyword.*a, b, c.*") self.assertIn("test_gi.py", w.filename) def test_deprecated_init_with_aliases(self): def init(self, **kwargs): self.assertDictEqual(kwargs, {"a": 1, "b": 2, "c": 3}) fn = gi.overrides.deprecated_init( init, arg_names=("a", "b", "c"), deprecated_aliases={"b": "bb", "c": "cc"} ) with self.assertWarns(PyGIDeprecationWarning) as w: fn(self, a=1, bb=2, cc=3) self.assertRegex( str(w.warning), '.*keyword.*"bb, cc".*deprecated.*"b, c" respectively' ) self.assertIn("test_gi.py", w.filename) def test_deprecated_init_with_defaults(self): def init(self, **kwargs): self.assertDictEqual(kwargs, {"a": 1, "b": 2, "c": 3}) fn = gi.overrides.deprecated_init( init, arg_names=("a", "b", "c"), deprecated_defaults={"b": 2, "c": 3} ) with self.assertWarns(PyGIDeprecationWarning) as w: fn(self, a=1) self.assertRegex( str(w.warning), ".*relying on deprecated non-standard defaults.*explicitly use: b=2, c=3", ) self.assertIn("test_gi.py", w.filename) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_gio.py0000664000000000000000000005706015074673150015707 0ustar00rootrootimport contextlib import os import unittest import warnings import pytest GioUnix = None with contextlib.suppress(ImportError): from gi.repository import GioUnix import gi.overrides from gi import PyGIWarning, PyGIDeprecationWarning from gi.repository import GLib, Gio from .helper import ignore_gi_deprecation_warnings class TestGio(unittest.TestCase): def test_file_enumerator(self): self.assertEqual(Gio.FileEnumerator, gi.overrides.Gio.FileEnumerator) f = Gio.file_new_for_path("./") iter_info = [ info.get_name() for info in f.enumerate_children("standard::*", 0, None) ] next_info = [] enumerator = f.enumerate_children("standard::*", 0, None) while True: info = enumerator.next_file(None) if info is None: break next_info.append(info.get_name()) self.assertEqual(iter_info, next_info) def test_menu_item(self): menu = Gio.Menu() item = Gio.MenuItem() item.set_attribute([("label", "s", "Test"), ("action", "s", "app.test")]) menu.append_item(item) value = menu.get_item_attribute_value(0, "label", GLib.VariantType.new("s")) self.assertEqual("Test", value.unpack()) value = menu.get_item_attribute_value(0, "action", GLib.VariantType.new("s")) self.assertEqual("app.test", value.unpack()) def test_volume_monitor_warning(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") Gio.VolumeMonitor() self.assertEqual(len(warn), 1) self.assertTrue(issubclass(warn[0].category, PyGIWarning)) self.assertRegex( str(warn[0].message), ".*Gio\\.VolumeMonitor\\.get\\(\\).*" ) class TestGioPlatform(unittest.TestCase): desktopFileContent = f"""[Desktop Entry] Version=1.0 Type=Application Name=Some Application Exec={GLib.find_program_in_path("true")} %u Actions=act; Categories=Development;Profiling; GenericName=Test Hidden=true Keywords=test;example; NoDisplay=true OnlyShowIn=GNOME; StartupWMClass=testTest X-Bool=true [Desktop Action act] Name=Take action! Exec={GLib.find_program_in_path("true")} action """ def setUp(self): super().setUp() if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) < (2, 80): self.skipTest("Installed Gio is not new enough for this test") if GioUnix: self.key_file = GLib.KeyFile() self.key_file.load_from_data( self.desktopFileContent, len(self.desktopFileContent), GLib.KeyFileFlags.NONE, ) def assert_expected_desktop_app_info(self, app_info): # All functionality is available as ordinary methods, without # needing extraneous arguments # https://gitlab.gnome.org/GNOME/pygobject/-/issues/719 self.assertEqual(app_info.get_action_name("act"), "Take action!") self.assertEqual(app_info.get_boolean("X-Bool"), True) self.assertEqual(app_info.get_categories(), "Development;Profiling;") self.assertIsNone(app_info.get_filename()) self.assertEqual(app_info.get_generic_name(), "Test") self.assertEqual(app_info.get_is_hidden(), True) self.assertEqual(app_info.get_keywords(), ["test", "example"]) self.assertEqual(app_info.get_locale_string("Keywords"), "test;example;") self.assertEqual(app_info.get_nodisplay(), True) self.assertEqual(app_info.get_show_in("GNOME"), True) self.assertEqual(app_info.get_show_in("KDE"), False) # get_show_in() can be called without an argument, which means NULL self.assertIn(app_info.get_show_in(), [True, False]) self.assertIn(app_info.get_show_in(None), [True, False]) self.assertEqual(app_info.get_startup_wm_class(), "testTest") self.assertEqual(app_info.get_string("StartupWMClass"), "testTest") self.assertEqual(app_info.get_string_list("Keywords"), ["test", "example"]) self.assertEqual(app_info.has_key("Keywords"), True) self.assertEqual(app_info.list_actions(), ["act"]) # All functionality is also available via unbound methods: # for example Cinnamon relies on this as of October 2025 self.assertEqual( GioUnix.DesktopAppInfo.get_action_name(app_info, "act"), "Take action!" ) self.assertEqual( Gio.DesktopAppInfo.get_action_name(app_info, "act"), "Take action!" ) # Exercise methods that actually launch something app_info.launch_action("act") app_info.launch_action("act", None) self.assertTrue( app_info.launch_uris_as_manager( ["about:blank"], None, GLib.SpawnFlags.DEFAULT, None, None, None, None, ), ) self.assertTrue( app_info.launch_uris_as_manager( ["about:blank"], None, GLib.SpawnFlags.DEFAULT, ), ) self.assertTrue( app_info.launch_uris_as_manager_with_fds( ["about:blank"], None, GLib.SpawnFlags.DEFAULT, None, None, None, None, -1, -1, -1, ), ) @unittest.skipIf( GioUnix is None or "DesktopAppInfo" not in dir(GioUnix), "Not supported" ) def test_desktop_app_info_can_be_created_from_gio_unix(self): app_info = GioUnix.DesktopAppInfo.new_from_keyfile(self.key_file) self.assertIsNotNone(app_info) self.assertIsInstance(app_info, GioUnix.DesktopAppInfo) self.assertIsInstance(app_info, Gio.AppInfo) self.assert_expected_desktop_app_info(app_info) @unittest.skipIf( GioUnix is None or "DesktopAppInfo" not in dir(GioUnix), "Not supported" ) def test_desktop_app_info_can_be_created_from_gio(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") app_info = Gio.DesktopAppInfo.new_from_keyfile(self.key_file) if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) >= (2, 86): self.assertEqual(len(warn), 1) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) self.assertEqual( str(warn[0].message), "Gio.DesktopAppInfo is deprecated; " + "use GioUnix.DesktopAppInfo instead", ) self.assertIsNotNone(app_info) self.assertIsInstance(app_info, Gio.DesktopAppInfo) self.assertIsInstance(app_info, Gio.AppInfo) @unittest.skipIf( GioUnix is None or "FDMessage" not in dir(GioUnix), "Not supported" ) def test_fd_message(self): message = GioUnix.FDMessage.new() self.assertIsNotNone(message) with open("/dev/null", "r+b") as devnull: self.assertTrue(message.append_fd(devnull.fileno())) self.assertIsNotNone(message.get_fd_list()) fds = message.steal_fds() self.assertEqual(len(fds), 1) os.close(fds[0]) @unittest.skipIf( GioUnix is None or "DesktopAppInfo" not in dir(GioUnix), "Not supported" ) def test_gio_unix_desktop_app_info_provides_platform_independent_functions(self): app_info = GioUnix.DesktopAppInfo.new_from_keyfile(self.key_file) self.assertEqual(app_info.get_name(), "Some Application") @unittest.skipIf( GioUnix is None or "DesktopAppInfo" not in dir(GioUnix), "Not supported" ) @ignore_gi_deprecation_warnings def test_gio_desktop_app_info_provides_platform_independent_functions(self): app_info = Gio.DesktopAppInfo.new_from_keyfile(self.key_file) self.assertEqual(app_info.get_name(), "Some Application") @unittest.skipIf( GioUnix is None or "DesktopAppInfo" not in dir(GioUnix), "Not supported" ) def test_gio_unix_desktop_app_info_provides_unix_only_functions(self): app_info = GioUnix.DesktopAppInfo.new_from_keyfile(self.key_file) self.assertTrue(app_info.has_key("Name")) self.assertEqual(app_info.get_string("Name"), "Some Application") @unittest.skipIf( GioUnix is None or "DesktopAppInfo" not in dir(GioUnix), "Not supported" ) @ignore_gi_deprecation_warnings def test_gio_desktop_app_info_provides_unix_only_functions(self): app_info = Gio.DesktopAppInfo.new_from_keyfile(self.key_file) self.assertTrue(app_info.has_key("Name")) self.assertEqual(app_info.get_string("Name"), "Some Application") @unittest.skipIf(GioUnix is None, "Not supported") def test_deprecated_unix_function_can_be_called_from_gio(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") mount_points = Gio.unix_mount_points_get() if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) >= (2, 86): self.assertEqual(len(warn), 1) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) self.assertEqual( str(warn[0].message), "Gio.unix_mount_points_get is deprecated; " + "use GioUnix.mount_points_get instead", ) self.assertIsNotNone(mount_points) if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) >= (2, 86): self.assertEqual(GioUnix.mount_points_get, Gio.unix_mount_points_get) def assert_expected_unix_stream_type(self, stream_type): with open("/dev/null", "r+b") as devnull: stream = stream_type.new(devnull.fileno(), False) self.assertIsNotNone(stream) self.assertEqual(stream.get_close_fd(), False) stream.set_close_fd(False) self.assertNotEqual(stream.get_fd(), -1) @unittest.skipIf(GioUnix is None, "Not supported") def test_deprecated_unix_type_can_be_used_if_equal_exists_in_gio(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") input_stream = Gio.UnixInputStream if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) >= (2, 86): self.assertEqual(len(warn), 1) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) self.assertEqual( str(warn[0].message), "Gio.UnixInputStream is deprecated; " + "use GioUnix.InputStream instead", ) self.assertIsNotNone(input_stream) self.assertEqual(Gio.UnixInputStream, GioUnix.InputStream) self.assertNotEqual(Gio.InputStream, GioUnix.InputStream) self.assert_expected_unix_stream_type(Gio.UnixInputStream) self.assert_expected_unix_stream_type(GioUnix.InputStream) self.assert_expected_unix_stream_type(Gio.UnixOutputStream) self.assert_expected_unix_stream_type(GioUnix.OutputStream) @unittest.skipIf(GioUnix is None, "Not supported") def test_deprecated_unix_class_can_be_used_from_gio(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") monitor = Gio.UnixMountMonitor.get() if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) >= (2, 86): self.assertEqual(len(warn), 1) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) self.assertEqual( str(warn[0].message), "Gio.UnixMountMonitor is deprecated; " + "use GioUnix.MountMonitor instead", ) self.assertIsNotNone(monitor) self.assertEqual(Gio.UnixMountMonitor.get, GioUnix.MountMonitor.get) @unittest.skipIf(GioUnix is None, "Not supported") def test_deprecated_unix_gobject_class_can_be_used_from_gio(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") input_stream_class = Gio.UnixInputStreamClass if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) >= (2, 86): self.assertEqual(len(warn), 1) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) self.assertEqual( str(warn[0].message), "Gio.UnixInputStreamClass is deprecated; " + "use GioUnix.InputStreamClass instead", ) self.assertIsNotNone(input_stream_class) if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) >= (2, 86): self.assertEqual(Gio.UnixInputStreamClass, GioUnix.InputStreamClass) self.assertNotEqual(Gio.InputStreamClass, GioUnix.InputStreamClass) class TestGSettings(unittest.TestCase): def setUp(self): self.settings = Gio.Settings.new("org.gnome.test") # we change the values in the tests, so set them to predictable start # value self.settings.reset("test-string") self.settings.reset("test-array") self.settings.reset("test-boolean") self.settings.reset("test-enum") def test_iter(self): assert set(self.settings) == { "test-tuple", "test-array", "test-boolean", "test-string", "test-enum", "test-range", } def test_get_set(self): for key in self.settings: old_value = self.settings[key] self.settings[key] = old_value assert self.settings[key] == old_value def test_native(self): self.assertTrue("test-array" in self.settings.list_keys()) # get various types v = self.settings.get_value("test-boolean") self.assertEqual(v.get_boolean(), True) self.assertEqual(self.settings.get_boolean("test-boolean"), True) v = self.settings.get_value("test-string") self.assertEqual(v.get_string(), "Hello") self.assertEqual(self.settings.get_string("test-string"), "Hello") v = self.settings.get_value("test-array") self.assertEqual(v.unpack(), [1, 2]) v = self.settings.get_value("test-tuple") self.assertEqual(v.unpack(), (1, 2)) v = self.settings.get_value("test-range") assert v.unpack() == 123 # set a value self.settings.set_string("test-string", "World") self.assertEqual(self.settings.get_string("test-string"), "World") self.settings.set_value("test-string", GLib.Variant("s", "Goodbye")) self.assertEqual(self.settings.get_string("test-string"), "Goodbye") def test_constructor(self): # default constructor uses path from schema self.assertEqual(self.settings.get_property("path"), "/tests/") # optional constructor arguments with_path = Gio.Settings.new_with_path("org.gnome.nopathtest", "/mypath/") self.assertEqual(with_path.get_property("path"), "/mypath/") self.assertEqual(with_path["np-int"], 42) def test_dictionary_api(self): self.assertEqual(len(self.settings), 6) self.assertTrue("test-array" in self.settings) self.assertTrue("test-array" in self.settings) self.assertFalse("nonexisting" in self.settings) self.assertFalse(4 in self.settings) self.assertEqual(bool(self.settings), True) def test_get(self): self.assertEqual(self.settings["test-boolean"], True) self.assertEqual(self.settings["test-string"], "Hello") self.assertEqual(self.settings["test-enum"], "banana") self.assertEqual(self.settings["test-array"], [1, 2]) self.assertEqual(self.settings["test-tuple"], (1, 2)) self.assertRaises(KeyError, self.settings.__getitem__, "unknown") self.assertRaises(KeyError, self.settings.__getitem__, 2) def test_set(self): self.settings["test-boolean"] = False self.assertEqual(self.settings["test-boolean"], False) self.settings["test-string"] = "Goodbye" self.assertEqual(self.settings["test-string"], "Goodbye") self.settings["test-array"] = [3, 4, 5] self.assertEqual(self.settings["test-array"], [3, 4, 5]) self.settings["test-enum"] = "pear" self.assertEqual(self.settings["test-enum"], "pear") self.assertRaises(TypeError, self.settings.__setitem__, "test-string", 1) self.assertRaises(ValueError, self.settings.__setitem__, "test-enum", "plum") self.assertRaises(KeyError, self.settings.__setitem__, "unknown", "moo") def test_set_range(self): self.settings["test-range"] = 7 assert self.settings["test-range"] == 7 self.settings["test-range"] = 65535 assert self.settings["test-range"] == 65535 with pytest.raises(ValueError, match=r".*7 - 65535.*"): self.settings["test-range"] = 7 - 1 with pytest.raises(ValueError, match=r".*7 - 65535.*"): self.settings["test-range"] = 65535 + 1 def test_empty(self): empty = Gio.Settings.new_with_path("org.gnome.empty", "/tests/") self.assertEqual(len(empty), 0) self.assertEqual(bool(empty), True) self.assertEqual(empty.keys(), []) @ignore_gi_deprecation_warnings def test_change_event(self): changed_log = [] change_event_log = [] def on_changed(settings, key): changed_log.append((settings, key)) def on_change_event(settings, keys, n_keys): change_event_log.append((settings, keys, n_keys)) self.settings.connect("changed", on_changed) self.settings.connect("change-event", on_change_event) self.settings["test-string"] = "Moo" self.assertEqual(changed_log, [(self.settings, "test-string")]) self.assertEqual( change_event_log, [(self.settings, [GLib.quark_from_static_string("test-string")], 1)], ) @unittest.skipIf(os.name == "nt", "FIXME") class TestGFile(unittest.TestCase): def setUp(self): self.file, self.io_stream = Gio.File.new_tmp("TestGFile.XXXXXX") def tearDown(self): with contextlib.suppress(GLib.GError): # test_delete and test_delete_async already remove it self.file.delete(None) def test_replace_contents(self): content = b"hello\0world\x7f!" succ, etag = self.file.replace_contents( content, None, False, Gio.FileCreateFlags.NONE, None ) new_succ, new_content, new_etag = self.file.load_contents(None) self.assertTrue(succ) self.assertTrue(new_succ) self.assertEqual(etag, new_etag) self.assertEqual(content, new_content) # https://bugzilla.gnome.org/show_bug.cgi?id=690525 def disabled_test_replace_contents_async(self): content = b"".join(bytes(chr(i), "utf-8") for i in range(128)) def callback(f, result, d): # Quit so in case of failed assertations loop doesn't keep running. main_loop.quit() _succ, _etag = self.file.replace_contents_finish(result) _new_succ, _new_content, _new_etag = self.file.load_contents(None) d["succ"], d["etag"] = self.file.replace_contents_finish(result) load = self.file.load_contents(None) d["new_succ"], d["new_content"], d["new_etag"] = load data = {} self.file.replace_contents_async( content, None, False, Gio.FileCreateFlags.NONE, None, callback, data ) main_loop = GLib.MainLoop() main_loop.run() self.assertTrue(data["succ"]) self.assertTrue(data["new_succ"]) self.assertEqual(data["etag"], data["new_etag"]) self.assertEqual(content, data["new_content"]) def test_tmp_exists(self): # A simple test to check if Gio.File.new_tmp is working correctly. self.assertTrue(self.file.query_exists(None)) def test_delete(self): self.file.delete(None) self.assertFalse(self.file.query_exists(None)) def test_delete_async(self): def callback(f, result, data): main_loop.quit() self.file.delete_async(0, None, callback, None) main_loop = GLib.MainLoop() main_loop.run() self.assertFalse(self.file.query_exists(None)) @unittest.skipIf(os.name == "nt", "crashes on Windows") class TestGApplication(unittest.TestCase): def test_command_line(self): class App(Gio.Application): args = None def __init__(self): super().__init__(flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE) def do_command_line(self, cmdline): self.args = cmdline.get_arguments() return 42 app = App() res = app.run(["spam", "eggs"]) self.assertEqual(res, 42) self.assertSequenceEqual(app.args, ["spam", "eggs"]) def test_local_command_line(self): class App(Gio.Application): local_args = None def __init__(self): super().__init__(flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE) def do_local_command_line(self, args): self.local_args = args[:] # copy args.remove("eggs") # True skips do_command_line being called. return True, args, 42 app = App() res = app.run(["spam", "eggs"]) self.assertEqual(res, 42) self.assertSequenceEqual(app.local_args, ["spam", "eggs"]) def test_local_and_remote_command_line(self): class App(Gio.Application): args = None local_args = None def __init__(self): super().__init__(flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE) def do_command_line(self, cmdline): self.args = cmdline.get_arguments() return 42 def do_local_command_line(self, args): self.local_args = args[:] # copy args.remove("eggs") # False causes do_command_line to be called with args. return False, args, 0 app = App() res = app.run(["spam", "eggs"]) self.assertEqual(res, 42) self.assertSequenceEqual(app.args, ["spam"]) self.assertSequenceEqual(app.local_args, ["spam", "eggs"]) @unittest.skipUnless( hasattr(Gio.Application, "add_main_option"), "Requires newer version of GLib" ) def test_add_main_option(self): stored_options = [] def on_handle_local_options(app, options): stored_options.append(options) return 0 # Return 0 if options have been handled def on_activate(app): pass app = Gio.Application() app.add_main_option( long_name="string", short_name=b"s", flags=0, arg=GLib.OptionArg.STRING, description="some string", ) app.connect("activate", on_activate) app.connect("handle-local-options", on_handle_local_options) app.run(["app", "-s", "test string"]) self.assertEqual(len(stored_options), 1) options = stored_options[0] self.assertTrue(options.contains("string")) self.assertEqual(options.lookup_value("string").unpack(), "test string") def test_add_action_entries_override(self): app = Gio.Application() app.add_action_entries( [ ("app.new", print), ("app.quit", print), ] ) assert app.lookup_action("app.new").get_name() == "app.new" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_glib.py0000664000000000000000000002551015074673150016041 0ustar00rootrootimport os import sys import unittest import os.path import warnings import subprocess import pytest from gi.repository import GLib from gi import PyGIDeprecationWarning class TestGLib(unittest.TestCase): @pytest.mark.xfail() def test_pytest_capture_error_in_closure(self): # this test is supposed to fail ml = GLib.MainLoop() def callback(): ml.quit() raise Exception("expected") GLib.idle_add(callback) ml.run() @unittest.skipIf(os.name == "nt", "no bash on Windows") def test_find_program_in_path(self): bash_path = GLib.find_program_in_path("bash") self.assertTrue(bash_path.endswith(os.path.sep + "bash")) self.assertTrue(os.path.exists(bash_path)) self.assertEqual(GLib.find_program_in_path("non existing"), None) def test_markup_escape_text(self): self.assertEqual(GLib.markup_escape_text("a&bä"), "a&bä") self.assertEqual(GLib.markup_escape_text(b"a&b\x05"), "a&b") # with explicit length argument self.assertEqual(GLib.markup_escape_text(b"a\x05\x01\x02", 2), "a") def test_progname(self): GLib.set_prgname("moo") self.assertEqual(GLib.get_prgname(), "moo") def test_appname(self): GLib.set_application_name("moo") self.assertEqual(GLib.get_application_name(), "moo") def test_xdg_dirs(self): d = GLib.get_user_data_dir() self.assertTrue(os.path.sep in d, d) d = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP) self.assertTrue(os.path.sep in d, d) with warnings.catch_warnings(): warnings.simplefilter("ignore", PyGIDeprecationWarning) # also works with backwards compatible enum names self.assertEqual( GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_MUSIC), GLib.get_user_special_dir(GLib.USER_DIRECTORY_MUSIC), ) for d in GLib.get_system_config_dirs(): self.assertTrue(os.path.sep in d, d) for d in GLib.get_system_data_dirs(): self.assertTrue(isinstance(d, str), d) def test_main_depth(self): self.assertEqual(GLib.main_depth(), 0) def test_filenames(self): self.assertEqual(GLib.filename_display_name("foo"), "foo") self.assertEqual(GLib.filename_display_basename("bar/foo"), "foo") def glibfsencode(f): # the annotations of filename_from_utf8() was changed in # https://bugzilla.gnome.org/show_bug.cgi?id=756128 if isinstance(f, bytes): return f if os.name == "nt": return f.encode("utf-8", "surrogatepass") return os.fsencode(f) # this is locale dependent, so we cannot completely verify the result res = GLib.filename_from_utf8("aäb") res = glibfsencode(res) self.assertTrue(isinstance(res, bytes)) self.assertGreaterEqual(len(res), 3) # with explicit length argument res = GLib.filename_from_utf8("aäb", 1) res = glibfsencode(res) self.assertEqual(res, b"a") def test_uri_extract(self): res = GLib.uri_list_extract_uris("""# some comment http://example.com https://my.org/q?x=1&y=2 http://gnome.org/new""") self.assertEqual( res, ["http://example.com", "https://my.org/q?x=1&y=2", "http://gnome.org/new"], ) def test_current_time(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") tm = GLib.get_current_time() self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) self.assertTrue(isinstance(tm, float)) self.assertGreater(tm, 1350000000.0) @unittest.skipIf(sys.platform == "darwin", "fails on OSX") def test_main_loop(self): # note we do not test run() here, as we use this in countless other # tests ml = GLib.MainLoop() self.assertFalse(ml.is_running()) context = ml.get_context() self.assertEqual(context, GLib.MainContext.default()) self.assertTrue(context.is_owner() in [True, False]) self.assertTrue(context.pending() in [True, False]) self.assertFalse(context.iteration(False)) def test_main_loop_with_context(self): context = GLib.MainContext() ml = GLib.MainLoop(context) self.assertFalse(ml.is_running()) self.assertEqual(ml.get_context(), context) def test_main_context(self): # constructor context = GLib.MainContext() self.assertTrue(context.is_owner() in [True, False]) self.assertFalse(context.pending()) self.assertFalse(context.iteration(False)) # GLib API context = GLib.MainContext.default() self.assertTrue(context.is_owner() in [True, False]) self.assertTrue(context.pending() in [True, False]) self.assertTrue(context.iteration(False) in [True, False]) # backwards compatible API context = GLib.main_context_default() self.assertTrue(context.is_owner() in [True, False]) self.assertTrue(context.pending() in [True, False]) self.assertTrue(context.iteration(False) in [True, False]) def test_main_context_query(self): context = GLib.MainContext() assert context.acquire() timeout_msec, fds = context.query(0) assert timeout_msec == 0 assert len(fds) == 1 @unittest.skipIf(os.name == "nt", "hangs") def test_io_add_watch_no_data(self): (r, w) = os.pipe() call_data = [] def cb(fd, condition): call_data.append((fd, condition, os.read(fd, 1))) if len(call_data) == 2: ml.quit() return True # io_add_watch() takes an IOChannel, calling with an fd is deprecated with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") GLib.io_add_watch(r, GLib.IOCondition.IN, cb, priority=GLib.PRIORITY_HIGH) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) def write(): os.write(w, b"a") GLib.idle_add(lambda: os.write(w, b"b") and False) ml = GLib.MainLoop() GLib.idle_add(write) GLib.timeout_add(2000, ml.quit) ml.run() self.assertEqual( call_data, [(r, GLib.IOCondition.IN, b"a"), (r, GLib.IOCondition.IN, b"b")] ) @unittest.skipIf(os.name == "nt", "hangs") def test_io_add_watch_with_data(self): (r, w) = os.pipe() call_data = [] def cb(fd, condition, data): call_data.append((fd, condition, os.read(fd, 1), data)) if len(call_data) == 2: ml.quit() return True # io_add_watch() takes an IOChannel, calling with an fd is deprecated with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") GLib.io_add_watch( r, GLib.IOCondition.IN, cb, "moo", priority=GLib.PRIORITY_HIGH ) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) def write(): os.write(w, b"a") GLib.idle_add(lambda: os.write(w, b"b") and False) ml = GLib.MainLoop() GLib.idle_add(write) GLib.timeout_add(2000, ml.quit) ml.run() self.assertEqual( call_data, [ (r, GLib.IOCondition.IN, b"a", "moo"), (r, GLib.IOCondition.IN, b"b", "moo"), ], ) @unittest.skipIf(os.name == "nt", "hangs") def test_io_add_watch_with_multiple_data(self): (r, w) = os.pipe() call_data = [] def cb(fd, condition, *user_data): call_data.append((fd, condition, os.read(fd, 1), user_data)) ml.quit() return True # io_add_watch() takes an IOChannel, calling with an fd is deprecated with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") GLib.io_add_watch(r, GLib.IOCondition.IN, cb, "moo", "foo") self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) ml = GLib.MainLoop() GLib.idle_add(lambda: os.write(w, b"a") and False) GLib.timeout_add(2000, ml.quit) ml.run() self.assertEqual(call_data, [(r, GLib.IOCondition.IN, b"a", ("moo", "foo"))]) @unittest.skipIf(sys.platform == "darwin", "fails") @unittest.skipIf(os.name == "nt", "no shell on Windows") def test_io_add_watch_pyfile(self): call_data = [] cmd = subprocess.Popen( "echo hello; echo world", shell=True, bufsize=0, stdout=subprocess.PIPE ) def cb(file, condition): call_data.append((file, condition, file.readline())) if len(call_data) == 2: # avoid having to wait for the full timeout ml.quit() return True # io_add_watch() takes an IOChannel, calling with a Python file is deprecated with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") GLib.io_add_watch(cmd.stdout, GLib.IOCondition.IN, cb) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) ml = GLib.MainLoop() GLib.timeout_add(2000, ml.quit) ml.run() cmd.wait() self.assertEqual( call_data, [ (cmd.stdout, GLib.IOCondition.IN, b"hello\n"), (cmd.stdout, GLib.IOCondition.IN, b"world\n"), ], ) def test_glib_version(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", PyGIDeprecationWarning) (major, minor, micro) = GLib.glib_version self.assertGreaterEqual(major, 2) self.assertGreaterEqual(minor, 0) self.assertGreaterEqual(micro, 0) def test_pyglib_version(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", PyGIDeprecationWarning) (major, minor, micro) = GLib.pyglib_version self.assertGreaterEqual(major, 3) self.assertGreaterEqual(minor, 0) self.assertGreaterEqual(micro, 0) def test_timezone_constructor(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) timezone = GLib.TimeZone("+05:21") self.assertEqual(timezone.get_offset(0), ((5 * 60) + 21) * 60) def test_source_attach_implicit_context(self): context = GLib.MainContext.default() source = GLib.Idle() source_id = source.attach() self.assertEqual(context, source.get_context()) self.assertTrue(GLib.Source.remove(source_id)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_gobject.py0000664000000000000000000010372215074673150016543 0ustar00rootrootimport sys import gc import unittest import warnings import weakref import platform import pytest from gi.repository import GObject, GLib, Gio from gi import PyGIDeprecationWarning from gi.module import get_introspection_module from gi import _gi import testhelper from .helper import capture_glib_deprecation_warnings @pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="crashes") def test_gobject_weak_ref(): called = [] def callback(*args): called.extend(args) # object gets finalized obj = GObject.Object() obj.weak_ref(callback, 1) del obj gc.collect() gc.collect() assert called == [1] del called[:] # wrapper gets finalized first obj = GObject.Object() pyref = weakref.ref(obj, lambda x: callback(-2)) value = GObject.Value(GObject.Object, obj) ref = obj.weak_ref(callback, 2) del obj gc.collect() assert called == [-2] del pyref value.unset() gc.collect() assert called == [-2, 2] del called[:] # weakref gets unregistered first obj = GObject.Object() ref = obj.weak_ref(callback, 3) ref.unref() del obj gc.collect() assert not called # weakref gets GCed obj = GObject.Object() obj.weak_ref(callback, 4) gc.collect() del obj assert called == [4] class TestGObjectAPI(unittest.TestCase): def test_run_dispose(self): class TestObject(GObject.GObject): int_prop = GObject.Property(default=0, type=int) obj = TestObject() called = [] def on_notify(*args): called.append(args) obj.connect("notify::int-prop", on_notify) obj.notify("int-prop") obj.notify("int-prop") # after this everything should be disconnected obj.run_dispose() obj.notify("int-prop") obj.notify("int-prop") assert len(called) == 2 def test_call_method_uninitialized_instance(self): obj = GObject.Object.__new__(GObject.Object) with self.assertRaisesRegex(RuntimeError, ".*is not initialized"): obj.notify("foo") def test_gobject_inheritance(self): # GObject.Object is a class hierarchy as follows: # overrides.Object -> introspection.Object -> static.GObject GIObjectModule = get_introspection_module("GObject") self.assertTrue(issubclass(GObject.Object, GIObjectModule.Object)) self.assertTrue(issubclass(GIObjectModule.Object, _gi.GObject)) self.assertEqual(_gi.GObject.__gtype__, GObject.TYPE_OBJECT) self.assertEqual(GIObjectModule.Object.__gtype__, GObject.TYPE_OBJECT) self.assertEqual(GObject.Object.__gtype__, GObject.TYPE_OBJECT) # The pytype wrapper should hold the outer most Object class from overrides. self.assertEqual(GObject.TYPE_OBJECT.pytype, GObject.Object) def test_gobject_unsupported_overrides(self): obj = GObject.Object() with self.assertRaisesRegex( RuntimeError, "Data access methods are unsupported.*" ): obj.get_data() with self.assertRaisesRegex( RuntimeError, "This method is currently unsupported.*" ): obj.force_floating() def test_compat_api(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") # GObject formerly exposed a lot of GLib's functions self.assertEqual(GObject.markup_escape_text("foo"), "foo") ml = GObject.MainLoop() self.assertFalse(ml.is_running()) context = GObject.main_context_default() self.assertTrue(context.pending() in [False, True]) context = GObject.MainContext() self.assertFalse(context.pending()) self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning)) self.assertTrue("GLib.markup_escape_text" in str(w[0]), str(w[0])) self.assertLess(GObject.PRIORITY_HIGH, GObject.PRIORITY_DEFAULT) def test_min_max_int(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", PyGIDeprecationWarning) self.assertEqual(GObject.G_MAXINT16, 2**15 - 1) self.assertEqual(GObject.G_MININT16, -(2**15)) self.assertEqual(GObject.G_MAXUINT16, 2**16 - 1) self.assertEqual(GObject.G_MAXINT32, 2**31 - 1) self.assertEqual(GObject.G_MININT32, -(2**31)) self.assertEqual(GObject.G_MAXUINT32, 2**32 - 1) self.assertEqual(GObject.G_MAXINT64, 2**63 - 1) self.assertEqual(GObject.G_MININT64, -(2**63)) self.assertEqual(GObject.G_MAXUINT64, 2**64 - 1) class TestReferenceCounting(unittest.TestCase): def test_regular_object(self): obj = GObject.GObject() self.assertEqual(obj.__grefcount__, 1) obj = GObject.new(GObject.GObject) self.assertEqual(obj.__grefcount__, 1) def test_floating(self): obj = testhelper.Floating() self.assertEqual(obj.__grefcount__, 1) obj = GObject.new(testhelper.Floating) self.assertEqual(obj.__grefcount__, 1) def test_owned_by_library(self): # Upon creation, the refcount of the object should be 2: # - someone already has a reference on the new object. # - the python wrapper should hold its own reference. obj = testhelper.OwnedByLibrary() self.assertEqual(obj.__grefcount__, 2) # We ask the library to release its reference, so the only # remaining ref should be our wrapper's. Once the wrapper # will run out of scope, the object will get finalized. obj.release() self.assertEqual(obj.__grefcount__, 1) def test_owned_by_library_out_of_scope(self): obj = testhelper.OwnedByLibrary() self.assertEqual(obj.__grefcount__, 2) # We are manually taking the object out of scope. This means # that our wrapper has been freed, and its reference dropped. We # cannot check it but the refcount should now be 1 (the ref held # by the library is still there, we didn't call release() obj = None # When we get the object back from the lib, the wrapper is # re-created, so our refcount will be 2 once again. obj = testhelper.owned_by_library_get_instance_list()[0] self.assertEqual(obj.__grefcount__, 2) obj.release() self.assertEqual(obj.__grefcount__, 1) def test_owned_by_library_using_gobject_new(self): # Upon creation, the refcount of the object should be 2: # - someone already has a reference on the new object. # - the python wrapper should hold its own reference. obj = GObject.new(testhelper.OwnedByLibrary) self.assertEqual(obj.__grefcount__, 2) # We ask the library to release its reference, so the only # remaining ref should be our wrapper's. Once the wrapper # will run out of scope, the object will get finalized. obj.release() self.assertEqual(obj.__grefcount__, 1) def test_owned_by_library_out_of_scope_using_gobject_new(self): obj = GObject.new(testhelper.OwnedByLibrary) self.assertEqual(obj.__grefcount__, 2) # We are manually taking the object out of scope. This means # that our wrapper has been freed, and its reference dropped. We # cannot check it but the refcount should now be 1 (the ref held # by the library is still there, we didn't call release() obj = None # When we get the object back from the lib, the wrapper is # re-created, so our refcount will be 2 once again. obj = testhelper.owned_by_library_get_instance_list()[0] self.assertEqual(obj.__grefcount__, 2) obj.release() self.assertEqual(obj.__grefcount__, 1) def test_floating_and_sunk(self): # Upon creation, the refcount of the object should be 2: # - someone already has a reference on the new object. # - the python wrapper should hold its own reference. obj = testhelper.FloatingAndSunk() self.assertEqual(obj.__grefcount__, 2) # We ask the library to release its reference, so the only # remaining ref should be our wrapper's. Once the wrapper # will run out of scope, the object will get finalized. obj.release() self.assertEqual(obj.__grefcount__, 1) def test_floating_and_sunk_out_of_scope(self): obj = testhelper.FloatingAndSunk() self.assertEqual(obj.__grefcount__, 2) # We are manually taking the object out of scope. This means # that our wrapper has been freed, and its reference dropped. We # cannot check it but the refcount should now be 1 (the ref held # by the library is still there, we didn't call release() obj = None # When we get the object back from the lib, the wrapper is # re-created, so our refcount will be 2 once again. obj = testhelper.floating_and_sunk_get_instance_list()[0] self.assertEqual(obj.__grefcount__, 2) obj.release() self.assertEqual(obj.__grefcount__, 1) def test_floating_and_sunk_using_gobject_new(self): # Upon creation, the refcount of the object should be 2: # - someone already has a reference on the new object. # - the python wrapper should hold its own reference. obj = GObject.new(testhelper.FloatingAndSunk) self.assertEqual(obj.__grefcount__, 2) # We ask the library to release its reference, so the only # remaining ref should be our wrapper's. Once the wrapper # will run out of scope, the object will get finalized. obj.release() self.assertEqual(obj.__grefcount__, 1) def test_floating_and_sunk_out_of_scope_using_gobject_new(self): obj = GObject.new(testhelper.FloatingAndSunk) self.assertEqual(obj.__grefcount__, 2) # We are manually taking the object out of scope. This means # that our wrapper has been freed, and its reference dropped. We # cannot check it but the refcount should now be 1 (the ref held # by the library is still there, we didn't call release() obj = None # When we get the object back from the lib, the wrapper is # re-created, so our refcount will be 2 once again. obj = testhelper.floating_and_sunk_get_instance_list()[0] self.assertEqual(obj.__grefcount__, 2) obj.release() self.assertEqual(obj.__grefcount__, 1) def test_uninitialized_object(self): class Obj(GObject.GObject): def __init__(self): x = self.__grefcount__ super().__init__() assert x >= 0 # Accessing __grefcount__ before the object is initialized is wrong. # Ensure we get a proper exception instead of a crash. self.assertRaises(TypeError, Obj) class A(GObject.GObject): def __init__(self): super().__init__() class TestPythonReferenceCounting(unittest.TestCase): # Newly created instances should alwayshave two references: one for # the GC, and one for the bound variable in the local scope. def test_new_instance_has_two_refs(self): obj = GObject.GObject() if hasattr(sys, "getrefcount"): self.assertEqual( sys.getrefcount(obj), 2 if sys.version_info < (3, 14) else 1 ) def test_new_instance_has_two_refs_using_gobject_new(self): obj = GObject.new(GObject.GObject) if hasattr(sys, "getrefcount"): self.assertEqual( sys.getrefcount(obj), 2 if sys.version_info < (3, 14) else 1 ) def test_new_subclass_instance_has_two_refs(self): obj = A() if hasattr(sys, "getrefcount"): self.assertEqual( sys.getrefcount(obj), 2 if sys.version_info < (3, 14) else 1 ) def test_new_subclass_instance_has_two_refs_using_gobject_new(self): obj = GObject.new(A) if hasattr(sys, "getrefcount"): self.assertEqual( sys.getrefcount(obj), 2 if sys.version_info < (3, 14) else 1 ) class TestContextManagers(unittest.TestCase): class ContextTestObject(GObject.GObject): prop = GObject.Property(default=0, type=int) def on_prop_set(self, obj, prop): # Handler which tracks property changed notifications. self.tracking.append(obj.get_property(prop.name)) def setUp(self): self.tracking = [] self.obj = self.ContextTestObject() self.handler = self.obj.connect("notify::prop", self.on_prop_set) def test_freeze_notify_context(self): # Verify prop tracking list self.assertEqual(self.tracking, []) self.obj.props.prop = 1 self.assertEqual(self.tracking, [1]) self.obj.props.prop = 2 self.assertEqual(self.tracking, [1, 2]) self.assertEqual(self.obj.__grefcount__, 1) if hasattr(sys, "getrefcount"): pyref_count = sys.getrefcount(self.obj) # Using the context manager the tracking list should not be affected. # The GObject reference count should stay the same and the python # object ref-count should go up. with self.obj.freeze_notify(): self.assertEqual(self.obj.__grefcount__, 1) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1) self.obj.props.prop = 3 self.assertEqual(self.obj.props.prop, 3) self.assertEqual(self.tracking, [1, 2]) # After the context manager, the prop should have been modified, # the tracking list will be modified, and the python object ref # count goes back down. gc.collect() self.assertEqual(self.obj.props.prop, 3) self.assertEqual(self.tracking, [1, 2, 3]) self.assertEqual(self.obj.__grefcount__, 1) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(self.obj), pyref_count) def test_handler_block_context(self): # Verify prop tracking list self.assertEqual(self.tracking, []) self.obj.props.prop = 1 self.assertEqual(self.tracking, [1]) self.obj.props.prop = 2 self.assertEqual(self.tracking, [1, 2]) self.assertEqual(self.obj.__grefcount__, 1) if hasattr(sys, "getrefcount"): pyref_count = sys.getrefcount(self.obj) # Using the context manager the tracking list should not be affected. # The GObject reference count should stay the same and the python # object ref-count should go up. with self.obj.handler_block(self.handler): self.assertEqual(self.obj.__grefcount__, 1) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1) self.obj.props.prop = 3 self.assertEqual(self.obj.props.prop, 3) self.assertEqual(self.tracking, [1, 2]) # After the context manager, the prop should have been modified # the tracking list should have stayed the same and the GObject ref # count goes back down. gc.collect() self.assertEqual(self.obj.props.prop, 3) self.assertEqual(self.tracking, [1, 2]) self.assertEqual(self.obj.__grefcount__, 1) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(self.obj), pyref_count) def test_freeze_notify_context_nested(self): self.assertEqual(self.tracking, []) with self.obj.freeze_notify(): self.obj.props.prop = 1 self.assertEqual(self.tracking, []) with self.obj.freeze_notify(): self.obj.props.prop = 2 self.assertEqual(self.tracking, []) with self.obj.freeze_notify(): self.obj.props.prop = 3 self.assertEqual(self.tracking, []) self.assertEqual(self.tracking, []) self.assertEqual(self.tracking, []) # Finally after last context, the notifications should have collapsed # and the last one sent. self.assertEqual(self.tracking, [3]) def test_handler_block_context_nested(self): self.assertEqual(self.tracking, []) with self.obj.handler_block(self.handler): self.obj.props.prop = 1 self.assertEqual(self.tracking, []) with self.obj.handler_block(self.handler): self.obj.props.prop = 2 self.assertEqual(self.tracking, []) with self.obj.handler_block(self.handler): self.obj.props.prop = 3 self.assertEqual(self.tracking, []) self.assertEqual(self.tracking, []) self.assertEqual(self.tracking, []) # Finally after last context, the notifications should have collapsed # and the last one sent. self.assertEqual(self.obj.props.prop, 3) self.assertEqual(self.tracking, []) def test_freeze_notify_normal_usage_ref_counts(self): # Ensure ref counts without using methods as context managers # maintain the same count. self.assertEqual(self.obj.__grefcount__, 1) self.obj.freeze_notify() self.assertEqual(self.obj.__grefcount__, 1) self.obj.thaw_notify() self.assertEqual(self.obj.__grefcount__, 1) def test_handler_block_normal_usage_ref_counts(self): self.assertEqual(self.obj.__grefcount__, 1) self.obj.handler_block(self.handler) self.assertEqual(self.obj.__grefcount__, 1) self.obj.handler_unblock(self.handler) self.assertEqual(self.obj.__grefcount__, 1) def test_freeze_notify_context_error(self): # Test an exception occurring within a freeze context exits the context try: with self.obj.freeze_notify(): self.obj.props.prop = 1 self.assertEqual(self.tracking, []) raise ValueError("Simulation") except ValueError: pass # Verify the property set within the context called notify. self.assertEqual(self.obj.props.prop, 1) self.assertEqual(self.tracking, [1]) # Verify we are still not in a frozen context. self.obj.props.prop = 2 self.assertEqual(self.tracking, [1, 2]) def test_handler_block_context_error(self): # Test an exception occurring within a handler block exits the context try: with self.obj.handler_block(self.handler): self.obj.props.prop = 1 self.assertEqual(self.tracking, []) raise ValueError("Simulation") except ValueError: pass # Verify the property set within the context didn't call notify. self.assertEqual(self.obj.props.prop, 1) self.assertEqual(self.tracking, []) # Verify we are still not in a handler block context. self.obj.props.prop = 2 self.assertEqual(self.tracking, [2]) @unittest.skipUnless( hasattr(GObject.Binding, "unbind"), "Requires newer GLib which has g_binding_unbind" ) class TestPropertyBindings(unittest.TestCase): class TestObject(GObject.GObject): int_prop = GObject.Property(default=0, type=int) def setUp(self): self.source = self.TestObject() self.target = self.TestObject() def test_default_binding(self): binding = self.source.bind_property( "int_prop", self.target, "int_prop", GObject.BindingFlags.DEFAULT ) binding = binding # Test setting value on source gets pushed to target self.source.int_prop = 1 self.assertEqual(self.source.int_prop, 1) self.assertEqual(self.target.int_prop, 1) # Test setting value on target does not change source self.target.props.int_prop = 2 self.assertEqual(self.source.int_prop, 1) self.assertEqual(self.target.int_prop, 2) def test_call_binding(self): binding = self.source.bind_property( "int_prop", self.target, "int_prop", GObject.BindingFlags.DEFAULT ) with capture_glib_deprecation_warnings() as warn: result = binding() assert len(warn) assert result is binding def test_bidirectional_binding(self): binding = self.source.bind_property( "int_prop", self.target, "int_prop", GObject.BindingFlags.BIDIRECTIONAL ) binding = binding # Test setting value on source gets pushed to target self.source.int_prop = 1 self.assertEqual(self.source.int_prop, 1) self.assertEqual(self.target.int_prop, 1) # Test setting value on target also changes source self.target.props.int_prop = 2 self.assertEqual(self.source.int_prop, 2) self.assertEqual(self.target.int_prop, 2) def test_transform_to_only(self): def transform_to(binding, value, user_data=None): self.assertEqual(user_data, "test-data") return value * 2 binding = self.source.bind_property( "int_prop", self.target, "int_prop", GObject.BindingFlags.DEFAULT, transform_to, user_data="test-data", ) binding = binding self.source.int_prop = 1 self.assertEqual(self.source.int_prop, 1) self.assertEqual(self.target.int_prop, 2) self.target.props.int_prop = 1 self.assertEqual(self.source.int_prop, 1) self.assertEqual(self.target.int_prop, 1) def test_transform_from_only(self): def transform_from(binding, value, user_data=None): self.assertEqual(user_data, None) return value * 2 binding = self.source.bind_property( "int_prop", self.target, "int_prop", GObject.BindingFlags.BIDIRECTIONAL, transform_from=transform_from, ) binding = binding self.source.int_prop = 1 self.assertEqual(self.source.int_prop, 1) self.assertEqual(self.target.int_prop, 1) self.target.props.int_prop = 1 self.assertEqual(self.source.int_prop, 2) self.assertEqual(self.target.int_prop, 1) def test_transform_bidirectional(self): test_data = object() def transform_to(binding, value, user_data=None): self.assertEqual(user_data, test_data) return value * 2 def transform_from(binding, value, user_data=None): self.assertEqual(user_data, test_data) return value // 2 if hasattr(sys, "getrefcount"): test_data_ref_count = sys.getrefcount(test_data) transform_to_ref_count = sys.getrefcount(transform_to) transform_from_ref_count = sys.getrefcount(transform_from) # bidirectional bindings binding = self.source.bind_property( "int_prop", self.target, "int_prop", GObject.BindingFlags.BIDIRECTIONAL, transform_to, transform_from, test_data, ) binding = binding if hasattr(sys, "getrefcount"): binding_ref_count = sys.getrefcount(binding) binding_gref_count = binding.__grefcount__ self.source.int_prop = 1 self.assertEqual(self.source.int_prop, 1) self.assertEqual(self.target.int_prop, 2) self.target.props.int_prop = 4 self.assertEqual(self.source.int_prop, 2) self.assertEqual(self.target.int_prop, 4) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(binding), binding_ref_count) self.assertEqual(binding.__grefcount__, binding_gref_count) # test_data ref count increases by 2, once for each callback. if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(test_data), test_data_ref_count + 2) self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count + 1) self.assertEqual( sys.getrefcount(transform_from), transform_from_ref_count + 1 ) # Unbind should clear out the binding and its transforms binding.unbind() # Setting source or target should not change the other. self.target.int_prop = 3 self.source.int_prop = 5 self.assertEqual(self.target.int_prop, 3) self.assertEqual(self.source.int_prop, 5) if hasattr(sys, "getrefcount"): self.assertEqual(sys.getrefcount(test_data), test_data_ref_count) self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count) self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count) def test_explicit_unbind_clears_connection(self): self.assertEqual(self.source.int_prop, 0) self.assertEqual(self.target.int_prop, 0) # Test deleting binding reference removes binding. binding = self.source.bind_property("int_prop", self.target, "int_prop") self.source.int_prop = 1 self.assertEqual(self.source.int_prop, 1) self.assertEqual(self.target.int_prop, 1) # unbind should clear out the bindings self reference binding.unbind() self.assertEqual(binding.__grefcount__, 1) self.source.int_prop = 10 self.assertEqual(self.source.int_prop, 10) self.assertEqual(self.target.int_prop, 1) for i in range(10): binding.unbind() def test_reference_counts(self): self.assertEqual(self.source.__grefcount__, 1) self.assertEqual(self.target.__grefcount__, 1) # Binding ref count will be 2 do to the initial ref implicitly held by # the act of binding and the ref incurred by using __call__ to generate # a wrapper from the weak binding ref within python. binding = self.source.bind_property("int_prop", self.target, "int_prop") self.assertEqual(binding.__grefcount__, 2) # Creating a binding does not inc refs on source and target (they are weak # on the binding object itself) self.assertEqual(self.source.__grefcount__, 1) self.assertEqual(self.target.__grefcount__, 1) # Use GObject.get_property because the "props" accessor leaks. # Note property names are canonicalized. self.assertEqual(binding.get_property("source"), self.source) self.assertEqual(binding.get_property("source_property"), "int-prop") self.assertEqual(binding.get_property("target"), self.target) self.assertEqual(binding.get_property("target_property"), "int-prop") self.assertEqual(binding.get_property("flags"), GObject.BindingFlags.DEFAULT) # Delete reference to source or target and the binding will remove its own # "self reference". ref = self.source.weak_ref() del self.source gc.collect() self.assertEqual(ref(), None) self.assertEqual(binding.__grefcount__, 1) # Finally clear out the last ref held by the python wrapper ref = binding.weak_ref() del binding gc.collect() self.assertEqual(ref(), None) class TestGValue(unittest.TestCase): def test_type_constant(self): self.assertEqual(GObject.TYPE_VALUE, GObject.Value.__gtype__) self.assertEqual(GObject.type_name(GObject.TYPE_VALUE), "GValue") def test_no_type(self): value = GObject.Value() self.assertEqual(value.g_type, GObject.TYPE_INVALID) self.assertRaises(TypeError, value.set_value, 23) self.assertEqual(value.get_value(), None) def test_int(self): value = GObject.Value(GObject.TYPE_UINT) self.assertEqual(value.g_type, GObject.TYPE_UINT) value.set_value(23) self.assertEqual(value.get_value(), 23) value.set_value(42.0) self.assertEqual(value.get_value(), 42) def test_string(self): value = GObject.Value(str, "foo_bar") self.assertEqual(value.g_type, GObject.TYPE_STRING) self.assertEqual(value.get_value(), "foo_bar") def test_float(self): # python float is G_TYPE_DOUBLE value = GObject.Value(float, 23.4) self.assertEqual(value.g_type, GObject.TYPE_DOUBLE) value.set_value(1e50) self.assertAlmostEqual(value.get_value(), 1e50) value = GObject.Value(GObject.TYPE_FLOAT, 23.4) self.assertEqual(value.g_type, GObject.TYPE_FLOAT) self.assertRaises(TypeError, value.set_value, "string") self.assertRaises(OverflowError, value.set_value, 1e50) def test_float_inf_nan(self): nan = float("nan") for type_ in [GObject.TYPE_FLOAT, GObject.TYPE_DOUBLE]: for x in [float("inf"), float("-inf"), nan]: value = GObject.Value(type_, x) # assertEqual() is False for (nan, nan) if x is nan: self.assertEqual(str(value.get_value()), "nan") else: self.assertEqual(value.get_value(), x) def test_enum(self): value = GObject.Value(Gio.FileType, Gio.FileType.DIRECTORY) self.assertEqual(value.get_value(), Gio.FileType.DIRECTORY) def test_flags(self): value = GObject.Value(Gio.FileCopyFlags, Gio.FileCopyFlags.OVERWRITE) self.assertEqual(value.get_value(), Gio.FileCopyFlags.OVERWRITE) def test_object(self): class TestObject(GObject.Object): pass obj = TestObject() value = GObject.Value(GObject.TYPE_OBJECT, obj) self.assertEqual(value.get_value(), obj) def test_dispose(self): class TestObject(GObject.Object): def __init__(self): super().__init__() self.dispose_invoked = False def do_dispose(self): self.dispose_invoked = True super().do_dispose() obj = TestObject() obj.run_dispose() assert obj.dispose_invoked def test_dispose_with_python_base_class(self): class TestBaseObject(GObject.Object): def __init__(self): super().__init__() self.dispose_invoked_base = False def do_dispose(self): self.dispose_invoked_base = True super().do_dispose() class TestObject(TestBaseObject): def __init__(self): super().__init__() self.dispose_invoked = False def do_dispose(self): self.dispose_invoked = True super().do_dispose() obj = TestObject() obj.run_dispose() assert obj.dispose_invoked_base assert obj.dispose_invoked def test_value_array(self): value = GObject.Value(GObject.ValueArray) self.assertEqual(value.g_type, GObject.type_from_name("GValueArray")) value.set_value([32, "foo_bar", 0.3]) self.assertEqual(value.get_value(), [32, "foo_bar", 0.3]) def test_value_array_from_gvalue_list(self): value = GObject.Value( GObject.ValueArray, [ GObject.Value(GObject.TYPE_UINT, 0xFFFFFFFF), GObject.Value(GObject.TYPE_STRING, "foo_bar"), ], ) self.assertEqual(value.g_type, GObject.type_from_name("GValueArray")) self.assertEqual(value.get_value(), [0xFFFFFFFF, "foo_bar"]) self.assertEqual( testhelper.value_array_get_nth_type(value, 0), GObject.TYPE_UINT ) self.assertEqual( testhelper.value_array_get_nth_type(value, 1), GObject.TYPE_STRING ) def test_value_array_append_gvalue(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) arr = GObject.ValueArray.new(0) arr.append(GObject.Value(GObject.TYPE_UINT, 0xFFFFFFFF)) arr.append(GObject.Value(GObject.TYPE_STRING, "foo_bar")) self.assertEqual(arr.get_nth(0), 0xFFFFFFFF) self.assertEqual(arr.get_nth(1), "foo_bar") self.assertEqual( testhelper.value_array_get_nth_type(arr, 0), GObject.TYPE_UINT ) self.assertEqual( testhelper.value_array_get_nth_type(arr, 1), GObject.TYPE_STRING ) def test_gerror_boxing(self): error = GLib.Error("test message", domain="mydomain", code=42) value = GObject.Value(GLib.Error, error) self.assertEqual(value.g_type, GObject.type_from_name("GError")) unboxed = value.get_value() self.assertEqual(unboxed.message, error.message) self.assertEqual(unboxed.domain, error.domain) self.assertEqual(unboxed.code, error.code) def test_gerror_novalue(self): GLib.Error("test message", domain="mydomain", code=42) value = GObject.Value(GLib.Error) self.assertEqual(value.g_type, GObject.type_from_name("GError")) self.assertEqual(value.get_value(), None) def test_list_properties(): def find_param(props, name): for param in props: if param.name == name: return param return None list_props = GObject.list_properties props = list_props(Gio.Action) param = find_param(props, "enabled") assert param assert param.value_type == GObject.TYPE_BOOLEAN assert list_props("GAction") == list_props(Gio.Action) assert list_props(Gio.Action.__gtype__) == list_props(Gio.Action) props = list_props(Gio.SimpleAction) assert find_param(props, "enabled") def names(props): return [p.name for p in props] assert set(names(list_props(Gio.Action))) <= set( names(list_props(Gio.SimpleAction)) ) props = list_props(Gio.FileIcon) param = find_param(props, "file") assert param assert param.value_type == Gio.File.__gtype__ assert list_props("GFileIcon") == list_props(Gio.FileIcon) assert list_props(Gio.FileIcon.__gtype__) == list_props(Gio.FileIcon) assert list_props(Gio.FileIcon(file=Gio.File.new_for_path("."))) == list_props( Gio.FileIcon ) for obj in [Gio.ActionEntry, Gio.DBusError, 0, object()]: with pytest.raises(TypeError): list_props(obj) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_gtk_template.py0000664000000000000000000004624515074673150017614 0ustar00rootrootimport tempfile import os import pytest Gtk = pytest.importorskip("gi.repository.Gtk") GLib = pytest.importorskip("gi.repository.GLib") GObject = pytest.importorskip("gi.repository.GObject") Gio = pytest.importorskip("gi.repository.Gio") from .helper import capture_exceptions GTK4 = Gtk._version == "4.0" def new_gtype_name(_count=[0]): _count[0] += 1 return f"GtkTemplateTest{_count[0]:d}" def ensure_resource_registered(): resource_path = "/org/gnome/pygobject/test/a.ui" def is_registered(path): try: Gio.resources_get_info(path, Gio.ResourceLookupFlags.NONE) except GLib.Error: return False return True if is_registered(resource_path): return resource_path gresource_data = ( b"GVariant\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00" b"\xc8\x00\x00\x00\x00\x00\x00(\x06\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00" b"\x06\x00\x00\x00KP\x90\x0b\x03\x00\x00\x00\xc8\x00\x00\x00" b"\x04\x00L\x00\xcc\x00\x00\x00\xd0\x00\x00\x00\xb0\xb7$0" b"\x00\x00\x00\x00\xd0\x00\x00\x00\x06\x00L\x00\xd8\x00\x00\x00" b"\xdc\x00\x00\x00f\xc30\xd1\x01\x00\x00\x00\xdc\x00\x00\x00" b"\n\x00L\x00\xe8\x00\x00\x00\xec\x00\x00\x00\xd4\xb5\x02\x00" b"\xff\xff\xff\xff\xec\x00\x00\x00\x01\x00L\x00\xf0\x00\x00\x00" b"\xf4\x00\x00\x005H}\xe3\x02\x00\x00\x00\xf4\x00\x00\x00" b"\x05\x00L\x00\xfc\x00\x00\x00\x00\x01\x00\x00\xa2^\xd6t" b"\x04\x00\x00\x00\x00\x01\x00\x00\x04\x00v\x00\x08\x01\x00\x00" b"\xa5\x01\x00\x00org/\x01\x00\x00\x00gnome/\x00\x00\x02\x00\x00\x00" b"pygobject/\x00\x00\x04\x00\x00\x00/\x00\x00\x00\x00\x00\x00\x00" b"test/\x00\x00\x00\x05\x00\x00\x00a.ui\x00\x00\x00\x00" b'\x8d\x00\x00\x00\x00\x00\x00\x00\n \n\n\x00\x00(uuay)' ) resource = Gio.Resource.new_from_data(GLib.Bytes.new(gresource_data)) Gio.resources_register(resource) assert is_registered(resource_path) return resource_path def test_allow_init_template_call(): type_name = new_gtype_name() xml = f"""\ """ @Gtk.Template.from_string(xml) class Foo(Gtk.Box): __gtype_name__ = type_name def __init__(self): super().__init__() self.init_template() # Stop current pygobject from handling the initialisation del Foo.__dontuse_ginstance_init__ Foo() def test_init_template_second_instance(): type_name = new_gtype_name() xml = f"""\ """ @Gtk.Template.from_string(xml) class Foo(Gtk.Box): __gtype_name__ = type_name label = Gtk.Template.Child("label") def __init__(self): super().__init__() self.init_template() # Stop current pygobject from handling the initialisation del Foo.__dontuse_ginstance_init__ foo = Foo() assert isinstance(foo.label, Gtk.Label) foo2 = Foo() assert isinstance(foo2.label, Gtk.Label) def test_main_example(): type_name = new_gtype_name() example_xml = f"""\ """ @Gtk.Template.from_string(example_xml) class Foo(Gtk.Box): __gtype_name__ = type_name def __init__(self): super().__init__() self.callback_hello = [] self.callback_hello_after = [] self.callback_goodbye = [] self.callback_goodbye_after = [] @Gtk.Template.Callback("hello_button_clicked") def _hello_button_clicked(self, *args): self.callback_hello.append(args) @Gtk.Template.Callback("hello_button_clicked_after") def _hello_after(self, *args): self.callback_hello_after.append(args) _hello_button = Gtk.Template.Child("hello_button") goodbye_button = Gtk.Template.Child() @Gtk.Template.Callback("goodbye_button_clicked") def _goodbye_button_clicked(self, *args): self.callback_goodbye.append(args) @Gtk.Template.Callback("goodbye_button_clicked_after") def _goodbye_after(self, *args): self.callback_goodbye_after.append(args) w = Foo() assert w.__gtype__.name == type_name assert w.props.orientation == Gtk.Orientation.HORIZONTAL assert w.props.spacing == 4 assert isinstance(w._hello_button, Gtk.Button) assert w._hello_button.props.label == "Hello World" assert isinstance(w.goodbye_button, Gtk.Button) assert w.goodbye_button.props.label == "Goodbye World" assert w.callback_hello == [] w._hello_button.emit("clicked") assert w.callback_hello == [(w,)] assert w.callback_hello_after == [(w,)] assert w.callback_goodbye == [] w.goodbye_button.emit("clicked") assert w.callback_goodbye == [(w.goodbye_button,)] assert w.callback_goodbye_after == [(w.goodbye_button,)] def test_duplicate_handler(): type_name = new_gtype_name() xml = f"""\ """ class Foo(Gtk.Box): __gtype_name__ = type_name @Gtk.Template.Callback("hello_button_clicked") def _hello_button_clicked(self, *args): pass @Gtk.Template.Callback() def hello_button_clicked(self, *args): pass with pytest.raises(RuntimeError, match=r".*hello_button_clicked.*"): Gtk.Template.from_string(xml)(Foo) def test_duplicate_child(): type_name = new_gtype_name() xml = f"""\ """ class Foo(Gtk.Box): __gtype_name__ = type_name foo = Gtk.Template.Child("hello_button") hello_button = Gtk.Template.Child() with pytest.raises(RuntimeError, match=r".*hello_button.*"): Gtk.Template.from_string(xml)(Foo) def test_nonexist_handler(): type_name = new_gtype_name() xml = f"""\ """ @Gtk.Template.from_string(xml) class Foo(Gtk.Box): __gtype_name__ = type_name @Gtk.Template.Callback("nonexit") def foo(self, *args): pass with capture_exceptions() as exc_info: Foo() assert "nonexit" in str(exc_info[0].value) assert exc_info[0].type is RuntimeError def test_missing_handler_callback(): type_name = new_gtype_name() xml = f"""\ """ class Foo(Gtk.Box): __gtype_name__ = type_name Gtk.Template.from_string(xml)(Foo)() def test_handler_swapped_not_supported(): type_name = new_gtype_name() xml = f"""\ """ @Gtk.Template.from_string(xml) class Foo(Gtk.Box): __gtype_name__ = type_name hello_button = Gtk.Template.Child() @Gtk.Template.Callback("hello_button_clicked") def foo(self, *args): pass with capture_exceptions() as exc_info: Foo() assert "ConnectFlags.SWAPPED" in str(exc_info[0].value) def test_handler_class_staticmethod(): type_name = new_gtype_name() xml = f"""\ """ signal_args_class = [] signal_args_static = [] @Gtk.Template.from_string(xml) class Foo(Gtk.Box): __gtype_name__ = type_name hello_button = Gtk.Template.Child() @Gtk.Template.Callback("clicked_class") @classmethod def cb1(*args): signal_args_class.append(args) @Gtk.Template.Callback("clicked_static") @staticmethod def cb2(*args): signal_args_static.append(args) foo = Foo() foo.hello_button.emit("clicked") assert signal_args_class == [(Foo, foo.hello_button)] assert signal_args_static == [(foo.hello_button,)] @pytest.mark.skipif(Gtk._version == "4.0", reason="errors out first with gtk4") def test_check_decorated_class(): NonWidget = type("Foo", (object,), {}) with pytest.raises(TypeError, match=r".*on Widgets.*"): Gtk.Template.from_string("")(NonWidget) Widget = type("Foo", (Gtk.Widget,), {"__gtype_name__": new_gtype_name()}) with pytest.raises(TypeError, match=r".*Cannot nest.*"): Gtk.Template.from_string("")(Gtk.Template.from_string("")(Widget)) Widget = type("Foo", (Gtk.Widget,), {}) with pytest.raises(TypeError, match=r".*__gtype_name__.*"): Gtk.Template.from_string("")(Widget) with pytest.raises(TypeError, match=r".*on Widgets.*"): Gtk.Template.from_string("")(object()) @pytest.mark.skipif(Gtk._version == "4.0", reason="errors out first with gtk4") def test_subclass_fail(): @Gtk.Template.from_string("") class Base(Gtk.Widget): __gtype_name__ = new_gtype_name() with capture_exceptions() as exc_info: type("Sub", (Base,), {})() assert "not allowed at this time" in str(exc_info[0].value) assert exc_info[0].type is TypeError def test_from_file(): fd, name = tempfile.mkstemp() try: os.close(fd) type_name = new_gtype_name() with open(name, "wb") as h: h.write( f"""\ """.encode() ) @Gtk.Template.from_file(name) class Foo(Gtk.Box): __gtype_name__ = type_name foo = Foo() assert foo.props.spacing == 42 finally: os.remove(name) def test_property_override(): type_name = new_gtype_name() xml = f"""\ """ @Gtk.Template.from_string(xml) class Foo(Gtk.Box): __gtype_name__ = type_name foo = Foo() assert foo.props.spacing == 42 foo = Foo(spacing=124) assert foo.props.spacing == 124 def test_from_file_non_exist(): dirname = tempfile.mkdtemp() try: path = os.path.join(dirname, "noexist") Widget = type("Foo", (Gtk.Widget,), {"__gtype_name__": new_gtype_name()}) with pytest.raises(GLib.Error, match=r".*No such file.*"): Gtk.Template.from_file(path)(Widget) finally: os.rmdir(dirname) def test_from_string_bytes(): type_name = new_gtype_name() xml = f"""\ """.encode() @Gtk.Template.from_string(xml) class Foo(Gtk.Box): __gtype_name__ = type_name foo = Foo() assert foo.props.spacing == 42 def test_from_resource(): resource_path = ensure_resource_registered() @Gtk.Template.from_resource(resource_path) class Foo(Gtk.Box): __gtype_name__ = "GtkTemplateTestResource" foo = Foo() assert foo.props.spacing == 42 def test_from_resource_non_exit(): Widget = type("Foo", (Gtk.Widget,), {"__gtype_name__": new_gtype_name()}) with pytest.raises(GLib.Error, match=r".*/or/gnome/pygobject/noexit.*"): Gtk.Template.from_resource("/or/gnome/pygobject/noexit")(Widget) def test_constructors(): with pytest.raises(TypeError): Gtk.Template() with pytest.raises(TypeError): Gtk.Template(foo=1) Gtk.Template(filename="foo") Gtk.Template(resource_path="foo") Gtk.Template(string="foo") with pytest.raises(TypeError): Gtk.Template(filename="foo", resource_path="bar") with pytest.raises(TypeError): Gtk.Template(filename="foo", nope="bar") Gtk.Template.from_string("bla") Gtk.Template.from_resource("foo") Gtk.Template.from_file("foo") def test_child_construct(): Gtk.Template.Child() Gtk.Template.Child("name") with pytest.raises(TypeError): Gtk.Template.Child("name", True) Gtk.Template.Child("name", internal=True) with pytest.raises(TypeError): Gtk.Template.Child("name", internal=True, something=False) def test_internal_child(): main_type_name = new_gtype_name() xml = f"""\ """ @Gtk.Template.from_string(xml) class MainThing(Gtk.Box): __gtype_name__ = main_type_name somechild = Gtk.Template.Child(internal=True) thing = MainThing() assert thing.somechild.props.margin_top == 42 other_type_name = new_gtype_name() xml = f"""\ """ @Gtk.Template.from_string(xml) class OtherThing(Gtk.Box): __gtype_name__ = other_type_name other = OtherThing() child = other.get_children()[0] if not GTK4 else other.get_first_child() assert isinstance(child, MainThing) child = child.get_children()[0] if not GTK4 else child.get_first_child() assert isinstance(child, Gtk.Box) assert child.props.margin_top == 24 child = child.get_children()[0] if not GTK4 else child.get_first_child() assert isinstance(child, Gtk.Label) assert child.props.label == "foo" def test_template_hierarchy(): testlabel = """ """ @Gtk.Template(string=testlabel) class TestLabel(Gtk.Label): __gtype_name__ = "TestLabel" def __init__(self): super().__init__() self.props.label = "TestLabel" testbox = """ """ @Gtk.Template(string=testbox) class TestBox(Gtk.Box): __gtype_name__ = "TestBox" _testlabel = Gtk.Template.Child() def __init__(self): super().__init__() assert isinstance(self._testlabel, TestLabel) window = """ """ @Gtk.Template(string=window) class MyWindow(Gtk.Window): __gtype_name__ = "MyWindow" _testbox = Gtk.Template.Child() _testlabel = Gtk.Template.Child() def __init__(self): super().__init__() assert isinstance(self._testbox, TestBox) assert isinstance(self._testlabel, TestLabel) children = self._testbox.get_children() if not GTK4 else list(self._testbox) assert len(children) == 2 win = MyWindow() assert isinstance(win, MyWindow) def test_multiple_init_template_calls(): xml = """ """ @Gtk.Template(string=xml) class MyBox(Gtk.Box): __gtype_name__ = "MyBox" _label = Gtk.Template.Child() def __init__(self): super().__init__() self._label.props.label = "awesome label" my_box = MyBox() assert isinstance(my_box, MyBox) children = my_box.get_children() if not GTK4 else list(my_box) assert len(children) == 1 my_box.init_template() assert isinstance(my_box, MyBox) children = my_box.get_children() if not GTK4 else list(my_box) assert len(children) == 1 def test_python_class_hierarchy(): xml = """ """ class ParentBox(Gtk.Box): __gtype_name__ = "ParentBox" def __init__(self): super().__init__() @Gtk.Template(string=xml) class ChildBox(ParentBox): __gtype_name__ = "ChildBox" _label = Gtk.Template.Child() def __init__(self): super().__init__() childBox = ChildBox() assert isinstance(childBox, ChildBox) children = childBox.get_children() if not GTK4 else list(childBox) assert len(children) == 1 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_gtype.py0000664000000000000000000001055315074673150016255 0ustar00rootrootimport unittest from gi.repository import GObject from gi.repository import GIMarshallingTests class CustomBase(GObject.GObject): pass class CustomChild(CustomBase, GIMarshallingTests.Interface): pass class TestTypeModuleLevelFunctions(unittest.TestCase): def test_type_name(self): self.assertEqual(GObject.type_name(GObject.TYPE_NONE), "void") self.assertEqual(GObject.type_name(GObject.TYPE_OBJECT), "GObject") self.assertEqual(GObject.type_name(GObject.TYPE_PYOBJECT), "PyObject") def test_type_from_name(self): # A complete test is not needed here since the TYPE_* defines are created # using this method. self.assertRaises(RuntimeError, GObject.type_from_name, "!NOT_A_REAL_TYPE!") self.assertEqual(GObject.type_from_name("GObject"), GObject.TYPE_OBJECT) self.assertEqual(GObject.type_from_name("GObject"), GObject.GObject.__gtype__) def test_type_is_a(self): self.assertTrue(GObject.type_is_a(CustomBase, GObject.TYPE_OBJECT)) self.assertTrue(GObject.type_is_a(CustomChild, CustomBase)) self.assertTrue(GObject.type_is_a(CustomBase, GObject.GObject)) self.assertTrue(GObject.type_is_a(CustomBase.__gtype__, GObject.TYPE_OBJECT)) self.assertFalse(GObject.type_is_a(GObject.TYPE_OBJECT, CustomBase)) self.assertFalse(GObject.type_is_a(CustomBase, int)) # invalid type self.assertRaises(TypeError, GObject.type_is_a, CustomBase, 1) self.assertRaises(TypeError, GObject.type_is_a, 2, GObject.TYPE_OBJECT) self.assertRaises(TypeError, GObject.type_is_a, 1, 2) def test_type_children(self): self.assertEqual(GObject.type_children(CustomBase), [CustomChild.__gtype__]) self.assertEqual(len(GObject.type_children(CustomChild)), 0) def test_type_interfaces(self): self.assertEqual(len(GObject.type_interfaces(CustomBase)), 0) self.assertEqual(len(GObject.type_interfaces(CustomChild)), 1) self.assertEqual( GObject.type_interfaces(CustomChild), [GIMarshallingTests.Interface.__gtype__], ) def test_type_parent(self): self.assertEqual(GObject.type_parent(CustomChild), CustomBase.__gtype__) self.assertEqual(GObject.type_parent(CustomBase), GObject.TYPE_OBJECT) self.assertRaises(RuntimeError, GObject.type_parent, GObject.GObject) def test_gtype_has_value_table(): assert CustomBase.__gtype__.has_value_table() assert not GIMarshallingTests.Interface.__gtype__.has_value_table() assert CustomChild.__gtype__.has_value_table() def test_gtype_is_abstract(): assert not CustomBase.__gtype__.is_abstract() assert not GIMarshallingTests.Interface.__gtype__.is_abstract() assert not CustomChild.__gtype__.is_abstract() def test_gtype_is_classed(): assert CustomBase.__gtype__.is_classed() assert not GIMarshallingTests.Interface.__gtype__.is_classed() assert CustomChild.__gtype__.is_classed() def test_gtype_is_deep_derivable(): assert CustomBase.__gtype__.is_deep_derivable() assert not GIMarshallingTests.Interface.__gtype__.is_deep_derivable() assert CustomChild.__gtype__.is_deep_derivable() def test_gtype_is_derivable(): assert CustomBase.__gtype__.is_derivable() assert GIMarshallingTests.Interface.__gtype__.is_derivable() assert CustomChild.__gtype__.is_derivable() def test_gtype_is_value_abstract(): assert not CustomBase.__gtype__.is_value_abstract() assert not GIMarshallingTests.Interface.__gtype__.is_value_abstract() assert not CustomChild.__gtype__.is_value_abstract() def test_gtype_is_value_type(): assert CustomBase.__gtype__.is_value_type() assert not GIMarshallingTests.Interface.__gtype__.is_value_type() assert CustomChild.__gtype__.is_value_type() def test_gtype_children(): assert CustomBase.__gtype__.children == [CustomChild.__gtype__] assert GIMarshallingTests.Interface.__gtype__.children == [] assert CustomChild.__gtype__.children == [] def test_gtype_depth(): assert CustomBase.__gtype__.depth == 2 assert GIMarshallingTests.Interface.__gtype__.depth == 2 assert CustomChild.__gtype__.depth == 3 def test_gtype_interfaces(): assert CustomBase.__gtype__.interfaces == [] assert GIMarshallingTests.Interface.__gtype__.interfaces == [] assert CustomChild.__gtype__.interfaces == [GIMarshallingTests.Interface.__gtype__] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_import_machinery.py0000664000000000000000000001232615074673150020476 0ustar00rootrootimport sys import unittest import gi.overrides import gi.module import gi.importer from gi.repository import Regress class TestOverrides(unittest.TestCase): def test_non_gi(self): class MyClass: pass try: gi.overrides.override(MyClass) self.fail("unexpected success of overriding non-GI class") except TypeError as e: self.assertTrue("Can not override a type MyClass" in str(e)) def test_separate_path(self): # Regress override is in tests/gi/overrides, separate from gi/overrides # https://bugzilla.gnome.org/show_bug.cgi?id=680913 self.assertEqual(Regress.REGRESS_OVERRIDE, 42) def test_load_overrides(self): mod = gi.module.get_introspection_module("GIMarshallingTests") mod_override = gi.overrides.load_overrides(mod) self.assertTrue(mod_override is not mod) self.assertTrue(mod_override._introspection_module is mod) self.assertEqual(mod_override.OVERRIDES_CONSTANT, 7) self.assertEqual(mod.OVERRIDES_CONSTANT, 42) def test_load_no_overrides(self): mod_key = "gi.overrides.GIMarshallingTests" had_mod = mod_key in sys.modules old_mod = sys.modules.get(mod_key) try: # this makes override import fail sys.modules[mod_key] = None mod = gi.module.get_introspection_module("GIMarshallingTests") mod_override = gi.overrides.load_overrides(mod) self.assertTrue(mod_override is mod) finally: del sys.modules[mod_key] if had_mod: sys.modules[mod_key] = old_mod class TestModule(unittest.TestCase): # Tests for gi.module def test_get_introspection_module_caching(self): # This test attempts to minimize side effects by # using a DynamicModule directly instead of going though: # from gi.repository import Foo # Clear out introspection module cache before running this test. old_modules = gi.module._introspection_modules gi.module._introspection_modules = {} mod_name = "GIMarshallingTests" mod1 = gi.module.get_introspection_module(mod_name) mod2 = gi.module.get_introspection_module(mod_name) self.assertTrue(mod1 is mod2) # Restore the previous cache gi.module._introspection_modules = old_modules def test_module_dependency_loading(self): # Difficult to because this generally need to run in isolation to make # sure GIMarshallingTests has not yet been loaded. But we can do this with: # make check TEST_NAMES=test_import_machinery.TestModule.test_module_dependency_loading if "gi.repository.Gio" in sys.modules: return from gi.repository import GIMarshallingTests GIMarshallingTests self.assertIn("gi.repository.Gio", sys.modules) self.assertIn("gi.repository.GIMarshallingTests", sys.modules) def test_static_binding_protection(self): # Importing old static bindings once gi has been imported should not # crash but instead give back a dummy module which produces RuntimeErrors # on access. with self.assertRaises(AttributeError): import gobject gobject.anything with self.assertRaises(AttributeError): import glib glib.anything with self.assertRaises(AttributeError): import gio gio.anything with self.assertRaises(AttributeError): import gtk gtk.anything with self.assertRaises(AttributeError): import gtk.gdk gtk.gdk.anything class TestImporter(unittest.TestCase): def test_invalid_repository_module_name(self): with self.assertRaises(ImportError) as context: from gi.repository import InvalidGObjectRepositoryModuleName InvalidGObjectRepositoryModuleName exception_string = str(context.exception) self.assertTrue("InvalidGObjectRepositoryModuleName" in exception_string) self.assertTrue("introspection typelib" in exception_string) def test_require_version_warning(self): check = gi.importer._check_require_version # make sure it doesn't fail at least with check("GLib", 1): from gi.repository import GLib GLib # make sure the exception propagates with ( self.assertRaises(ImportError), check("InvalidGObjectRepositoryModuleName", 1), ): from gi.repository import InvalidGObjectRepositoryModuleName InvalidGObjectRepositoryModuleName def test_require_version_versiontype(self): import gi with self.assertRaises(ValueError): gi.require_version("GLib", 2.0) with self.assertRaises(ValueError): gi.require_version("GLib", b"2.0") def test_require_versions(self): import gi gi.require_versions({"GLib": "2.0", "Gio": "2.0", "GObject": "2.0"}) from gi.repository import GLib GLib def test_get_import_stacklevel(self): gi.importer.get_import_stacklevel(import_hook=True) gi.importer.get_import_stacklevel(import_hook=False) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_interface.py0000664000000000000000000000203415074673150017060 0ustar00rootrootimport unittest from gi.repository import GObject import testhelper GUnknown = GObject.type_from_name("TestUnknown") Unknown = GUnknown.pytype class MyUnknown(Unknown, testhelper.Interface): some_property = GObject.Property(type=str) def __init__(self): Unknown.__init__(self) self.called = False def do_iface_method(self): self.called = True Unknown.do_iface_method(self) GObject.type_register(MyUnknown) class MyObject(GObject.GObject, testhelper.Interface): some_property = GObject.Property(type=str) def __init__(self): GObject.GObject.__init__(self) self.called = False def do_iface_method(self): self.called = True GObject.type_register(MyObject) class TestIfaceImpl(unittest.TestCase): def test_reimplement_interface(self): m = MyUnknown() m.iface_method() self.assertEqual(m.called, True) def test_implement_interface(self): m = MyObject() m.iface_method() self.assertEqual(m.called, True) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_internal_api.py0000664000000000000000000000776615074673150017606 0ustar00rootrootimport unittest import pytest from gi.repository import GLib, GObject import testhelper class PyGObject(GObject.GObject): __gtype_name__ = "PyGObject" __gproperties__ = { "label": ( GObject.TYPE_STRING, "label property", "the label of the object", "default", GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE, ), } def __init__(self): self._props = {} GObject.GObject.__init__(self) self.set_property("label", "hello") def do_set_property(self, name, value): self._props[name] = value def do_get_property(self, name): return self._props[name] def test_parse_constructor_args(): assert testhelper.test_parse_constructor_args("foo") == 1 class TestObject(unittest.TestCase): def test_create_ctor(self): o = PyGObject() self.assertTrue(isinstance(o, GObject.Object)) self.assertTrue(isinstance(o, PyGObject)) # has expected property self.assertEqual(o.props.label, "hello") o.props.label = "goodbye" self.assertEqual(o.props.label, "goodbye") self.assertRaises(AttributeError, getattr, o.props, "nosuchprop") def test_pyobject_new_test_type(self): o = testhelper.create_test_type() self.assertTrue(isinstance(o, PyGObject)) # has expected property self.assertEqual(o.props.label, "hello") o.props.label = "goodbye" self.assertEqual(o.props.label, "goodbye") self.assertRaises(AttributeError, getattr, o.props, "nosuchprop") def test_new_refcount(self): # TODO: justify why this should be 2 self.assertEqual(testhelper.test_g_object_new(), 2) class TestGValueConversion(unittest.TestCase): def test_int(self): self.assertEqual(testhelper.test_value(0), 0) self.assertEqual(testhelper.test_value(5), 5) self.assertEqual(testhelper.test_value(-5), -5) self.assertEqual(testhelper.test_value(GLib.MAXINT32), GLib.MAXINT32) self.assertEqual(testhelper.test_value(GLib.MININT32), GLib.MININT32) def test_str(self): self.assertEqual(testhelper.test_value("hello"), "hello") def test_int_array(self): self.assertEqual(testhelper.test_value_array([]), []) self.assertEqual(testhelper.test_value_array([0]), [0]) ar = list(range(100)) self.assertEqual(testhelper.test_value_array(ar), ar) def test_str_array(self): self.assertEqual(testhelper.test_value_array([]), []) self.assertEqual(testhelper.test_value_array(["a"]), ["a"]) ar = ("aa " * 1000).split() self.assertEqual(testhelper.test_value_array(ar), ar) class TestErrors(unittest.TestCase): def test_gerror(self): def callable_(): return GLib.file_get_contents("/nonexisting ") self.assertRaises(GLib.GError, testhelper.test_gerror_exception, callable_) def test_no_gerror(self): def callable_(): return GLib.file_get_contents(__file__) self.assertEqual(testhelper.test_gerror_exception(callable_), None) def test_to_unichar_conv(): assert testhelper.test_to_unichar_conv("A") == 65 assert testhelper.test_to_unichar_conv("Ä") == 196 with pytest.raises(TypeError): assert testhelper.test_to_unichar_conv(b"\x65") with pytest.raises(TypeError): testhelper.test_to_unichar_conv(object()) with pytest.raises(TypeError): testhelper.test_to_unichar_conv("AA") def test_constant_strip_prefix(): assert testhelper.constant_strip_prefix("foo", "bar") == "foo" assert testhelper.constant_strip_prefix("foo", "f") == "oo" assert testhelper.constant_strip_prefix("foo", "f") == "oo" assert testhelper.constant_strip_prefix("ha2foo", "ha") == "a2foo" assert testhelper.constant_strip_prefix("2foo", "ha") == "2foo" assert testhelper.constant_strip_prefix("bla_foo", "bla") == "_foo" def test_state_ensure_release(): testhelper.test_state_ensure_release() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_iochannel.py0000664000000000000000000003757215074673150017077 0ustar00rootrootimport os import unittest import tempfile import os.path import shutil import warnings try: import fcntl except ImportError: fcntl = None from gi.repository import GLib from gi import PyGIDeprecationWarning class IOChannel(unittest.TestCase): def setUp(self): self.workdir = tempfile.mkdtemp() self.testutf8 = os.path.join(self.workdir, "testutf8.txt") with open(self.testutf8, "wb") as f: f.write( """hello ♥ world second line À demain!""".encode() ) self.testlatin1 = os.path.join(self.workdir, "testlatin1.txt") with open(self.testlatin1, "wb") as f: f.write(b"""hell\xf8 world second line \xc0 demain!""") self.testout = os.path.join(self.workdir, "testout.txt") def tearDown(self): shutil.rmtree(self.workdir) def test_file_readline_utf8(self): ch = GLib.IOChannel(filename=self.testutf8) self.assertEqual(ch.get_encoding(), "UTF-8") self.assertTrue(ch.get_close_on_unref()) self.assertEqual(ch.readline(), "hello ♥ world\n") self.assertEqual(ch.get_buffer_condition(), GLib.IOCondition.IN) self.assertEqual(ch.readline(), "second line\n") self.assertEqual(ch.readline(), "\n") self.assertEqual(ch.readline(), "À demain!") self.assertEqual(ch.get_buffer_condition(), 0) self.assertEqual(ch.readline(), "") ch.shutdown(True) def test_file_readline_latin1(self): ch = GLib.IOChannel(filename=self.testlatin1, mode="r") ch.set_encoding("latin1") self.assertEqual(ch.get_encoding(), "latin1") self.assertEqual(ch.readline(), "hellø world\n") self.assertEqual(ch.readline(), "second line\n") self.assertEqual(ch.readline(), "\n") self.assertEqual(ch.readline(), "À demain!") ch.shutdown(True) def test_file_iter(self): items = [] ch = GLib.IOChannel(filename=self.testutf8) for item in ch: items.append(item) # noqa: PERF402 self.assertEqual(len(items), 4) self.assertEqual(items[0], "hello ♥ world\n") ch.shutdown(True) def test_file_readlines(self): ch = GLib.IOChannel(filename=self.testutf8) lines = ch.readlines() # Note, this really ought to be 4, but the static bindings add an extra # empty one self.assertGreaterEqual(len(lines), 4) self.assertLessEqual(len(lines), 5) self.assertEqual(lines[0], "hello ♥ world\n") self.assertEqual(lines[3], "À demain!") if len(lines) == 4: self.assertEqual(lines[4], "") def test_file_read(self): ch = GLib.IOChannel(filename=self.testutf8) with open(self.testutf8, "rb") as f: self.assertEqual(ch.read(), f.read()) ch = GLib.IOChannel(filename=self.testutf8) with open(self.testutf8, "rb") as f: self.assertEqual(ch.read(10), f.read(10)) ch = GLib.IOChannel(filename=self.testutf8) with open(self.testutf8, "rb") as f: self.assertEqual(ch.read(max_count=15), f.read(15)) def test_file_read_chars(self): ch = GLib.IOChannel(filename=self.testutf8) with open(self.testutf8, "rb") as f: self.assertEqual(ch.read_chars(), f.read()) def test_seek(self): ch = GLib.IOChannel(filename=self.testutf8) ch.seek(2) self.assertEqual(ch.read(3), b"llo") ch.seek(2, 0) # SEEK_SET self.assertEqual(ch.read(3), b"llo") ch.seek(1, 1) # SEEK_CUR, skip the space self.assertEqual(ch.read(3), b"\xe2\x99\xa5") ch.seek(2, 2) # SEEK_END # FIXME: does not work currently # self.assertEqual(ch.read(2), b'n!') # invalid whence value self.assertRaises(ValueError, ch.seek, 0, 3) ch.shutdown(True) def test_file_write(self): ch = GLib.IOChannel(filename=self.testout, mode="w") ch.set_encoding("latin1") ch.write("hellø world\n") ch.shutdown(True) ch = GLib.IOChannel(filename=self.testout, mode="a") ch.set_encoding("latin1") ch.write("À demain!") ch.shutdown(True) with open(self.testout, "rb") as f: self.assertEqual(f.read().decode("latin1"), "hellø world\nÀ demain!") def test_file_writelines(self): ch = GLib.IOChannel(filename=self.testout, mode="w") ch.writelines(["foo", "bar\n", "baz\n", "end"]) ch.shutdown(True) with open(self.testout) as f: self.assertEqual(f.read(), "foobar\nbaz\nend") def test_buffering(self): writer = GLib.IOChannel(filename=self.testout, mode="w") writer.set_encoding(None) self.assertTrue(writer.get_buffered()) self.assertGreater(writer.get_buffer_size(), 10) reader = GLib.IOChannel(filename=self.testout, mode="r") # does not get written immediately on buffering writer.write("abc") self.assertEqual(reader.read(), b"") writer.flush() self.assertEqual(reader.read(), b"abc") # does get written immediately without buffering writer.set_buffered(False) writer.write("def") self.assertEqual(reader.read(), b"def") # writes after buffer overflow writer.set_buffer_size(10) writer.write("0123456789012") self.assertTrue(reader.read().startswith(b"012")) writer.flush() reader.read() # ignore bits written after flushing # closing flushes writer.set_buffered(True) writer.write("ghi") writer.shutdown(True) self.assertEqual(reader.read(), b"ghi") reader.shutdown(True) @unittest.skipIf(os.name == "nt", "NONBLOCK not implemented on Windows") def test_fd_read(self): (r, w) = os.pipe() ch = GLib.IOChannel(filedes=r) ch.set_encoding(None) ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK) self.assertNotEqual(ch.get_flags() | GLib.IOFlags.NONBLOCK, 0) self.assertEqual(ch.read(), b"") os.write(w, b"\x01\x02") self.assertEqual(ch.read(), b"\x01\x02") # now test blocking case, after closing the write end ch.set_flags(GLib.IOFlags(ch.get_flags() & ~GLib.IOFlags.NONBLOCK)) os.write(w, b"\x03\x04") os.close(w) self.assertEqual(ch.read(), b"\x03\x04") ch.shutdown(True) @unittest.skipUnless(fcntl, "no fcntl") def test_fd_write(self): (r, w) = os.pipe() fcntl.fcntl(r, fcntl.F_SETFL, fcntl.fcntl(r, fcntl.F_GETFL) | os.O_NONBLOCK) ch = GLib.IOChannel(filedes=w, mode="w") ch.set_encoding(None) ch.set_buffered(False) ch.write(b"\x01\x02") self.assertEqual(os.read(r, 10), b"\x01\x02") # now test blocking case, after closing the write end fcntl.fcntl(r, fcntl.F_SETFL, fcntl.fcntl(r, fcntl.F_GETFL) & ~os.O_NONBLOCK) ch.write(b"\x03\x04") ch.shutdown(True) self.assertEqual(os.read(r, 10), b"\x03\x04") os.close(r) @unittest.skipIf(os.name == "nt", "NONBLOCK not implemented on Windows") def test_deprecated_method_add_watch_no_data(self): (r, w) = os.pipe() ch = GLib.IOChannel(filedes=r) ch.set_encoding(None) ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK) cb_reads = [] def cb(channel, condition): self.assertEqual(channel, ch) self.assertEqual(condition, GLib.IOCondition.IN) cb_reads.append(channel.read()) if len(cb_reads) == 2: ml.quit() return True # io_add_watch() method is deprecated, use GLib.io_add_watch with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") ch.add_watch(GLib.IOCondition.IN, cb, priority=GLib.PRIORITY_HIGH) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) def write(): os.write(w, b"a") GLib.idle_add(lambda: os.write(w, b"b") and False) ml = GLib.MainLoop() GLib.idle_add(write) GLib.timeout_add(2000, ml.quit) ml.run() self.assertEqual(cb_reads, [b"a", b"b"]) @unittest.skipIf(os.name == "nt", "NONBLOCK not implemented on Windows") def test_deprecated_method_add_watch_data_priority(self): (r, w) = os.pipe() ch = GLib.IOChannel(filedes=r) ch.set_encoding(None) ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK) cb_reads = [] def cb(channel, condition, data): self.assertEqual(channel, ch) self.assertEqual(condition, GLib.IOCondition.IN) self.assertEqual(data, "hello") cb_reads.append(channel.read()) if len(cb_reads) == 2: ml.quit() return True ml = GLib.MainLoop() # io_add_watch() method is deprecated, use GLib.io_add_watch with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") id = ch.add_watch( GLib.IOCondition.IN, cb, "hello", priority=GLib.PRIORITY_HIGH ) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) def write(): os.write(w, b"a") GLib.idle_add(lambda: os.write(w, b"b") and False) GLib.idle_add(write) GLib.timeout_add(2000, ml.quit) ml.run() self.assertEqual(cb_reads, [b"a", b"b"]) @unittest.skipIf(os.name == "nt", "NONBLOCK not implemented on Windows") def test_add_watch_no_data(self): (r, w) = os.pipe() ch = GLib.IOChannel(filedes=r) ch.set_encoding(None) ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK) cb_reads = [] def cb(channel, condition): self.assertEqual(channel, ch) self.assertEqual(condition, GLib.IOCondition.IN) cb_reads.append(channel.read()) if len(cb_reads) == 2: ml.quit() return True id = GLib.io_add_watch(ch, GLib.PRIORITY_HIGH, GLib.IOCondition.IN, cb) ml = GLib.MainLoop() self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) def write(): os.write(w, b"a") GLib.idle_add(lambda: os.write(w, b"b") and False) GLib.idle_add(write) GLib.timeout_add(2000, ml.quit) ml.run() self.assertEqual(cb_reads, [b"a", b"b"]) @unittest.skipIf(os.name == "nt", "NONBLOCK not implemented on Windows") def test_add_watch_with_data(self): (r, w) = os.pipe() ch = GLib.IOChannel(filedes=r) ch.set_encoding(None) ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK) cb_reads = [] def cb(channel, condition, data): self.assertEqual(channel, ch) self.assertEqual(condition, GLib.IOCondition.IN) self.assertEqual(data, "hello") cb_reads.append(channel.read()) if len(cb_reads) == 2: ml.quit() return True id = GLib.io_add_watch(ch, GLib.PRIORITY_HIGH, GLib.IOCondition.IN, cb, "hello") ml = GLib.MainLoop() self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) def write(): os.write(w, b"a") GLib.idle_add(lambda: os.write(w, b"b") and False) GLib.idle_add(write) GLib.timeout_add(2000, ml.quit) ml.run() self.assertEqual(cb_reads, [b"a", b"b"]) @unittest.skipIf(os.name == "nt", "NONBLOCK not implemented on Windows") def test_add_watch_with_multi_data(self): (r, w) = os.pipe() ch = GLib.IOChannel(filedes=r) ch.set_encoding(None) ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK) cb_reads = [] def cb(channel, condition, data1, data2, data3): self.assertEqual(channel, ch) self.assertEqual(condition, GLib.IOCondition.IN) self.assertEqual(data1, "a") self.assertEqual(data2, "b") self.assertEqual(data3, "c") cb_reads.append(channel.read()) if len(cb_reads) == 2: ml.quit() return True id = GLib.io_add_watch( ch, GLib.PRIORITY_HIGH, GLib.IOCondition.IN, cb, "a", "b", "c" ) ml = GLib.MainLoop() self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) def write(): os.write(w, b"a") GLib.idle_add(lambda: os.write(w, b"b") and False) GLib.idle_add(write) GLib.timeout_add(2000, ml.quit) ml.run() self.assertEqual(cb_reads, [b"a", b"b"]) @unittest.skipIf(os.name == "nt", "NONBLOCK not implemented on Windows") def test_deprecated_add_watch_no_data(self): (r, w) = os.pipe() ch = GLib.IOChannel(filedes=r) ch.set_encoding(None) ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK) cb_reads = [] def cb(channel, condition): self.assertEqual(channel, ch) self.assertEqual(condition, GLib.IOCondition.IN) cb_reads.append(channel.read()) if len(cb_reads) == 2: ml.quit() return True with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") id = GLib.io_add_watch( ch, GLib.IOCondition.IN, cb, priority=GLib.PRIORITY_HIGH ) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) ml = GLib.MainLoop() self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) def write(): os.write(w, b"a") GLib.idle_add(lambda: os.write(w, b"b") and False) GLib.idle_add(write) GLib.timeout_add(2000, ml.quit) ml.run() self.assertEqual(cb_reads, [b"a", b"b"]) @unittest.skipIf(os.name == "nt", "NONBLOCK not implemented on Windows") def test_deprecated_add_watch_with_data(self): (r, w) = os.pipe() ch = GLib.IOChannel(filedes=r) ch.set_encoding(None) ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK) cb_reads = [] def cb(channel, condition, data): self.assertEqual(channel, ch) self.assertEqual(condition, GLib.IOCondition.IN) self.assertEqual(data, "hello") cb_reads.append(channel.read()) if len(cb_reads) == 2: ml.quit() return True with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") id = GLib.io_add_watch( ch, GLib.IOCondition.IN, cb, "hello", priority=GLib.PRIORITY_HIGH ) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) ml = GLib.MainLoop() self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) def write(): os.write(w, b"a") GLib.idle_add(lambda: os.write(w, b"b") and False) GLib.idle_add(write) GLib.timeout_add(2000, ml.quit) ml.run() self.assertEqual(cb_reads, [b"a", b"b"]) def test_backwards_compat_flags(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", PyGIDeprecationWarning) self.assertEqual(GLib.IOCondition.IN, GLib.IO_IN) self.assertEqual(GLib.IOFlags.NONBLOCK, GLib.IO_FLAG_NONBLOCK) self.assertEqual(GLib.IOFlags.IS_SEEKABLE, GLib.IO_FLAG_IS_SEEKABLE) self.assertEqual(GLib.IOStatus.NORMAL, GLib.IO_STATUS_NORMAL) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_mainloop.py0000664000000000000000000000402415074673150016737 0ustar00rootrootimport os import select import signal import unittest import warnings from gi.repository import GLib from .helper import capture_exceptions class TestMainLoop(unittest.TestCase): @unittest.skipUnless(hasattr(os, "fork"), "no os.fork available") def test_exception_handling(self): pipe_r, pipe_w = os.pipe() with warnings.catch_warnings(): warnings.filterwarnings("ignore", ".*may lead to deadlock.*") pid = os.fork() if pid == 0: os.close(pipe_w) select.select([pipe_r], [], []) os.close(pipe_r) os._exit(1) def child_died(pid, status, loop): loop.quit() raise Exception("deadbabe") loop = GLib.MainLoop() GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, child_died, loop) os.close(pipe_r) os.write(pipe_w, b"Y") os.close(pipe_w) with capture_exceptions() as exc: loop.run() assert len(exc) == 1 assert exc[0].type is Exception assert exc[0].value.args[0] == "deadbabe" @unittest.skipUnless(hasattr(os, "fork"), "no os.fork available") @unittest.skipIf(os.environ.get("PYGI_TEST_GDB"), "SIGINT stops gdb") def test_sigint(self): r, w = os.pipe() with warnings.catch_warnings(): warnings.filterwarnings("ignore", ".*may lead to deadlock.*") pid = os.fork() if pid == 0: # wait for the parent process loop to start os.read(r, 1) os.close(r) os.kill(os.getppid(), signal.SIGINT) os._exit(0) def notify_child(): # tell the child that it can kill the parent os.write(w, b"X") os.close(w) GLib.idle_add(notify_child) loop = GLib.MainLoop() try: loop.run() self.fail("expected KeyboardInterrupt exception") except KeyboardInterrupt: pass self.assertFalse(loop.is_running()) os.waitpid(pid, 0) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_object_marshaling.py0000664000000000000000000006177215074673150020611 0ustar00rootrootimport unittest import weakref import gc import sys import warnings from gi import PyGIDeprecationWarning from gi.repository import GObject from gi.repository import GIMarshallingTests import testhelper try: from gi.repository import Regress except ImportError: Regress = None class StrongRef: # A class that behaves like weakref.ref but holds a strong reference. # This allows re-use of the VFuncsBase by swapping out the ObjectRef # class var with either weakref.ref or StrongRef. def __init__(self, obj): self.obj = obj def __call__(self): return self.obj class VFuncsBase(GIMarshallingTests.Object): # Class which generically implements the vfuncs used for reference counting tests # in a way that can be easily sub-classed and modified. #: Object type used by this class for testing #: This can be GObject.Object or GObject.InitiallyUnowned Object = GObject.Object #: Reference type used by this class for holding refs to in/out objects. #: This can be set to weakref.ref or StrongRef ObjectRef = weakref.ref def __init__(self): super().__init__() #: Hold ref of input or output python wrappers self.object_ref = None #: store grefcount of input object self.in_object_grefcount = None self.in_object_is_floating = None def do_vfunc_return_object_transfer_none(self): # Return an object but keep a python reference to it. obj = self.Object() self.object_ref = self.ObjectRef(obj) return obj def do_vfunc_return_object_transfer_full(self): # Return an object and hand off the reference to the caller. obj = self.Object() self.object_ref = self.ObjectRef(obj) return obj def do_vfunc_out_object_transfer_none(self): # Same as do_vfunc_return_object_transfer_none but the pygi # internals convert the return here into an out arg. obj = self.Object() self.object_ref = self.ObjectRef(obj) return obj def do_vfunc_out_object_transfer_full(self): # Same as do_vfunc_return_object_transfer_full but the pygi # internals convert the return here into an out arg. obj = self.Object() self.object_ref = self.ObjectRef(obj) return obj def do_vfunc_in_object_transfer_none(self, obj): # 'obj' will have a python wrapper as well as still held # by the caller. self.object_ref = self.ObjectRef(obj) self.in_object_grefcount = obj.__grefcount__ self.in_object_is_floating = obj.is_floating() def do_vfunc_in_object_transfer_full(self, obj): # 'obj' will now be owned by the Python GObject wrapper. # When obj goes out of scope and is collected, the GObject # should also be fully released. self.object_ref = self.ObjectRef(obj) self.in_object_grefcount = obj.__grefcount__ self.in_object_is_floating = obj.is_floating() class TestVFuncsWithObjectArg(unittest.TestCase): # Basic set of tests which work on non-floating objects which python does # not keep an additional reference of. class VFuncs(VFuncsBase): # Object for testing non-floating objects without holding any refs. Object = GObject.Object ObjectRef = weakref.ref def test_vfunc_self_arg_ref_count(self): # Check to make sure vfunc "self" arguments don't leak. vfuncs = self.VFuncs() vfuncs_ref = weakref.ref(vfuncs) vfuncs.get_ref_info_for_vfunc_return_object_transfer_full() # Use any vfunc to test this. gc.collect() if hasattr(sys, "getrefcount"): self.assertEqual( sys.getrefcount(vfuncs), 2 if sys.version_info < (3, 14) else 1 ) self.assertEqual(vfuncs.__grefcount__, 1) del vfuncs gc.collect() self.assertTrue(vfuncs_ref() is None) def test_vfunc_return_object_transfer_none(self): # This tests a problem case where the vfunc returns a GObject owned solely by Python # but the argument is marked as transfer-none. # In this case pygobject marshaling adds an additional ref and gives a warning # of a potential leak. If this occures it is really a bug in the underlying library # but pygobject tries to react to this in a reasonable way. vfuncs = self.VFuncs() with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_out_object_transfer_none() ) if hasattr(sys, "getrefcount"): self.assertTrue(issubclass(warn[0].category, RuntimeWarning)) # The ref count of the GObject returned to the caller (get_ref_info_for_vfunc_return_object_transfer_none) # should be a single floating ref if hasattr(sys, "getrefcount"): self.assertEqual(ref_count, 1) self.assertFalse(is_floating) gc.collect() self.assertTrue(vfuncs.object_ref() is None) def test_vfunc_out_object_transfer_none(self): # Same as above except uses out arg instead of return vfuncs = self.VFuncs() with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_out_object_transfer_none() ) if hasattr(sys, "getrefcount"): self.assertTrue(issubclass(warn[0].category, RuntimeWarning)) if hasattr(sys, "getrefcount"): self.assertEqual(ref_count, 1) self.assertFalse(is_floating) gc.collect() self.assertTrue(vfuncs.object_ref() is None) def test_vfunc_return_object_transfer_full(self): vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_return_object_transfer_full() ) # The vfunc caller receives full ownership of a single ref which should not # be floating. if hasattr(sys, "getrefcount"): self.assertEqual(ref_count, 1) self.assertFalse(is_floating) gc.collect() self.assertTrue(vfuncs.object_ref() is None) def test_vfunc_out_object_transfer_full(self): # Same as above except uses out arg instead of return vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_out_object_transfer_full() ) if hasattr(sys, "getrefcount"): self.assertEqual(ref_count, 1) self.assertFalse(is_floating) gc.collect() self.assertTrue(vfuncs.object_ref() is None) def test_vfunc_in_object_transfer_none(self): vfuncs = self.VFuncs() ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_none( self.VFuncs.Object ) gc.collect() self.assertEqual(vfuncs.in_object_grefcount, 2) # initial + python wrapper self.assertFalse(vfuncs.in_object_is_floating) if hasattr(sys, "getrefcount"): self.assertEqual(ref_count, 1) # ensure python wrapper released self.assertFalse(is_floating) gc.collect() gc.collect() self.assertTrue(vfuncs.object_ref() is None) def test_vfunc_in_object_transfer_full(self): vfuncs = self.VFuncs() ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_full( self.VFuncs.Object ) gc.collect() # python wrapper should take sole ownership of the gobject self.assertEqual(vfuncs.in_object_grefcount, 1) self.assertFalse(vfuncs.in_object_is_floating) # ensure python wrapper took ownership and released, after vfunc was complete if hasattr(sys, "getrefcount"): self.assertEqual(ref_count, 0) self.assertFalse(is_floating) gc.collect() gc.collect() self.assertTrue(vfuncs.object_ref() is None) class TestVFuncsWithFloatingArg(unittest.TestCase): # All tests here work with a floating object by using InitiallyUnowned as the argument class VFuncs(VFuncsBase): # Object for testing non-floating objects without holding any refs. Object = GObject.InitiallyUnowned ObjectRef = weakref.ref @unittest.skipUnless(hasattr(sys, "getrefcount"), "refcount specific") def test_vfunc_return_object_transfer_none_with_floating(self): # Python is expected to return a single floating reference without warning. vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_return_object_transfer_none() ) # The ref count of the GObject returned to the caller (get_ref_info_for_vfunc_return_object_transfer_none) # should be a single floating ref self.assertEqual(ref_count, 1) self.assertTrue(is_floating) gc.collect() self.assertTrue(vfuncs.object_ref() is None) @unittest.skipUnless(hasattr(sys, "getrefcount"), "refcount specific") def test_vfunc_out_object_transfer_none_with_floating(self): # Same as above except uses out arg instead of return vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_out_object_transfer_none() ) self.assertEqual(ref_count, 1) self.assertTrue(is_floating) gc.collect() self.assertTrue(vfuncs.object_ref() is None) def test_vfunc_return_object_transfer_full_with_floating(self): vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_return_object_transfer_full() ) # The vfunc caller receives full ownership of a single ref. if hasattr(sys, "getrefcount"): self.assertEqual(ref_count, 1) self.assertFalse(is_floating) gc.collect() self.assertTrue(vfuncs.object_ref() is None) def test_vfunc_out_object_transfer_full_with_floating(self): # Same as above except uses out arg instead of return vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_out_object_transfer_full() ) if hasattr(sys, "getrefcount"): self.assertEqual(ref_count, 1) self.assertFalse(is_floating) gc.collect() self.assertTrue(vfuncs.object_ref() is None) def test_vfunc_in_object_transfer_none_with_floating(self): vfuncs = self.VFuncs() def ref(obj): testhelper.force_g_object_ref(obj) # FIXME: Add an item dictionary so that the python wrapper cannot # be destroyed because it is unused. Unfortunately, a weakref does # not trigger this handling (though it may be possible through # object resurrection). obj._something = None return weakref.ref(obj) vfuncs.ObjectRef = ref ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_none( self.VFuncs.Object ) gc.collect() # python wrapper should maintain the object as floating and add an additional ref # So, two plus the one we added explicitly. No extra toggle reference to keep the wrapper alive. self.assertEqual(vfuncs.in_object_grefcount, 2 + 1) self.assertTrue(vfuncs.in_object_is_floating) # vfunc caller should only have a single floating ref after the vfunc finishes # Add to that the explicit reference we added and then the toggle reference for the dict if hasattr(sys, "getrefcount"): self.assertEqual(ref_count, 1 + 2) self.assertTrue(is_floating) # There are two references now, one explicit and one from the wrapper self.assertEqual(vfuncs.object_ref().__grefcount__, 2) self.assertTrue(vfuncs.object_ref().is_floating()) # Sinking and unref'ing our "C" one will drop both (as the second is a toggle ref) with warnings.catch_warnings(): warnings.simplefilter("ignore", PyGIDeprecationWarning) vfuncs.object_ref()._ref_sink() testhelper.force_g_object_unref(vfuncs.object_ref()) gc.collect() gc.collect() self.assertTrue(vfuncs.object_ref() is None) def test_vfunc_in_object_transfer_full_with_floating(self): vfuncs = self.VFuncs() ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_full( self.VFuncs.Object ) gc.collect() # python wrapper sinks and owns the gobject self.assertEqual(vfuncs.in_object_grefcount, 1) self.assertFalse(vfuncs.in_object_is_floating) # ensure python wrapper took ownership and released if hasattr(sys, "getrefcount"): self.assertEqual(ref_count, 0) self.assertFalse(is_floating) gc.collect() gc.collect() self.assertTrue(vfuncs.object_ref() is None) class TestVFuncsWithHeldObjectArg(unittest.TestCase): # Same tests as TestVFuncsWithObjectArg except we hold # onto the python object reference in all cases. class VFuncs(VFuncsBase): # Object for testing non-floating objects with a held ref. Object = GObject.Object ObjectRef = StrongRef def test_vfunc_return_object_transfer_none_with_held_object(self): vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_return_object_transfer_none() ) # Python holds the single gobject ref in 'vfuncs.object_ref' # Because of this, we do not expect a floating ref or a ref increase. self.assertEqual(ref_count, 1) self.assertFalse(is_floating) # The actual grefcount should stay at 1 even after the vfunc return. self.assertEqual(vfuncs.object_ref().__grefcount__, 1) self.assertFalse(vfuncs.in_object_is_floating) held_object_ref = weakref.ref(vfuncs.object_ref) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) def test_vfunc_out_object_transfer_none_with_held_object(self): vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_out_object_transfer_none() ) self.assertEqual(ref_count, 1) self.assertFalse(is_floating) self.assertEqual(vfuncs.object_ref().__grefcount__, 1) self.assertFalse(vfuncs.in_object_is_floating) held_object_ref = weakref.ref(vfuncs.object_ref) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) def test_vfunc_return_object_transfer_full_with_held_object(self): # The vfunc caller receives full ownership which should not # be floating. However, the held python wrapper also has a ref. vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_return_object_transfer_full() ) # Ref count from the perspective of C after the vfunc is called # The vfunc caller receives a new reference which should not # be floating. However, the held python wrapper also has a ref. self.assertEqual(ref_count, 2) self.assertFalse(is_floating) # Current ref count # The vfunc caller should have decremented its reference. self.assertEqual(vfuncs.object_ref().__grefcount__, 1) held_object_ref = weakref.ref(vfuncs.object_ref) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) def test_vfunc_out_object_transfer_full_with_held_object(self): # Same test as above except uses out arg instead of return vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_out_object_transfer_full() ) # Ref count from the perspective of C after the vfunc is called # The vfunc caller receives a new reference which should not # be floating. However, the held python wrapper also has a ref. self.assertEqual(ref_count, 2) self.assertFalse(is_floating) # Current ref count # The vfunc caller should have decremented its reference. self.assertEqual(vfuncs.object_ref().__grefcount__, 1) held_object_ref = weakref.ref(vfuncs.object_ref()) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) def test_vfunc_in_object_transfer_none_with_held_object(self): vfuncs = self.VFuncs() ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_none( self.VFuncs.Object ) gc.collect() # Ref count inside vfunc from the perspective of Python self.assertEqual(vfuncs.in_object_grefcount, 2) # initial + python wrapper self.assertFalse(vfuncs.in_object_is_floating) # Ref count from the perspective of C after the vfunc is called self.assertEqual(ref_count, 2) # kept after vfunc + held python wrapper self.assertFalse(is_floating) # Current ref count after C cleans up its reference self.assertEqual(vfuncs.object_ref().__grefcount__, 1) held_object_ref = weakref.ref(vfuncs.object_ref()) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) def test_vfunc_in_object_transfer_full_with_held_object(self): vfuncs = self.VFuncs() ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_full( self.VFuncs.Object ) gc.collect() # Ref count inside vfunc from the perspective of Python self.assertEqual( vfuncs.in_object_grefcount, 1 ) # python wrapper takes ownership of the gobject self.assertFalse(vfuncs.in_object_is_floating) # Ref count from the perspective of C after the vfunc is called self.assertEqual(ref_count, 1) self.assertFalse(is_floating) # Current ref count self.assertEqual(vfuncs.object_ref().__grefcount__, 1) held_object_ref = weakref.ref(vfuncs.object_ref()) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) class TestVFuncsWithHeldFloatingArg(unittest.TestCase): # Tests for a floating object which we hold a reference to the python wrapper # on the VFuncs test class. class VFuncs(VFuncsBase): # Object for testing floating objects with a held ref. Object = GObject.InitiallyUnowned ObjectRef = StrongRef def test_vfunc_return_object_transfer_none_with_held_floating(self): # Python holds onto the wrapper which basically means the floating ref # should also be owned by python. vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_return_object_transfer_none() ) # This is a borrowed ref from what is held in python. self.assertEqual(ref_count, 1) self.assertFalse(is_floating) # The actual grefcount should stay at 1 even after the vfunc return. self.assertEqual(vfuncs.object_ref().__grefcount__, 1) held_object_ref = weakref.ref(vfuncs.object_ref) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) def test_vfunc_out_object_transfer_none_with_held_floating(self): # Same as above vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_out_object_transfer_none() ) self.assertEqual(ref_count, 1) self.assertFalse(is_floating) self.assertEqual(vfuncs.object_ref().__grefcount__, 1) held_object_ref = weakref.ref(vfuncs.object_ref) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) def test_vfunc_return_object_transfer_full_with_held_floating(self): vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_return_object_transfer_full() ) # Ref count from the perspective of C after the vfunc is called self.assertEqual(ref_count, 2) self.assertFalse(is_floating) # Current ref count # vfunc wrapper destroyes ref it was given self.assertEqual(vfuncs.object_ref().__grefcount__, 1) held_object_ref = weakref.ref(vfuncs.object_ref) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) def test_vfunc_out_object_transfer_full_with_held_floating(self): # Same test as above except uses out arg instead of return vfuncs = self.VFuncs() ref_count, is_floating = ( vfuncs.get_ref_info_for_vfunc_out_object_transfer_full() ) # Ref count from the perspective of C after the vfunc is called self.assertEqual(ref_count, 2) self.assertFalse(is_floating) # Current ref count # vfunc wrapper destroyes ref it was given self.assertEqual(vfuncs.object_ref().__grefcount__, 1) held_object_ref = weakref.ref(vfuncs.object_ref()) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) def test_vfunc_in_floating_transfer_none_with_held_floating(self): vfuncs = self.VFuncs() ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_none( self.VFuncs.Object ) gc.collect() # Ref count inside vfunc from the perspective of Python self.assertTrue(vfuncs.in_object_is_floating) self.assertEqual( vfuncs.in_object_grefcount, 2 ) # python wrapper sinks and owns the gobject # Ref count from the perspective of C after the vfunc is called self.assertTrue(is_floating) self.assertEqual(ref_count, 2) # floating + held by wrapper # Current ref count after C cleans up its reference self.assertEqual(vfuncs.object_ref().__grefcount__, 1) # Our reference is still floating at this point ... self.assertTrue(vfuncs.object_ref().is_floating()) # ... usually it should have been sunk within C at some point, # do it here to avoid a critical warning. with warnings.catch_warnings(): warnings.simplefilter("ignore", PyGIDeprecationWarning) vfuncs.object_ref()._ref_sink() # However, that means that the above comment of "sinks and owns" is wrong. held_object_ref = weakref.ref(vfuncs.object_ref()) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) def test_vfunc_in_floating_transfer_full_with_held_floating(self): vfuncs = self.VFuncs() ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_full( self.VFuncs.Object ) gc.collect() # Ref count from the perspective of C after the vfunc is called self.assertEqual( vfuncs.in_object_grefcount, 1 ) # python wrapper sinks and owns the gobject self.assertFalse(vfuncs.in_object_is_floating) # Ref count from the perspective of C after the vfunc is called self.assertEqual(ref_count, 1) # held by wrapper self.assertFalse(is_floating) # Current ref count self.assertEqual(vfuncs.object_ref().__grefcount__, 1) held_object_ref = weakref.ref(vfuncs.object_ref()) del vfuncs.object_ref gc.collect() self.assertTrue(held_object_ref() is None) @unittest.skipIf(Regress is None, "Regress is required") class TestArgumentTypeErrors(unittest.TestCase): def test_object_argument_type_error(self): # ensure TypeError is raised for things which are not GObjects obj = Regress.TestObj() obj.set_bare(GObject.Object()) obj.set_bare(None) self.assertRaises(TypeError, obj.set_bare, object()) self.assertRaises(TypeError, obj.set_bare, 42) self.assertRaises(TypeError, obj.set_bare, "not an object") def test_instance_argument_error(self): # ensure TypeError is raised for non Regress.TestObj instances. obj = Regress.TestObj() self.assertEqual(Regress.TestObj.instance_method(obj), -1) self.assertRaises(TypeError, Regress.TestObj.instance_method, object()) self.assertRaises(TypeError, Regress.TestObj.instance_method, GObject.Object()) self.assertRaises(TypeError, Regress.TestObj.instance_method, 42) self.assertRaises(TypeError, Regress.TestObj.instance_method, "not an object") def test_instance_argument_base_type_error(self): # ensure TypeError is raised when a base type is passed to something # expecting a derived type obj = Regress.TestSubObj() self.assertEqual(Regress.TestSubObj.instance_method(obj), 0) self.assertRaises( TypeError, Regress.TestSubObj.instance_method, GObject.Object() ) self.assertRaises( TypeError, Regress.TestSubObj.instance_method, Regress.TestObj() ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_option.py0000664000000000000000000001162115074673150016432 0ustar00rootrootimport unittest from gi import PyGIDeprecationWarning from gi.repository import GLib from .helper import capture_exceptions class TestOption(unittest.TestCase): def setUp(self): with self.assertWarns(PyGIDeprecationWarning): self.parser = GLib.option.OptionParser( "NAMES...", description="Option unit test" ) self.parser.add_option( "-t", "--test", help="Unit test option", action="store_false", dest="test", default=True, ) ( self.parser.add_option( "--g-fatal-warnings", action="store_true", dest="fatal_warnings", help="dummy", ), ) def _create_group(self): def option_callback(option, opt, value, parser): raise Exception("foo") with self.assertWarns(PyGIDeprecationWarning): group = GLib.option.OptionGroup( "unittest", "Unit test options", "Show all unittest options", option_list=[ GLib.option.make_option( "-f", "-u", "--file", "--unit-file", type="filename", dest="unit_file", help="Unit test option", ), GLib.option.make_option( "--test-integer", type="int", dest="test_integer", help="Unit integer option", ), GLib.option.make_option( "--callback-failure-test", action="callback", callback=option_callback, dest="test_integer", help="Unit integer option", ), ], ) group.add_option( "-t", "--test", action="store_false", dest="test", default=True, help="Unit test option", ) self.parser.add_option_group(group) return group def test_integer(self): self._create_group() options, args = self.parser.parse_args(["--test-integer", "42", "bla"]) assert options.test_integer == 42 assert args == ["bla"] def test_file(self): self._create_group() options, args = self.parser.parse_args(["--file", "fn", "bla"]) assert options.unit_file == "fn" assert args == ["bla"] def test_mixed(self): self._create_group() options, args = self.parser.parse_args( [ "--file", "fn", "--test-integer", "12", "--test", "--g-fatal-warnings", "nope", ] ) assert options.unit_file == "fn" assert options.test_integer == 12 assert options.test is False assert options.fatal_warnings is True assert args == ["nope"] def test_parse_args(self): _options, args = self.parser.parse_args([]) self.assertFalse(args) _options, args = self.parser.parse_args(["foo"]) self.assertEqual(args, ["foo"]) _options, args = self.parser.parse_args(["foo", "bar"]) self.assertEqual(args, ["foo", "bar"]) def test_parse_args_double_dash(self): _options, args = self.parser.parse_args(["--", "-xxx"]) self.assertEqual(args, ["--", "-xxx"]) def test_parse_args_group(self): group = self._create_group() options, args = self.parser.parse_args(["--test", "-f", "test"]) self.assertFalse(options.test) self.assertEqual(options.unit_file, "test") self.assertTrue(group.values.test) self.assertFalse(self.parser.values.test) self.assertEqual(group.values.unit_file, "test") self.assertFalse(args) def test_option_value_error(self): self._create_group() self.assertRaises( GLib.option.OptionValueError, self.parser.parse_args, ["--test-integer=text"], ) def test_bad_option_error(self): self.assertRaises( GLib.option.BadOptionError, self.parser.parse_args, ["--unknwon-option"] ) def test_option_group_constructor(self): self.assertRaises(TypeError, GLib.option.OptionGroup) def test_standard_error(self): self._create_group() with capture_exceptions() as exc: self.parser.parse_args(["--callback-failure-test"]) assert len(exc) == 1 assert exc[0].value.args[0] == "foo" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_ossig.py0000664000000000000000000001447115074673150016254 0ustar00rootroot# Copyright 2017 Christoph Reiter # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, see . import os import signal import unittest import threading from contextlib import contextmanager try: from gi.repository import Gtk Gtk_version = Gtk._version except ImportError: Gtk = None Gtk_version = None from gi.repository import Gio, GLib from gi._ossighelper import wakeup_on_signal, register_sigint_fallback class TestOverridesWakeupOnAlarm(unittest.TestCase): @contextmanager def _run_with_timeout(self, timeout, abort_func): failed = [] def fail(): abort_func() failed.append(1) return True fail_id = GLib.timeout_add(timeout, fail) try: yield finally: GLib.source_remove(fail_id) self.assertFalse(failed) def test_basic(self): self.assertEqual(signal.set_wakeup_fd(-1), -1) with wakeup_on_signal(): pass self.assertEqual(signal.set_wakeup_fd(-1), -1) def test_in_thread(self): failed = [] def target(): try: with wakeup_on_signal(): pass except ValueError or EnvironmentError: failed.append(1) t = threading.Thread(target=target) t.start() t.join(5) self.assertFalse(failed) @unittest.skipIf(os.name == "nt", "not on Windows") def test_glib_mainloop(self): loop = GLib.MainLoop() signal.signal(signal.SIGALRM, lambda *args: loop.quit()) GLib.idle_add(signal.setitimer, signal.ITIMER_REAL, 0.001) with self._run_with_timeout(2000, loop.quit): loop.run() @unittest.skipIf(os.name == "nt", "not on Windows") def test_gio_application(self): app = Gio.Application() signal.signal(signal.SIGALRM, lambda *args: app.quit()) GLib.idle_add(signal.setitimer, signal.ITIMER_REAL, 0.001) with self._run_with_timeout(2000, app.quit): app.hold() app.connect("activate", lambda *args: None) app.run() @unittest.skipIf(Gtk is None or os.name == "nt", "not on Windows") @unittest.skipIf(Gtk is None or Gtk_version == "4.0", "not in gtk4") def test_gtk_main(self): signal.signal(signal.SIGALRM, lambda *args: Gtk.main_quit()) GLib.idle_add(signal.setitimer, signal.ITIMER_REAL, 0.001) with self._run_with_timeout(2000, Gtk.main_quit): Gtk.main() @unittest.skipIf(Gtk is None or os.name == "nt", "not on Windows") @unittest.skipIf(Gtk is None or Gtk_version == "4.0", "not in gtk4") def test_gtk_dialog_run(self): w = Gtk.Window() d = Gtk.Dialog(transient_for=w) signal.signal(signal.SIGALRM, lambda *args: d.destroy()) GLib.idle_add(signal.setitimer, signal.ITIMER_REAL, 0.001) with self._run_with_timeout(2000, d.destroy): d.run() class TestSigintFallback(unittest.TestCase): def setUp(self): self.assertEqual(signal.getsignal(signal.SIGINT), signal.default_int_handler) def tearDown(self): self.assertEqual(signal.getsignal(signal.SIGINT), signal.default_int_handler) def test_replace_handler_and_restore_nested(self): with register_sigint_fallback(lambda: None): new_handler = signal.getsignal(signal.SIGINT) self.assertNotEqual(new_handler, signal.default_int_handler) with register_sigint_fallback(lambda: None): self.assertTrue(signal.getsignal(signal.SIGINT) is new_handler) self.assertEqual(signal.getsignal(signal.SIGINT), signal.default_int_handler) def test_no_replace_if_not_default(self): def new_handler(*args): return None signal.signal(signal.SIGINT, new_handler) try: with register_sigint_fallback(lambda: None): self.assertTrue(signal.getsignal(signal.SIGINT) is new_handler) with register_sigint_fallback(lambda: None): self.assertTrue(signal.getsignal(signal.SIGINT) is new_handler) self.assertTrue(signal.getsignal(signal.SIGINT) is new_handler) finally: signal.signal(signal.SIGINT, signal.default_int_handler) def test_noop_in_threads(self): failed = [] def target(): try: with ( register_sigint_fallback(lambda: None), register_sigint_fallback(lambda: None), ): self.assertTrue( signal.getsignal(signal.SIGINT) is signal.default_int_handler ) except: failed.append(1) t = threading.Thread(target=target) t.start() t.join(5) self.assertFalse(failed) @unittest.skipIf(os.name == "nt", "not on Windows") def test_no_replace_if_set_by_glib(self): id_ = GLib.unix_signal_add( GLib.PRIORITY_DEFAULT, signal.SIGINT, lambda *args: None ) try: # signal.getsignal() doesn't pick up that unix_signal_add() # has changed the handler, but we should anyway. self.assertEqual( signal.getsignal(signal.SIGINT), signal.default_int_handler ) with register_sigint_fallback(lambda: None): self.assertEqual( signal.getsignal(signal.SIGINT), signal.default_int_handler ) self.assertEqual( signal.getsignal(signal.SIGINT), signal.default_int_handler ) finally: GLib.source_remove(id_) signal.signal(signal.SIGINT, signal.SIG_DFL) signal.signal(signal.SIGINT, signal.default_int_handler) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_overrides_gdk.py0000664000000000000000000002747415074673150017766 0ustar00rootrootimport re import os import sys import unittest import pytest import gi import gi.overrides from gi import PyGIDeprecationWarning try: from gi.repository import Gio, Gdk, GdkPixbuf, Gtk GDK4 = Gdk._version == "4.0" except ImportError: Gdk = None Gtk = None GDK4 = False def gtkver(): if Gtk is None: return (0, 0, 0) return (Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()) try: gi.require_foreign("cairo") has_cairo = True except ImportError: has_cairo = False from .helper import capture_glib_deprecation_warnings @unittest.skipUnless(Gdk, "Gdk not available") class TestGdk(unittest.TestCase): @unittest.skipIf(sys.platform == "darwin" or os.name == "nt", "crashes") @unittest.skipIf(GDK4, "not in gdk4") def test_constructor(self): attribute = Gdk.WindowAttr() attribute.window_type = Gdk.WindowType.CHILD attributes_mask = Gdk.WindowAttributesType.X | Gdk.WindowAttributesType.Y window = Gdk.Window(None, attribute, attributes_mask) self.assertEqual(window.get_window_type(), Gdk.WindowType.CHILD) @unittest.skipIf(GDK4, "not in gdk4") def test_color(self): color = Gdk.Color(100, 200, 300) self.assertEqual(color.red, 100) self.assertEqual(color.green, 200) self.assertEqual(color.blue, 300) with capture_glib_deprecation_warnings(): self.assertEqual(color, Gdk.Color(100, 200, 300)) self.assertNotEqual(color, Gdk.Color(1, 2, 3)) self.assertNotEqual(color, None) # assertNotEqual only tests __ne__. Following line explicitly # tests __eq__ with objects of other types self.assertFalse(color == object()) @unittest.skipIf(GDK4, "not in gdk4") def test_color_floats(self): self.assertEqual( Gdk.Color(13107, 21845, 65535), Gdk.Color.from_floats(0.2, 1.0 / 3.0, 1.0) ) self.assertEqual( Gdk.Color(13107, 21845, 65535).to_floats(), (0.2, 1.0 / 3.0, 1.0) ) self.assertEqual( Gdk.RGBA(0.2, 1.0 / 3.0, 1.0, 0.5).to_color(), Gdk.Color.from_floats(0.2, 1.0 / 3.0, 1.0), ) self.assertEqual( Gdk.RGBA.from_color(Gdk.Color(13107, 21845, 65535)), Gdk.RGBA(0.2, 1.0 / 3.0, 1.0, 1.0), ) @unittest.skipIf(GDK4, "not in gdk4") def test_color_to_floats_attrs(self): color = Gdk.Color(13107, 21845, 65535) assert color.red_float == 0.2 color.red_float = 0 assert color.red_float == 0 assert color.green_float == 1.0 / 3.0 color.green_float = 0 assert color.green_float == 0 assert color.blue_float == 1.0 color.blue_float = 0 assert color.blue_float == 0 def test_rgba(self): self.assertEqual(Gdk.RGBA, gi.overrides.Gdk.RGBA) rgba = Gdk.RGBA(0.1, 0.2, 0.3, 0.4) self.assertEqual(rgba, Gdk.RGBA(0.1, 0.2, 0.3, 0.4)) self.assertNotEqual(rgba, Gdk.RGBA(0.0, 0.2, 0.3, 0.4)) self.assertAlmostEqual(rgba.red, 0.1) self.assertAlmostEqual(rgba.green, 0.2) self.assertAlmostEqual(rgba.blue, 0.3) self.assertAlmostEqual(rgba.alpha, 0.4) rgba.green = 0.9 self.assertAlmostEqual(rgba.green, 0.9) self.assertNotEqual(rgba, None) # assertNotEqual only tests __ne__. Following line explicitly # tests __eq__ with objects of other types self.assertFalse(rgba == object()) # Iterator/tuple convsersion assert tuple(Gdk.RGBA(0.1, 0.2, 0.3, 0.4)) == pytest.approx( (0.1, 0.2, 0.3, 0.4) ) @unittest.skipUnless(GDK4, "only in gdk4") def test_rgba_gtk4(self): c = Gdk.RGBA(0, 0, 0, 0) assert c.to_string() == "rgba(0,0,0,0)" @unittest.skipIf(not has_cairo or GDK4, "not in gdk4") def test_window(self): w = Gtk.Window() w.realize() window = w.get_window() with capture_glib_deprecation_warnings(): assert window.cairo_create() is not None @unittest.skipIf(GDK4, "not in gdk4") def test_drag_context(self): context = Gdk.DragContext() # using it this way crashes.. assert hasattr(context, "finish") @unittest.skipIf(GDK4, "not in gdk4") def test_event(self): event = Gdk.Event.new(Gdk.EventType.CONFIGURE) self.assertEqual(event.type, Gdk.EventType.CONFIGURE) self.assertEqual(event.send_event, 0) event = Gdk.Event() event.type = Gdk.EventType.SCROLL self.assertRaises(AttributeError, lambda: getattr(event, "foo_bar")) @unittest.skipIf(GDK4, "not in gdk4") def test_scroll_event(self): event = Gdk.Event.new(Gdk.EventType.SCROLL) assert event.direction == Gdk.ScrollDirection.UP @unittest.skipIf(GDK4, "not in gdk4") def test_event_strip_boolean(self): ev = Gdk.EventButton() ev.type = Gdk.EventType.BUTTON_PRESS assert ev.get_coords() == (0.0, 0.0) # https://gitlab.gnome.org/GNOME/pygobject/issues/85 ev = Gdk.Event.new(Gdk.EventType.BUTTON_PRESS) assert ev.get_coords() == (True, 0.0, 0.0) @unittest.skipIf(GDK4, "not in gdk4") def test_event_touch(self): event = Gdk.Event.new(Gdk.EventType.TOUCH_BEGIN) self.assertEqual(event.type, Gdk.EventType.TOUCH_BEGIN) # emulating_pointer is unique to touch events self.assertFalse(event.emulating_pointer) self.assertFalse(event.touch.emulating_pointer) event.emulating_pointer = True self.assertTrue(event.emulating_pointer) self.assertTrue(event.touch.emulating_pointer) @unittest.skipIf(GDK4, "not in gdk4") def test_event_setattr(self): event = Gdk.Event.new(Gdk.EventType.DRAG_MOTION) event.x_root, event.y_root = 0, 5 self.assertEqual(event.dnd.x_root, 0) self.assertEqual(event.dnd.y_root, 5) self.assertEqual(event.x_root, 0) self.assertEqual(event.y_root, 5) # this used to work, keep it that way self.assertFalse(hasattr(event, "foo_bar")) event.foo_bar = 42 # unhandled type event.type = Gdk.EventType.EVENT_LAST with pytest.raises(AttributeError): event.foo_bar event.foo_bar = 42 assert event.foo_bar == 42 @unittest.skipIf(GDK4, "not in gdk4") def test_event_repr(self): event = Gdk.Event.new(Gdk.EventType.CONFIGURE) self.assertTrue("CONFIGURE" in repr(event)) @unittest.skipIf(GDK4, "not in gdk4") def test_event_structures(self): def button_press_cb(button, event): self.assertTrue(isinstance(event, Gdk.EventButton)) self.assertTrue(event.type == Gdk.EventType.BUTTON_PRESS) self.assertEqual(event.send_event, 0) self.assertEqual(event.get_state(), Gdk.ModifierType.CONTROL_MASK) self.assertEqual(event.get_root_coords(), (2, 5)) event.time = 12345 self.assertEqual(event.get_time(), 12345) w = Gtk.Window() b = Gtk.Button() b.connect("button-press-event", button_press_cb) w.add(b) b.show() b.realize() Gdk.test_simulate_button( b.get_window(), 2, 5, 0, Gdk.ModifierType.CONTROL_MASK, Gdk.EventType.BUTTON_PRESS, ) @unittest.skipIf(GDK4, "not in gdk4") def test_cursor(self): self.assertEqual(Gdk.Cursor, gi.overrides.Gdk.Cursor) with capture_glib_deprecation_warnings(): c = Gdk.Cursor(Gdk.CursorType.WATCH) self.assertNotEqual(c, None) with capture_glib_deprecation_warnings(): c = Gdk.Cursor(cursor_type=Gdk.CursorType.WATCH) self.assertNotEqual(c, None) display_manager = Gdk.DisplayManager.get() display = display_manager.get_default_display() test_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, 5, 10) with capture_glib_deprecation_warnings() as warn: c = Gdk.Cursor(display, test_pixbuf, y=0, x=0) self.assertNotEqual(c, None) self.assertEqual(len(warn), 1) self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning)) self.assertRegex(str(warn[0].message), ".*new_from_pixbuf.*") self.assertRaises(ValueError, Gdk.Cursor, 1, 2, 3) with capture_glib_deprecation_warnings() as warn: c = Gdk.Cursor(display, Gdk.CursorType.WATCH) assert len(warn) == 1 # on macOS the type is switched to PIXMAP behind the scenes assert c.props.cursor_type in ( Gdk.CursorType.WATCH, Gdk.CursorType.CURSOR_IS_PIXMAP, ) assert c.props.display == display @unittest.skipUnless(GDK4, "only gdk4") def test_cursor_gdk4(self): Gdk.Cursor() Gdk.Cursor(name="foo") Gdk.Cursor(fallback=Gdk.Cursor()) def test_flags(self): self.assertEqual(Gdk.ModifierType.META_MASK | 0, 0x10000000) self.assertEqual(hex(Gdk.ModifierType.META_MASK), "0x10000000") self.assertEqual( repr(Gdk.ModifierType.META_MASK), "" ) # RELEASE_MASK does not exist in gdk4 if not GDK4: self.assertEqual(Gdk.ModifierType.RELEASE_MASK | 0, 0x40000000) self.assertEqual(hex(Gdk.ModifierType.RELEASE_MASK), "0x40000000") self.assertEqual( repr(Gdk.ModifierType.RELEASE_MASK), "", ) self.assertEqual( Gdk.ModifierType.RELEASE_MASK | Gdk.ModifierType.META_MASK, 0x50000000 ) self.assertIn( repr(Gdk.ModifierType.RELEASE_MASK | Gdk.ModifierType.META_MASK), { "", "", }, ) @unittest.skipIf(GDK4, "not in gdk4") def test_color_parse(self): with capture_glib_deprecation_warnings(): c = Gdk.color_parse("#00FF80") self.assertEqual(c.red, 0) self.assertEqual(c.green, 65535) self.assertEqual(c.blue, 32896) self.assertEqual(Gdk.color_parse("bogus"), None) @unittest.skipIf(GDK4, "not in gdk4") def test_color_representations(self): # __repr__ should generate a string which is parsable when possible # http://docs.python.org/2/reference/datamodel.html#object.__repr__ color = Gdk.Color(red=65535, green=32896, blue=1) self.assertEqual(eval(repr(color)), color) def test_rgba_representations(self): rgba = Gdk.RGBA(red=1.0, green=0.8, blue=0.6, alpha=0.4) self.assertEqual(eval(repr(rgba)), rgba) @unittest.skipIf(GDK4, "not in gdk4") def test_rectangle_functions(self): # https://bugzilla.gnome.org/show_bug.cgi?id=756364 a = Gdk.Rectangle() b = Gdk.Rectangle() self.assertTrue(isinstance(Gdk.rectangle_union(a, b), Gdk.Rectangle)) intersect, rect = Gdk.rectangle_intersect(a, b) self.assertTrue(isinstance(rect, Gdk.Rectangle)) self.assertTrue(isinstance(intersect, bool)) @unittest.skipIf(GDK4, "not in gdk4") def test_atom_repr_str(self): atom = Gdk.atom_intern("", True) assert re.match(r"", repr(atom)) assert re.match(r"Gdk.Atom<\d+>", str(atom)) @unittest.skipUnless(GDK4, "only in gdk4") @unittest.skipUnless(gtkver() >= (4, 8, 0), "constructor available since 4.8") def test_file_list(self): f = Gio.File.new_for_path("/tmp") filelist = Gdk.FileList([f]) self.assertTrue(isinstance(filelist, Gdk.FileList)) self.assertEqual(len(filelist), 1) self.assertEqual(filelist[0], f) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_overrides_gdkpixbuf.py0000664000000000000000000000356115074673150021173 0ustar00rootroot# Copyright 2018 Christoph Reiter # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import pytest from gi import PyGIDeprecationWarning GdkPixbuf = pytest.importorskip("gi.repository.GdkPixbuf") def test_new_from_data(): width = 600 height = 32769 pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, width, height) pixels = pixbuf.get_pixels() new_pixbuf = GdkPixbuf.Pixbuf.new_from_data( pixels, GdkPixbuf.Colorspace.RGB, True, 8, pixbuf.get_width(), pixbuf.get_height(), pixbuf.get_rowstride(), ) del pixbuf del pixels new_pixels = new_pixbuf.get_pixels() assert len(new_pixels) == width * height * 4 def test_new_from_data_deprecated_args(): GdkPixbuf.Pixbuf.new_from_data(b"1234", 0, True, 8, 1, 1, 4) GdkPixbuf.Pixbuf.new_from_data(b"1234", 0, True, 8, 1, 1, 4, None) with ( pytest.warns(PyGIDeprecationWarning, match=".*destroy_fn argument.*"), pytest.warns(PyGIDeprecationWarning, match=".*destroy_fn_data argument.*"), ): GdkPixbuf.Pixbuf.new_from_data( b"1234", 0, True, 8, 1, 1, 4, object(), object(), object() ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_overrides_gio.py0000664000000000000000000002644015074673150017767 0ustar00rootrootimport os import platform import random import warnings import pytest from gi.repository import Gio, GLib, GObject from gi import PyGIWarning class Item(GObject.Object): _id = 0 def __init__(self, **kwargs): super().__init__(**kwargs) Item._id += 1 self._id = self._id def __repr__(self): return str(self._id) class NamedItem(Item): name = GObject.Property(type=str, default="") def __repr__(self): return self.props.name def test_list_store_sort(): store = Gio.ListStore() items = [NamedItem(name=n) for n in "cabx"] sorted_items = sorted(items, key=lambda i: i.props.name) user_data = [object(), object()] def sort_func(a, b, *args): assert list(args) == user_data assert isinstance(a, NamedItem) assert isinstance(b, NamedItem) def cmp(a, b): return (a > b) - (a < b) return cmp(a.props.name, b.props.name) store[:] = items assert store[:] != sorted_items store.sort(sort_func, *user_data) assert store[:] == sorted_items def test_list_store_insert_sorted(): store = Gio.ListStore() items = [NamedItem(name=n) for n in "cabx"] sorted_items = sorted(items, key=lambda i: i.props.name) user_data = [object(), object()] def sort_func(a, b, *args): assert list(args) == user_data assert isinstance(a, NamedItem) assert isinstance(b, NamedItem) def cmp(a, b): return (a > b) - (a < b) return cmp(a.props.name, b.props.name) for item in items: index = store.insert_sorted(item, sort_func, *user_data) assert isinstance(index, int) assert store[:] == sorted_items def test_list_model_len(): model = Gio.ListStore.new(Item) assert len(model) == 0 assert not model for i in range(1, 10): model.append(Item()) assert len(model) == i assert model model.remove_all() assert not model assert len(model) == 0 def test_list_model_get_item_simple(): model = Gio.ListStore.new(Item) with pytest.raises(IndexError): model[0] first_item = Item() model.append(first_item) assert model[0] is first_item assert model[-1] is first_item second_item = Item() model.append(second_item) assert model[1] is second_item assert model[-1] is second_item assert model[-2] is first_item with pytest.raises(IndexError): model[-3] with pytest.raises(TypeError): model[object()] def test_list_model_get_item_slice(): model = Gio.ListStore.new(Item) source = [Item() for i in range(30)] for i in source: model.append(i) assert model[1:10] == source[1:10] assert model[1:-2] == source[1:-2] assert model[-4:-1] == source[-4:-1] assert model[-100:-1] == source[-100:-1] assert model[::-1] == source[::-1] assert model[:] == source[:] def test_list_model_contains(): model = Gio.ListStore.new(Item) item = Item() model.append(item) assert item in model assert Item() not in model with pytest.raises(TypeError): object() in model with pytest.raises(TypeError): None in model def test_list_model_iter(): model = Gio.ListStore.new(Item) item = Item() model.append(item) it = iter(model) assert next(it) is item repr(item) def test_list_store_delitem_simple(): store = Gio.ListStore.new(Item) store.append(Item()) del store[0] assert not store with pytest.raises(IndexError): del store[0] with pytest.raises(IndexError): del store[-1] store.append(Item()) with pytest.raises(IndexError): del store[-2] del store[-1] assert not store source = [Item(), Item()] store.append(source[0]) store.append(source[1]) del store[-1] assert store[:] == [source[0]] with pytest.raises(TypeError): del store[object()] def test_list_store_delitem_slice(): def do_del(count, key): events = [] def on_changed(m, *args): events.append(args) store = Gio.ListStore.new(Item) source = [Item() for i in range(count)] for item in source: store.append(item) store.connect("items-changed", on_changed) source.__delitem__(key) store.__delitem__(key) assert source == store[:] return events values = [None, 1, -15, 3, -2, 0, -3, 5, 7] variants = set() for i in range(500): start = random.choice(values) stop = random.choice(values) step = random.choice(values) length = abs(random.choice(values) or 0) if step == 0: step += 1 variants.add((length, start, stop, step)) for length, start, stop, step in variants: do_del(length, slice(start, stop, step)) # basics do_del(10, slice(None, None, None)) do_del(10, slice(None, None, None)) do_del(10, slice(None, None, -1)) do_del(10, slice(0, 5, None)) do_del(10, slice(0, 10, 1)) do_del(10, slice(0, 10, 2)) do_del(10, slice(14, 2, -1)) # test some fast paths assert do_del(100, slice(None, None, None)) == [(0, 100, 0)] assert do_del(100, slice(None, None, -1)) == [(0, 100, 0)] assert do_del(100, slice(0, 50, 1)) == [(0, 50, 0)] def test_list_store_setitem_simple(): store = Gio.ListStore.new(Item) first = Item() store.append(first) class Wrong(GObject.Object): pass with pytest.raises(TypeError): store[0] = object() with pytest.raises(TypeError): store[0] = None with pytest.raises(TypeError): store[0] = Wrong() assert store[:] == [first] new = Item() store[0] = new assert len(store) == 1 store[-1] = Item() assert len(store) == 1 with pytest.raises(IndexError): store[1] = Item() with pytest.raises(IndexError): store[-2] = Item() store = Gio.ListStore.new(Item) source = [Item(), Item(), Item()] for item in source: store.append(item) new = Item() store[1] = new assert store[:] == [source[0], new, source[2]] with pytest.raises(TypeError): store[object()] = Item() def test_list_store_setitem_slice(): def do_set(count, key, new_count): if ( count == 0 and key.step is not None and platform.python_implementation() == "PyPy" ): # https://foss.heptapod.net/pypy/pypy/-/issues/2804 return store = Gio.ListStore.new(Item) source = [Item() for i in range(count)] new = [Item() for i in range(new_count)] for item in source: store.append(item) source_error = None try: source.__setitem__(key, new) except ValueError as e: source_error = type(e) store_error = None try: store.__setitem__(key, new) except Exception as e: store_error = type(e) assert source_error == store_error assert source == store[:] values = [None, 1, -15, 3, -2, 0, 3, 4, 100] variants = set() for i in range(500): start = random.choice(values) stop = random.choice(values) step = random.choice(values) length = abs(random.choice(values) or 0) new = random.choice(values) or 0 if step == 0: step += 1 variants.add((length, start, stop, step, new)) for length, start, stop, step, new in variants: do_set(length, slice(start, stop, step), new) # basics do_set(10, slice(None, None, None), 20) do_set(10, slice(None, None, None), 0) do_set(10, slice(None, None, -1), 20) do_set(10, slice(None, None, -1), 10) do_set(10, slice(0, 5, None), 20) do_set(10, slice(0, 10, 1), 0) # test iterators store = Gio.ListStore.new(Item) store[:] = iter([Item() for i in range(10)]) assert len(store) == 10 # make sure we do all or nothing store = Gio.ListStore.new(Item) with pytest.raises(TypeError): store[:] = [Item(), object()] assert len(store) == 0 def test_action_map_add_action_entries(): actionmap = Gio.SimpleActionGroup() test_data = [] def f(action, parameter, data): test_data.append("test back") actionmap.add_action_entries( ( ("simple", f), ("with_type", f, "i"), ("with_state", f, "s", "'left'", f), ) ) assert actionmap.has_action("simple") assert actionmap.has_action("with_type") assert actionmap.has_action("with_state") actionmap.add_action_entries((("with_user_data", f),), "user_data") assert actionmap.has_action("with_user_data") with pytest.raises(TypeError): actionmap.add_action_entries((("invaild_type_string", f, "asdf"),)) with pytest.raises(ValueError): actionmap.add_action_entries( (("stateless_with_change_state", f, None, None, f),) ) actionmap.activate_action("simple") assert test_data[0] == "test back" def test_types_init_warn(): types = [ Gio.DBusAnnotationInfo, Gio.DBusArgInfo, Gio.DBusMethodInfo, Gio.DBusSignalInfo, Gio.DBusInterfaceInfo, Gio.DBusNodeInfo, ] for t in types: with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") t() assert issubclass(warn[0].category, PyGIWarning) def test_file_fspath(): file, stream = Gio.File.new_tmp("TestGFile.XXXXXX") content = b"hello\0world\x7f!" stream.get_output_stream().write_bytes(GLib.Bytes(content)) stream.close() path = file.peek_path() assert isinstance(path, str) fspath = file.__fspath__() assert isinstance(fspath, str) assert fspath == path with open(file, "rb") as file_like: assert file_like.read() == content def test_file_fspath_with_no_path(): file = Gio.File.new_for_path("") path = file.peek_path() # In older versions of GLib, creating a GFile for an empty path will result # in one representing the current pwd instead of a GDummyFile with no path. if path is None: with pytest.raises(TypeError): file.__fspath__() else: assert path == file.__fspath__() assert path == os.getcwd() @pytest.mark.skipif( not hasattr(Gio.ListStore, "find_with_equal_func_full"), reason="ListStore.find_with_equal_func_full() is available in Gio 2.74", ) def test_list_store_find_with_equal_func(): def test(*user_data): class TestObject(GObject.Object): def __init__(self, val): super().__init__() self.val = val NUM = 5 data = [TestObject(i) for i in range(NUM)] list_store = Gio.ListStore() for d in data: list_store.append(d) def equal_func(a, b, *data): assert data == user_data return a.val == b.val for i in range(NUM): res, position = list_store.find_with_equal_func( data[i], equal_func, *user_data ) assert res assert position == i not_in_list_store = TestObject(NUM + 1) res, position = list_store.find_with_equal_func( not_in_list_store, equal_func, *user_data ) assert not res test() test((100, "data")) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_overrides_glib.py0000664000000000000000000006642015074673150020130 0ustar00rootrootimport os import gc import unittest import tempfile import socket import pytest import gi from gi.repository import GLib from .helper import capture_gi_deprecation_warnings def test_io_add_watch_get_args(): get_args = GLib._io_add_watch_get_args def func(): return None # create a closed channel for testing fd, fn = tempfile.mkstemp() os.close(fd) try: chan = GLib.IOChannel(filename=fn) chan.shutdown(True) finally: os.remove(fn) # old way with capture_gi_deprecation_warnings(): assert get_args(chan, GLib.IOCondition.IN, func) == ( chan, 0, GLib.IOCondition.IN, func, (), ) with pytest.raises(TypeError): get_args(chan, GLib.IOCondition.IN, object()) # new way prio = GLib.PRIORITY_DEFAULT with capture_gi_deprecation_warnings(): assert get_args(chan, prio, GLib.IOCondition.IN, func, 99) == ( chan, prio, GLib.IOCondition.IN, func, (99,), ) with pytest.raises(TypeError): assert get_args(chan, prio, GLib.IOCondition.IN) with pytest.raises(TypeError): assert get_args(chan, prio, 99) @pytest.mark.skipif(os.name != "nt", reason="windows only") def test_io_add_watch_get_args_win32_socket(): get_args = GLib._io_add_watch_get_args s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def func(): return None prio = GLib.PRIORITY_DEFAULT chan = get_args(s, prio, GLib.IOCondition.IN, func)[0] assert isinstance(chan, GLib.IOChannel) chan.shutdown(False) def test_threads_init(): with capture_gi_deprecation_warnings() as w: GLib.threads_init() assert len(w) def test_gerror_matches(): e = GLib.Error(domain=42, code=24) assert e.matches(42, 24) def test_timeout_add_seconds(): h = GLib.timeout_add_seconds( 100, lambda *x: None, 1, 2, 3, priority=GLib.PRIORITY_HIGH_IDLE ) GLib.source_remove(h) def test_iochannel(): with pytest.raises(TypeError): GLib.IOChannel() def test_iochannel_write(): fd, fn = tempfile.mkstemp() os.close(fd) chan = GLib.IOChannel(filename=fn, mode="r+") try: assert chan.write(b"foo", 2) == 2 chan.seek(0) assert chan.read() == b"fo" finally: chan.shutdown(True) @pytest.mark.skipif(os.name == "nt", reason="unix only") def test_has_unix_signal_add(): with capture_gi_deprecation_warnings(): GLib.unix_signal_add == GLib.unix_signal_add_full @pytest.mark.skipif(os.name != "nt", reason="windows only") def test_iochannel_win32(): fd, fn = tempfile.mkstemp() closed = False try: channel = GLib.IOChannel(hwnd=fd) try: assert channel.read() == b"" finally: closed = True channel.shutdown(True) finally: if not closed: os.close(fd) os.remove(fn) class TestGVariant(unittest.TestCase): def test_create_simple(self): variant = GLib.Variant("i", 42) self.assertTrue(isinstance(variant, GLib.Variant)) self.assertEqual(variant.get_int32(), 42) variant = GLib.Variant("s", "") self.assertTrue(isinstance(variant, GLib.Variant)) self.assertEqual(variant.get_string(), "") variant = GLib.Variant("s", "hello") self.assertTrue(isinstance(variant, GLib.Variant)) self.assertEqual(variant.get_string(), "hello") def test_simple_invalid_ops(self): variant = GLib.Variant("i", 42) with pytest.raises(TypeError): len(variant) with pytest.raises(TypeError): variant[0] with pytest.raises(TypeError): variant.keys() def test_create_variant(self): variant = GLib.Variant("v", GLib.Variant("i", 42)) self.assertTrue(isinstance(variant, GLib.Variant)) self.assertTrue(isinstance(variant.get_variant(), GLib.Variant)) self.assertEqual(variant.get_type_string(), "v") self.assertEqual(variant.get_variant().get_type_string(), "i") self.assertEqual(variant.get_variant().get_int32(), 42) variant = GLib.Variant("v", GLib.Variant("v", GLib.Variant("i", 42))) self.assertEqual(variant.get_type_string(), "v") self.assertEqual(variant.get_variant().get_type_string(), "v") self.assertEqual(variant.get_variant().get_variant().get_type_string(), "i") self.assertEqual(variant.get_variant().get_variant().get_int32(), 42) def test_create_tuple(self): variant = GLib.Variant("()", ()) self.assertEqual(variant.get_type_string(), "()") self.assertEqual(variant.n_children(), 0) variant = GLib.Variant("(i)", (3,)) self.assertEqual(variant.get_type_string(), "(i)") self.assertTrue(isinstance(variant, GLib.Variant)) self.assertEqual(variant.n_children(), 1) self.assertTrue(isinstance(variant.get_child_value(0), GLib.Variant)) self.assertEqual(variant.get_child_value(0).get_int32(), 3) variant = GLib.Variant("(ss)", ("mec", "mac")) self.assertEqual(variant.get_type_string(), "(ss)") self.assertTrue(isinstance(variant, GLib.Variant)) self.assertTrue(isinstance(variant.get_child_value(0), GLib.Variant)) self.assertTrue(isinstance(variant.get_child_value(1), GLib.Variant)) self.assertEqual(variant.get_child_value(0).get_string(), "mec") self.assertEqual(variant.get_child_value(1).get_string(), "mac") # nested tuples variant = GLib.Variant("((si)(ub))", (("hello", -1), (42, True))) self.assertEqual(variant.get_type_string(), "((si)(ub))") self.assertEqual(variant.unpack(), (("hello", -1), (42, True))) def test_new_tuple_sink(self): # https://bugzilla.gnome.org/show_bug.cgi?id=735166 variant = GLib.Variant.new_tuple(GLib.Variant.new_tuple()) del variant gc.collect() def test_create_dictionary(self): variant = GLib.Variant("a{si}", {}) self.assertTrue(isinstance(variant, GLib.Variant)) self.assertEqual(variant.get_type_string(), "a{si}") self.assertEqual(variant.n_children(), 0) variant = GLib.Variant("a{si}", {"": 1, "key1": 2, "key2": 3}) self.assertEqual(variant.get_type_string(), "a{si}") self.assertTrue(isinstance(variant, GLib.Variant)) self.assertTrue(isinstance(variant.get_child_value(0), GLib.Variant)) self.assertTrue(isinstance(variant.get_child_value(1), GLib.Variant)) self.assertTrue(isinstance(variant.get_child_value(2), GLib.Variant)) self.assertEqual(variant.unpack(), {"": 1, "key1": 2, "key2": 3}) # nested dictionaries variant = GLib.Variant("a{sa{si}}", {}) self.assertTrue(isinstance(variant, GLib.Variant)) self.assertEqual(variant.get_type_string(), "a{sa{si}}") self.assertEqual(variant.n_children(), 0) d = {"": {"": 1, "keyn1": 2}, "key1": {"key11": 11, "key12": 12}} variant = GLib.Variant("a{sa{si}}", d) self.assertEqual(variant.get_type_string(), "a{sa{si}}") self.assertTrue(isinstance(variant, GLib.Variant)) self.assertEqual(variant.unpack(), d) # init with an iterable variant = GLib.Variant("a{si}", [("foo", 2)]) assert variant.unpack() == {"foo": 2} with pytest.raises(TypeError): GLib.Variant("a{si}", [("foo",)]) with pytest.raises(TypeError): GLib.Variant("a{si}", [("foo", 1, 2)]) def test_create_array(self): variant = GLib.Variant("ai", []) self.assertEqual(variant.get_type_string(), "ai") self.assertEqual(variant.n_children(), 0) variant = GLib.Variant("ai", [1, 2]) self.assertEqual(variant.get_type_string(), "ai") self.assertTrue(isinstance(variant, GLib.Variant)) self.assertTrue(isinstance(variant.get_child_value(0), GLib.Variant)) self.assertTrue(isinstance(variant.get_child_value(1), GLib.Variant)) self.assertEqual(variant.get_child_value(0).get_int32(), 1) self.assertEqual(variant.get_child_value(1).get_int32(), 2) variant = GLib.Variant("as", []) self.assertEqual(variant.get_type_string(), "as") self.assertEqual(variant.n_children(), 0) variant = GLib.Variant("as", [""]) self.assertEqual(variant.get_type_string(), "as") self.assertTrue(isinstance(variant, GLib.Variant)) self.assertTrue(isinstance(variant.get_child_value(0), GLib.Variant)) self.assertEqual(variant.get_child_value(0).get_string(), "") variant = GLib.Variant("as", ["hello", "world"]) self.assertEqual(variant.get_type_string(), "as") self.assertTrue(isinstance(variant, GLib.Variant)) self.assertTrue(isinstance(variant.get_child_value(0), GLib.Variant)) self.assertTrue(isinstance(variant.get_child_value(1), GLib.Variant)) self.assertEqual(variant.get_child_value(0).get_string(), "hello") self.assertEqual(variant.get_child_value(1).get_string(), "world") # nested arrays variant = GLib.Variant("aai", []) self.assertEqual(variant.get_type_string(), "aai") self.assertEqual(variant.n_children(), 0) variant = GLib.Variant("aai", [[]]) self.assertEqual(variant.get_type_string(), "aai") self.assertEqual(variant.n_children(), 1) self.assertEqual(variant.get_child_value(0).n_children(), 0) variant = GLib.Variant("aai", [[1, 2], [3, 4, 5]]) self.assertEqual(variant.get_type_string(), "aai") self.assertEqual(variant.unpack(), [[1, 2], [3, 4, 5]]) def test_create_array_guchar(self): variant = GLib.Variant("ay", [97, 97, 97]) assert variant.unpack() == [97, 97, 97] variant = GLib.Variant("ay", b"aaa") assert variant.unpack() == [97, 97, 97] variant = GLib.Variant("ay", iter([1, 2, 3])) assert variant.unpack() == [1, 2, 3] with self.assertRaises(TypeError): GLib.Variant("ay", "aaa") with self.assertRaises(TypeError): GLib.Variant("ay", object()) def test_create_maybe(self): variant = GLib.Variant("mai", None) self.assertEqual(variant.get_type_string(), "mai") self.assertEqual(variant.n_children(), 0) self.assertEqual(variant.unpack(), None) variant = GLib.Variant("mai", []) self.assertEqual(variant.get_type_string(), "mai") self.assertEqual(variant.n_children(), 1) variant = GLib.Variant("mami", [None]) self.assertEqual(variant.get_type_string(), "mami") self.assertEqual(variant.n_children(), 1) variant = GLib.Variant("mami", [None, 13, None]) self.assertEqual(variant.get_type_string(), "mami") self.assertEqual(variant.n_children(), 1) array = variant.get_child_value(0) self.assertEqual(array.n_children(), 3) element = array.get_child_value(0) self.assertEqual(element.n_children(), 0) element = array.get_child_value(1) self.assertEqual(element.n_children(), 1) self.assertEqual(element.get_child_value(0).get_int32(), 13) element = array.get_child_value(2) self.assertEqual(element.n_children(), 0) def test_create_complex(self): variant = GLib.Variant("(as)", ([],)) self.assertEqual(variant.get_type_string(), "(as)") self.assertEqual(variant.n_children(), 1) self.assertEqual(variant.get_child_value(0).n_children(), 0) variant = GLib.Variant("(as)", ([""],)) self.assertEqual(variant.get_type_string(), "(as)") self.assertEqual(variant.n_children(), 1) self.assertEqual(variant.get_child_value(0).n_children(), 1) self.assertEqual(variant.get_child_value(0).get_child_value(0).get_string(), "") variant = GLib.Variant("(as)", (["hello"],)) self.assertEqual(variant.get_type_string(), "(as)") self.assertEqual(variant.n_children(), 1) self.assertEqual(variant.get_child_value(0).n_children(), 1) self.assertEqual( variant.get_child_value(0).get_child_value(0).get_string(), "hello" ) variant = GLib.Variant("a(ii)", []) self.assertEqual(variant.get_type_string(), "a(ii)") self.assertEqual(variant.n_children(), 0) variant = GLib.Variant("a(ii)", [(5, 6)]) self.assertEqual(variant.get_type_string(), "a(ii)") self.assertEqual(variant.n_children(), 1) self.assertEqual(variant.get_child_value(0).n_children(), 2) self.assertEqual(variant.get_child_value(0).get_child_value(0).get_int32(), 5) self.assertEqual(variant.get_child_value(0).get_child_value(1).get_int32(), 6) variant = GLib.Variant("(a(ii))", ([],)) self.assertEqual(variant.get_type_string(), "(a(ii))") self.assertEqual(variant.n_children(), 1) self.assertEqual(variant.get_child_value(0).n_children(), 0) variant = GLib.Variant("(a(ii))", ([(5, 6)],)) self.assertEqual(variant.get_type_string(), "(a(ii))") self.assertEqual(variant.n_children(), 1) self.assertEqual(variant.get_child_value(0).n_children(), 1) self.assertEqual(variant.get_child_value(0).get_child_value(0).n_children(), 2) self.assertEqual( variant.get_child_value(0) .get_child_value(0) .get_child_value(0) .get_int32(), 5, ) self.assertEqual( variant.get_child_value(0) .get_child_value(0) .get_child_value(1) .get_int32(), 6, ) obj = {"a1": (1, True), "a2": (2, False)} variant = GLib.Variant("a{s(ib)}", obj) self.assertEqual(variant.get_type_string(), "a{s(ib)}") self.assertEqual(variant.unpack(), obj) obj = {"a1": (1, GLib.Variant("b", True)), "a2": (2, GLib.Variant("y", 255))} variant = GLib.Variant("a{s(iv)}", obj) self.assertEqual(variant.get_type_string(), "a{s(iv)}") self.assertEqual(variant.unpack(), {"a1": (1, True), "a2": (2, 255)}) obj = (1, {"a": {"a1": True, "a2": False}, "b": {"b1": False}, "c": {}}, "foo") variant = GLib.Variant("(ia{sa{sb}}s)", obj) self.assertEqual(variant.get_type_string(), "(ia{sa{sb}}s)") self.assertEqual(variant.unpack(), obj) obj = { "frequency": GLib.Variant("t", 738000000), "hierarchy": GLib.Variant("i", 0), "bandwidth": GLib.Variant("x", 8), "code-rate-hp": GLib.Variant("d", 2.0 / 3.0), "constellation": GLib.Variant("s", "QAM16"), "guard-interval": GLib.Variant("u", 4), } variant = GLib.Variant("a{sv}", obj) self.assertEqual(variant.get_type_string(), "a{sv}") self.assertEqual( variant.unpack(), { "frequency": 738000000, "hierarchy": 0, "bandwidth": 8, "code-rate-hp": 2.0 / 3.0, "constellation": "QAM16", "guard-interval": 4, }, ) def test_create_errors(self): # excess arguments self.assertRaises(TypeError, GLib.Variant, "i", 42, 3) self.assertRaises(TypeError, GLib.Variant, "(i)", (42, 3)) # not enough arguments self.assertRaises(TypeError, GLib.Variant, "(ii)", (42,)) # data type mismatch self.assertRaises(TypeError, GLib.Variant, "i", "hello") self.assertRaises(TypeError, GLib.Variant, "s", 42) self.assertRaises(TypeError, GLib.Variant, "(ss)", "mec", "mac") self.assertRaises(TypeError, GLib.Variant, "(s)", "hello") # invalid format string self.assertRaises(TypeError, GLib.Variant, "Q", 1) # invalid types self.assertRaises(TypeError, GLib.Variant, "(ii", (42, 3)) self.assertRaises(TypeError, GLib.Variant, "(ii))", (42, 3)) self.assertRaises(TypeError, GLib.Variant, "a{si", {}) self.assertRaises(TypeError, GLib.Variant, "a{si}}", {}) self.assertRaises(TypeError, GLib.Variant, "a{iii}", {}) def test_unpack(self): # simple values res = GLib.Variant.new_int32(-42).unpack() self.assertEqual(res, -42) res = GLib.Variant.new_uint64(34359738368).unpack() self.assertEqual(res, 34359738368) res = GLib.Variant.new_boolean(True).unpack() self.assertEqual(res, True) res = GLib.Variant.new_object_path("/foo/Bar").unpack() self.assertEqual(res, "/foo/Bar") # variant res = GLib.Variant("v", GLib.Variant.new_int32(-42)).unpack() self.assertEqual(res, -42) GLib.Variant("v", GLib.Variant("v", GLib.Variant("i", 42))) self.assertEqual(res, -42) # tuple res = GLib.Variant.new_tuple( GLib.Variant.new_int32(-1), GLib.Variant.new_string("hello") ).unpack() self.assertEqual(res, (-1, "hello")) # array vb = GLib.VariantBuilder.new(gi._gi.variant_type_from_string("ai")) vb.add_value(GLib.Variant.new_int32(-1)) vb.add_value(GLib.Variant.new_int32(3)) res = vb.end().unpack() self.assertEqual(res, [-1, 3]) # dictionary res = GLib.Variant("a{si}", {"key1": 1, "key2": 2}).unpack() self.assertEqual(res, {"key1": 1, "key2": 2}) # maybe v = GLib.Variant("mi", 1) self.assertEqual(v.unpack(), 1) v = GLib.Variant("mi", None) self.assertEqual(v.unpack(), None) v = GLib.Variant("mai", []) self.assertEqual(v.unpack(), []) v = GLib.Variant("m()", ()) self.assertEqual(v.unpack(), ()) v = GLib.Variant("mami", [None, 1, None]) self.assertEqual(v.unpack(), [None, 1, None]) def test_iteration(self): # array index access vb = GLib.VariantBuilder.new(gi._gi.variant_type_from_string("ai")) vb.add_value(GLib.Variant.new_int32(-1)) vb.add_value(GLib.Variant.new_int32(3)) v = vb.end() self.assertEqual(len(v), 2) self.assertEqual(v[0], -1) self.assertEqual(v[1], 3) self.assertEqual(v[-1], 3) self.assertEqual(v[-2], -1) self.assertRaises(IndexError, v.__getitem__, 2) self.assertRaises(IndexError, v.__getitem__, -3) self.assertRaises(ValueError, v.__getitem__, "a") # array iteration self.assertEqual(list(v), [-1, 3]) self.assertEqual(list(v), [-1, 3]) # tuple index access v = GLib.Variant.new_tuple( GLib.Variant.new_int32(-1), GLib.Variant.new_string("hello") ) self.assertEqual(len(v), 2) self.assertEqual(v[0], -1) self.assertEqual(v[1], "hello") self.assertEqual(v[-1], "hello") self.assertEqual(v[-2], -1) self.assertRaises(IndexError, v.__getitem__, 2) self.assertRaises(IndexError, v.__getitem__, -3) self.assertRaises(ValueError, v.__getitem__, "a") # tuple iteration self.assertEqual(list(v), [-1, "hello"]) self.assertEqual(tuple(v), (-1, "hello")) # dictionary index access vsi = GLib.Variant("a{si}", {"key1": 1, "key2": 2}) vis = GLib.Variant("a{is}", {1: "val1", 5: "val2"}) self.assertEqual(len(vsi), 2) self.assertEqual(vsi["key1"], 1) self.assertEqual(vsi["key2"], 2) self.assertRaises(KeyError, vsi.__getitem__, "unknown") self.assertEqual(len(vis), 2) self.assertEqual(vis[1], "val1") self.assertEqual(vis[5], "val2") self.assertRaises(KeyError, vsi.__getitem__, 3) # dictionary iteration self.assertEqual(set(vsi.keys()), {"key1", "key2"}) self.assertEqual(set(vis.keys()), {1, 5}) # string index access v = GLib.Variant("s", "hello") self.assertEqual(len(v), 5) self.assertEqual(v[0], "h") self.assertEqual(v[4], "o") self.assertEqual(v[-1], "o") self.assertEqual(v[-5], "h") self.assertRaises(IndexError, v.__getitem__, 5) self.assertRaises(IndexError, v.__getitem__, -6) # string iteration self.assertEqual(list(v), ["h", "e", "l", "l", "o"]) def test_split_signature(self): self.assertEqual(GLib.Variant.split_signature("()"), []) self.assertEqual(GLib.Variant.split_signature("s"), ["s"]) self.assertEqual(GLib.Variant.split_signature("as"), ["as"]) self.assertEqual(GLib.Variant.split_signature("(s)"), ["s"]) self.assertEqual(GLib.Variant.split_signature("(iso)"), ["i", "s", "o"]) self.assertEqual( GLib.Variant.split_signature("(s(ss)i(ii))"), ["s", "(ss)", "i", "(ii)"] ) self.assertEqual(GLib.Variant.split_signature("(as)"), ["as"]) self.assertEqual( GLib.Variant.split_signature("(s(ss)iaiaasa(ii))"), ["s", "(ss)", "i", "ai", "aas", "a(ii)"], ) self.assertEqual( GLib.Variant.split_signature("(a{iv}(ii)((ss)a{s(ss)}))"), ["a{iv}", "(ii)", "((ss)a{s(ss)})"], ) def test_hash(self): v1 = GLib.Variant("s", "somestring") v2 = GLib.Variant("s", "somestring") v3 = GLib.Variant("s", "somestring2") self.assertTrue(v2 in {v1, v3}) self.assertTrue(v2 in frozenset([v1, v3])) self.assertTrue(v2 in {v1: "1", v3: "2"}) def test_compare(self): # Check if identical GVariant are equal def assert_equal(vtype, value): self.assertEqual(GLib.Variant(vtype, value), GLib.Variant(vtype, value)) def assert_not_equal(vtype1, value1, vtype2, value2): self.assertNotEqual( GLib.Variant(vtype1, value1), GLib.Variant(vtype2, value2) ) numbers = ["y", "n", "q", "i", "u", "x", "t", "h", "d"] for num in numbers: assert_equal(num, 42) assert_not_equal(num, 42, num, 41) assert_not_equal(num, 42, "s", "42") assert_equal("s", "something") assert_not_equal("s", "something", "s", "somethingelse") assert_not_equal("s", "something", "i", 1234) assert_equal("g", "dustybinqhogx") assert_not_equal("g", "dustybinqhogx", "g", "dustybin") assert_not_equal("g", "dustybinqhogx", "i", 1234) assert_equal("o", "/dev/null") assert_not_equal("o", "/dev/null", "o", "/dev/zero") assert_not_equal("o", "/dev/null", "i", 1234) assert_equal("(s)", ("strtuple",)) assert_not_equal("(s)", ("strtuple",), "(s)", ("strtuple2",)) assert_equal("a{si}", {"str": 42}) assert_not_equal("a{si}", {"str": 42}, "a{si}", {"str": 43}) assert_equal("v", GLib.Variant("i", 42)) assert_not_equal("v", GLib.Variant("i", 42), "v", GLib.Variant("i", 43)) assert GLib.Variant("i", 42) != object() assert GLib.Variant("i", 42) != object() def test_bool(self): # Check if the GVariant bool matches the unpacked Pythonic bool def assert_equals_bool(vtype, value): self.assertEqual(bool(GLib.Variant(vtype, value)), bool(value)) # simple values assert_equals_bool("b", True) assert_equals_bool("b", False) numbers = ["y", "n", "q", "i", "u", "x", "t", "h", "d"] for number in numbers: assert_equals_bool(number, 0) assert_equals_bool(number, 1) assert_equals_bool("s", "") assert_equals_bool("g", "") assert_equals_bool("s", "something") assert_equals_bool("o", "/dev/null") assert_equals_bool("g", "dustybinqhogx") # arrays assert_equals_bool("ab", [True]) assert_equals_bool("ab", [False]) for number in numbers: assert_equals_bool("a" + number, []) assert_equals_bool("a" + number, [0]) assert_equals_bool("as", []) assert_equals_bool("as", [""]) assert_equals_bool("ao", []) assert_equals_bool("ao", ["/"]) assert_equals_bool("ag", []) assert_equals_bool("ag", [""]) assert_equals_bool("aai", [[]]) # tuples assert_equals_bool("()", ()) for number in numbers: assert_equals_bool("(" + number + ")", (0,)) assert_equals_bool("(s)", ("",)) assert_equals_bool("(o)", ("/",)) assert_equals_bool("(g)", ("",)) assert_equals_bool("(())", ((),)) # dictionaries assert_equals_bool("a{si}", {}) assert_equals_bool("a{si}", {"": 0}) # complex types, always True assert_equals_bool("(as)", ([],)) assert_equals_bool("a{s(i)}", {"": (0,)}) # variant types, recursive unpacking assert_equals_bool("v", GLib.Variant("i", 0)) assert_equals_bool("v", GLib.Variant("i", 1)) # maybe types assert_equals_bool("mi", 42) assert_equals_bool("mi", 0) assert_equals_bool("mi", None) def test_repr(self): # with C constructor v = GLib.Variant.new_uint32(42) self.assertEqual(repr(v), "GLib.Variant('u', 42)") # with override constructor v = GLib.Variant("(is)", (1, "somestring")) self.assertEqual(repr(v), "GLib.Variant('(is)', (1, 'somestring'))") def test_str(self): # with C constructor v = GLib.Variant.new_uint32(42) self.assertEqual(str(v), "uint32 42") # with override constructor v = GLib.Variant("(is)", (1, "somestring")) self.assertEqual(str(v), "(1, 'somestring')") def test_parse_error(self): # This test doubles as a test for GLib.Error marshaling. source_str = "abc" with self.assertRaises(GLib.Error) as context: GLib.Variant.parse(None, source_str, None, None) e = context.exception text = GLib.Variant.parse_error_print_context(e, source_str) self.assertTrue(source_str in text) def test_parse_error_exceptions(self): source_str = "abc" self.assertRaisesRegex( TypeError, "Must be GLib.Error, not int", GLib.Variant.parse_error_print_context, 42, source_str, ) gerror = GLib.Error(message=42) # not a string self.assertRaisesRegex( TypeError, ".*Must be string, not int.*", GLib.Variant.parse_error_print_context, gerror, source_str, ) gerror = GLib.Error(domain=42) # not a string self.assertRaisesRegex( TypeError, ".*Must be string, not int.*", GLib.Variant.parse_error_print_context, gerror, source_str, ) gerror = GLib.Error(code="not an int") self.assertRaisesRegex( TypeError, ".*Must be number, not str.*", GLib.Variant.parse_error_print_context, gerror, source_str, ) gerror = GLib.Error(code=GLib.MAXUINT) self.assertRaisesRegex( OverflowError, ".*not in range.*", GLib.Variant.parse_error_print_context, gerror, source_str, ) class TestConstants(unittest.TestCase): def test_basic_types_limits(self): self.assertTrue(isinstance(GLib.MINFLOAT, float)) self.assertTrue(isinstance(GLib.MAXLONG, int)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_overrides_gobject.py0000664000000000000000000002341515074673150020625 0ustar00rootrootimport pytest from gi import PyGIDeprecationWarning from gi.repository import GObject, GLib, GIMarshallingTests from .helper import ignore_gi_deprecation_warnings def test_stop_emission_deprec(): class TestObject(GObject.GObject): int_prop = GObject.Property(default=0, type=int) obj = TestObject() def notify_callback(obj, *args): with pytest.warns(PyGIDeprecationWarning): obj.stop_emission("notify::int-prop") with pytest.warns(PyGIDeprecationWarning): obj.emit_stop_by_name("notify::int-prop") obj.stop_emission_by_name("notify::int-prop") obj.connect("notify::int-prop", notify_callback) obj.notify("int-prop") def test_signal_parse_name(): obj = GObject.GObject() assert GObject.signal_parse_name("notify", obj, True) == (1, 0) with pytest.raises(ValueError): GObject.signal_parse_name("foobar", obj, True) def test_signal_query(): obj = GObject.GObject() res = GObject.signal_query("notify", obj) assert res.signal_name == "notify" assert res.itype == obj.__gtype__ res = GObject.signal_query("foobar", obj) assert res is None def test_value_repr(): v = GObject.Value() assert repr(v) == "" v = GObject.Value(int, 0) assert repr(v) == "" def test_value_no_init(): v = GObject.Value() with pytest.raises(TypeError): v.set_value(0) v.init(GObject.TYPE_LONG) assert v.get_value() == 0 v.set_value(0) def test_value_invalid_type(): v = GObject.Value() assert v.g_type == GObject.TYPE_INVALID assert isinstance(GObject.TYPE_INVALID, GObject.GType) with pytest.raises(ValueError, match="Invalid GType"): v.init(GObject.TYPE_INVALID) with pytest.raises(TypeError, match=r"GObject.Value needs to be initialized first"): v.set_value(None) assert v.get_value() is None def test_value_long(): v = GObject.Value(GObject.TYPE_LONG) assert v.get_value() == 0 v.set_value(0) assert v.get_value() == 0 v.set_value(GLib.MAXLONG) assert v.get_value() == GLib.MAXLONG v.set_value(GLib.MINLONG) assert v.get_value() == GLib.MINLONG with pytest.raises(OverflowError): v.set_value(GLib.MAXLONG + 1) with pytest.raises(OverflowError): v.set_value(GLib.MINLONG - 1) def test_value_ulong(): v = GObject.Value(GObject.TYPE_ULONG) assert v.get_value() == 0 v.set_value(0) assert v.get_value() == 0 v.set_value(GLib.MAXULONG) assert v.get_value() == GLib.MAXULONG with pytest.raises(OverflowError): v.set_value(GLib.MAXULONG + 1) with pytest.raises(OverflowError): v.set_value(-1) with pytest.raises(TypeError): v.set_value(object()) with pytest.raises(TypeError): v.set_value(None) def test_value_float(): v = GObject.Value(GObject.TYPE_FLOAT) for getter, setter in [(v.get_value, v.set_value), (v.get_float, v.set_float)]: assert getter() == 0.0 setter(0) assert getter() == 0 setter(GLib.MAXFLOAT) assert getter() == GLib.MAXFLOAT setter(GLib.MINFLOAT) assert getter() == GLib.MINFLOAT setter(-GLib.MAXFLOAT) assert getter() == -GLib.MAXFLOAT with pytest.raises(OverflowError): setter(GLib.MAXFLOAT * 2) with pytest.raises(OverflowError): setter(-GLib.MAXFLOAT * 2) with pytest.raises(TypeError): setter(object()) with pytest.raises(TypeError): setter(None) with pytest.raises(TypeError): setter(1j) v.reset() def test_value_double(): v = GObject.Value(GObject.TYPE_DOUBLE) assert v.get_value() == 0.0 v.set_value(0) assert v.get_value() == 0 v.set_value(GLib.MAXDOUBLE) assert v.get_value() == GLib.MAXDOUBLE v.set_value(GLib.MINDOUBLE) assert v.get_value() == GLib.MINDOUBLE v.set_value(-GLib.MAXDOUBLE) assert v.get_value() == -GLib.MAXDOUBLE with pytest.raises(TypeError): v.set_value(object()) with pytest.raises(TypeError): v.set_value(None) with pytest.raises(TypeError): v.set_value(1j) def test_value_uint64(): v = GObject.Value(GObject.TYPE_UINT64) assert v.get_value() == 0 v.set_value(0) assert v.get_value() == 0 v.set_value(GLib.MAXUINT64) assert v.get_value() == GLib.MAXUINT64 with pytest.raises(OverflowError): v.set_value(GLib.MAXUINT64 + 1) with pytest.raises(OverflowError): v.set_value(-1) def test_value_int64(): v = GObject.Value(GObject.TYPE_INT64) assert v.get_value() == 0 v.set_value(0) assert v.get_value() == 0 v.set_value(GLib.MAXINT64) assert v.get_value() == GLib.MAXINT64 v.set_value(GLib.MININT64) assert v.get_value() == GLib.MININT64 with pytest.raises(OverflowError): v.set_value(GLib.MAXINT64 + 1) with pytest.raises(OverflowError): v.set_value(GLib.MININT64 - 1) with pytest.raises(TypeError): v.set_value(object()) with pytest.raises(TypeError): v.set_value(None) def test_value_pointer(): v = GObject.Value(GObject.TYPE_POINTER) assert v.get_value() == 0 v.set_value(42) assert v.get_value() == 42 v.set_value(0) assert v.get_value() == 0 def test_value_unichar(): assert GObject.TYPE_UNICHAR == GObject.TYPE_UINT v = GObject.Value(GObject.TYPE_UNICHAR) assert v.get_value() == 0 v.set_value(42) assert v.get_value() == 42 v.set_value(GLib.MAXUINT) assert v.get_value() == GLib.MAXUINT def test_value_gtype(): class TestObject(GObject.GObject): pass v = GObject.Value(GObject.TYPE_GTYPE) assert v.get_value() == GObject.TYPE_INVALID v.set_value(TestObject.__gtype__) assert v.get_value() == TestObject.__gtype__ v.set_value(TestObject) assert v.get_value() == TestObject.__gtype__ with pytest.raises(TypeError): v.set_value(None) def test_value_variant(): v = GObject.Value(GObject.TYPE_VARIANT) assert v.get_value() is None variant = GLib.Variant("i", 42) v.set_value(variant) assert v.get_value() == variant v.set_value(None) assert v.get_value() is None with pytest.raises(TypeError): v.set_value(object()) def test_value_param(): # FIXME: set_value and get_value trigger a critical # GObject.Value(GObject.TYPE_PARAM) pass def test_value_string(): v = GObject.Value(GObject.TYPE_STRING) for getter, setter in [(v.get_value, v.set_value), (v.get_string, v.set_string)]: assert getter() is None with pytest.raises(TypeError): setter(b"bar") setter("quux") assert getter() == "quux" assert isinstance(getter(), str) setter(None) assert getter() is None v.reset() def test_value_pyobject(): class Foo: pass v = GObject.Value(GObject.TYPE_PYOBJECT) assert v.get_value() is None for obj in [Foo(), None, 42, "foo"]: v.set_value(obj) assert v.get_value() == obj @ignore_gi_deprecation_warnings def test_value_char(): v = GObject.Value(GObject.TYPE_CHAR) assert v.get_value() == 0 v.set_value(42) assert v.get_value() == 42 v.set_value(-1) assert v.get_value() == -1 v.set_value(b"a") assert v.get_value() == 97 v.set_value(b"\x00") assert v.get_value() == 0 with pytest.raises(TypeError): v.set_value("a") with pytest.raises(OverflowError): v.set_value(128) def test_value_uchar(): v = GObject.Value(GObject.TYPE_UCHAR) assert v.get_value() == 0 v.set_value(200) assert v.get_value() == 200 v.set_value(b"a") assert v.get_value() == 97 v.set_value(b"\x00") assert v.get_value() == 0 with pytest.raises(TypeError): v.set_value("a") with pytest.raises(OverflowError): v.set_value(256) def test_value_set_boxed_deprecate_non_boxed(): v = GObject.Value(GObject.TYPE_POINTER) with pytest.warns(PyGIDeprecationWarning): v.get_boxed() with pytest.warns(PyGIDeprecationWarning): v.set_boxed(None) def test_value_boolean(): v = GObject.Value(GObject.TYPE_BOOLEAN) for getter, setter in [(v.get_value, v.set_value), (v.get_boolean, v.set_boolean)]: assert getter() is False assert isinstance(getter(), bool) setter(42) assert getter() is True setter(-1) assert getter() is True setter(0) assert getter() is False setter([]) assert getter() is False setter(["foo"]) assert getter() is True setter(None) assert getter() is False v.reset() def test_value_enum(): t = GIMarshallingTests.GEnum v = GObject.Value(t) for getter, setter in [(v.get_value, v.set_value), (v.get_enum, v.set_enum)]: assert v.g_type == t.__gtype__ assert getter() == 0 setter(t.VALUE1) assert getter() == t.VALUE1 # FIXME: we should try to return an enum type assert type(getter()) is int setter(2424242) assert getter() == 2424242 setter(-1) assert getter() == -1 with pytest.raises(TypeError): setter(object()) with pytest.raises(TypeError): setter(None) v.reset() def test_value_object(): v = GObject.Value(GIMarshallingTests.Object) assert v.g_type.is_a(GObject.TYPE_OBJECT) for getter, setter in [(v.get_value, v.set_value), (v.get_object, v.set_object)]: assert getter() is None setter(None) assert getter() is None obj = GIMarshallingTests.Object() setter(obj) assert getter() is obj with pytest.raises(TypeError): setter(object()) v.reset() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_overrides_gtk.py0000664000000000000000000033266115074673150020003 0ustar00rootrootimport contextlib import unittest import sys import gc import warnings import timeit import pytest from .helper import ignore_gi_deprecation_warnings, capture_glib_warnings import gi.overrides import gi.types from gi.repository import Gio, GLib, GObject try: from gi.repository import Gtk, GdkPixbuf, Gdk PyGTKDeprecationWarning = Gtk.PyGTKDeprecationWarning Gtk_version = Gtk._version except ImportError: Gtk = None Gtk_version = None PyGTKDeprecationWarning = None GdkPixbuf = None Gdk = None def gtkver(): if Gtk is None: return (0, 0, 0) return (Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()) GTK4 = Gtk and Gtk._version == "4.0" @contextlib.contextmanager def realized(widget): """Makes sure the widget is realized. view = Gtk.TreeView() with realized(view): do_something(view) """ if isinstance(widget, Gtk.Window): toplevel = widget else: if Gtk._version == "4.0": toplevel = widget.get_parent() else: toplevel = widget.get_parent_window() if toplevel is None: window = Gtk.Window() if Gtk._version == "4.0": window.set_child(widget) else: window.add(widget) window.show() widget.realize() if Gtk._version == "4.0": context = GLib.MainContext() while context.pending(): context.iteration(False) else: while Gtk.events_pending(): Gtk.main_iteration() assert widget.get_realized() yield widget if toplevel is None: if Gtk._version == "4.0": window.set_child(None) else: window.remove(widget) window.destroy() if Gtk._version == "4.0": context = GLib.MainContext() while context.pending(): context.iteration(False) else: while Gtk.events_pending(): Gtk.main_iteration() @unittest.skipUnless(Gtk, "Gtk not available") @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_freeze_child_notif(): events = [] def on_notify(widget, spec): events.append(spec.name) b = Gtk.Box() c = Gtk.Button() c.connect("child-notify", on_notify) c.freeze_child_notify() b.pack_start(c, True, True, 0) b.child_set_property(c, "pack-type", Gtk.PackType.END) b.child_set_property(c, "pack-type", Gtk.PackType.START) c.thaw_child_notify() assert events.count("pack-type") == 1 del events[:] with c.freeze_child_notify(): b.child_set_property(c, "pack-type", Gtk.PackType.END) b.child_set_property(c, "pack-type", Gtk.PackType.START) assert events.count("pack-type") == 1 @unittest.skipUnless(Gtk, "Gtk not available") @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_menu_popup(): m = Gtk.Menu() with capture_glib_warnings(): m.popup(None, None, None, None, 0, 0) m.popdown() @unittest.skipUnless(Gtk, "Gtk not available") @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_button_stock(): with capture_glib_warnings(): button = Gtk.Button(stock=Gtk.STOCK_OK) assert button.props.label == Gtk.STOCK_OK assert button.props.use_stock @unittest.skipUnless(Gtk, "Gtk not available") def test_wrapper_toggle_refs(): BASE = Gtk.Button if not GTK4 else Gtk.Widget class MyWidget(BASE): def __init__(self, height): BASE.__init__(self) self._height = height def do_measure(self, orientation, for_size): if orientation == Gtk.Orientation.VERTICAL: return (self._height, self._height, -1, -1) return (0, 0, -1, -1) def do_get_preferred_height(self): return (self._height, self._height) height = 142 w = Gtk.Window() b = MyWidget(height) if not GTK4: w.add(b) b.show_all() else: w.set_child(b) del b gc.collect() gc.collect() assert w.get_preferred_size().minimum_size.height >= height @unittest.skipUnless(Gtk, "Gtk not available") @ignore_gi_deprecation_warnings class TestGtk(unittest.TestCase): @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_container(self): box = Gtk.Box() self.assertTrue(isinstance(box, Gtk.Box)) self.assertTrue(isinstance(box, Gtk.Container)) self.assertTrue(isinstance(box, Gtk.Widget)) self.assertTrue(box) label = Gtk.Label() label2 = Gtk.Label() box.add(label) box.add(label2) self.assertTrue(label in box) self.assertTrue(label2 in box) self.assertEqual(len(box), 2) self.assertTrue(box) labels = list(box) self.assertEqual(labels, [label, label2]) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_actions(self): self.assertEqual(Gtk.Action, gi.overrides.Gtk.Action) action = Gtk.Action( name="test", label="Test", tooltip="Test Action", stock_id=Gtk.STOCK_COPY ) self.assertEqual(action.get_name(), "test") self.assertEqual(action.get_label(), "Test") self.assertEqual(action.get_tooltip(), "Test Action") self.assertEqual(action.get_stock_id(), Gtk.STOCK_COPY) self.assertEqual(Gtk.RadioAction, gi.overrides.Gtk.RadioAction) action = Gtk.RadioAction( name="test", label="Test", tooltip="Test Action", stock_id=Gtk.STOCK_COPY, value=1, ) self.assertEqual(action.get_name(), "test") self.assertEqual(action.get_label(), "Test") self.assertEqual(action.get_tooltip(), "Test Action") self.assertEqual(action.get_stock_id(), Gtk.STOCK_COPY) self.assertEqual(action.get_current_value(), 1) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_actiongroup(self): self.assertEqual(Gtk.ActionGroup, gi.overrides.Gtk.ActionGroup) action_group = Gtk.ActionGroup(name="TestActionGroup") callback_data = "callback data" def test_action_callback_data(action, user_data): self.assertEqual(user_data, callback_data) def test_radio_action_callback_data(action, current, user_data): self.assertEqual(user_data, callback_data) action_group.add_actions( [ ( "test-action1", None, "Test Action 1", None, None, test_action_callback_data, ), ( "test-action2", Gtk.STOCK_COPY, "Test Action 2", None, None, test_action_callback_data, ), ], callback_data, ) action_group.add_toggle_actions( [ ( "test-toggle-action1", None, "Test Toggle Action 1", None, None, test_action_callback_data, False, ), ( "test-toggle-action2", Gtk.STOCK_COPY, "Test Toggle Action 2", None, None, test_action_callback_data, True, ), ], callback_data, ) action_group.add_radio_actions( [ ("test-radio-action1", None, "Test Radio Action 1"), ("test-radio-action2", Gtk.STOCK_COPY, "Test Radio Action 2"), ], 1, test_radio_action_callback_data, callback_data, ) expected_results = [ ("test-action1", Gtk.Action), ("test-action2", Gtk.Action), ("test-toggle-action1", Gtk.ToggleAction), ("test-toggle-action2", Gtk.ToggleAction), ("test-radio-action1", Gtk.RadioAction), ("test-radio-action2", Gtk.RadioAction), ] for action in action_group.list_actions(): a = (action.get_name(), type(action)) self.assertTrue(a in expected_results) expected_results.remove(a) action.activate() @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_action_group_error_handling(self): action_group = Gtk.ActionGroup(name="TestActionGroup") with pytest.raises(TypeError): action_group.add_actions(42) with pytest.raises(TypeError): action_group.add_toggle_actions(42) with pytest.raises(TypeError): action_group.add_radio_actions(42) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_action_group_no_user_data(self): action_group = Gtk.ActionGroup(name="TestActionGroup") called = [] def test_action_callback_no_data(action): called.append(action) action_group.add_actions( [ ( "test-action1", None, "Test Action 1", None, None, test_action_callback_no_data, ) ] ) action_group.add_actions([("test2-action1",)]) action_group.get_action("test-action1").activate() action_group.add_toggle_actions( [ ( "test-action2", None, "Test Action 2", None, None, test_action_callback_no_data, ) ] ) action_group.add_toggle_actions([("test2-action2",)]) action_group.get_action("test-action2").activate() def test_action_callback_no_data_radio(action, current): called.append(action) action_group.add_radio_actions( [ ("test-action3", None, "Test Action 3", None, None, 0), ("test-action4", None, "Test Action 4", None, None, 1), ], 1, test_action_callback_no_data_radio, ) action_group.add_radio_actions([("test2-action3",)]) action = action_group.get_action("test-action3") assert action.get_current_value() == 1 action.activate() assert len(called) == 3 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_uimanager(self): self.assertEqual(Gtk.UIManager, gi.overrides.Gtk.UIManager) ui = Gtk.UIManager() ui.add_ui_from_string(""" """) menubar = ui.get_widget("/menubar1") self.assertEqual(type(menubar), Gtk.MenuBar) ag = Gtk.ActionGroup(name="ag1") ui.insert_action_group(ag) ag2 = Gtk.ActionGroup(name="ag2") ui.insert_action_group(ag2) groups = ui.get_action_groups() self.assertEqual(ag, groups[-2]) self.assertEqual(ag2, groups[-1]) with pytest.raises(TypeError): ui.add_ui_from_string(42) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_uimanager_nonascii(self): ui = Gtk.UIManager() ui.add_ui_from_string( b''.decode("UTF-8") ) mi = ui.get_widget("/menubær1") self.assertEqual(type(mi), Gtk.MenuBar) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_window_gtk3(self): # standard Window w = Gtk.Window() self.assertEqual(w.get_property("type"), Gtk.WindowType.TOPLEVEL) # type works as keyword argument w = Gtk.Window(type=Gtk.WindowType.POPUP) self.assertEqual(w.get_property("type"), Gtk.WindowType.POPUP) class TestWindow(Gtk.Window): __gtype_name__ = "TestWindow" # works from builder builder = Gtk.Builder() builder.add_from_string(""" popup popup """) self.assertEqual( builder.get_object("win").get_property("type"), Gtk.WindowType.POPUP ) self.assertEqual( builder.get_object("testwin").get_property("type"), Gtk.WindowType.TOPLEVEL ) self.assertEqual( builder.get_object("testpop").get_property("type"), Gtk.WindowType.POPUP ) @unittest.skipUnless(Gtk_version == "4.0", "no GtkWindowType in gtk4") def test_window_gtk4(self): w = Gtk.Window() # check that setting default size works w.set_default_size(300, 300) self.assertEqual(w.get_default_size(), (300, 300)) class TestWindow(Gtk.Window): __gtype_name__ = "TestWindow" # works from builder builder = Gtk.Builder() builder.add_from_string(""" amazing amazing-test """) self.assertEqual(builder.get_object("win").get_property("css-name"), "amazing") self.assertEqual( builder.get_object("testwin").get_property("css-name"), "amazing-test" ) def test_dialog_classes(self): self.assertEqual(Gtk.Dialog, gi.overrides.Gtk.Dialog) if not GTK4: self.assertEqual(Gtk.FileChooserDialog, gi.overrides.Gtk.FileChooserDialog) self.assertEqual( Gtk.RecentChooserDialog, gi.overrides.Gtk.RecentChooserDialog ) self.assertEqual( Gtk.ColorSelectionDialog, gi.overrides.Gtk.ColorSelectionDialog ) self.assertEqual( Gtk.FontSelectionDialog, gi.overrides.Gtk.FontSelectionDialog ) def test_dialog_base(self): dialog = Gtk.Dialog(title="Foo", modal=True) self.assertTrue(isinstance(dialog, Gtk.Dialog)) self.assertTrue(isinstance(dialog, Gtk.Window)) self.assertEqual("Foo", dialog.get_title()) self.assertTrue(dialog.get_modal()) @unittest.skipIf(GTK4, "flags not in gtk4") def test_dialog_deprecations(self): with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") dialog = Gtk.Dialog(title="Foo", flags=Gtk.DialogFlags.MODAL) self.assertTrue(dialog.get_modal()) self.assertEqual(len(warn), 1) self.assertTrue(issubclass(warn[0].category, PyGTKDeprecationWarning)) self.assertRegex(str(warn[0].message), ".*flags.*modal.*") with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") dialog = Gtk.Dialog(title="Foo", flags=Gtk.DialogFlags.DESTROY_WITH_PARENT) self.assertTrue(dialog.get_destroy_with_parent()) self.assertEqual(len(warn), 1) self.assertTrue(issubclass(warn[0].category, PyGTKDeprecationWarning)) self.assertRegex(str(warn[0].message), ".*flags.*destroy_with_parent.*") @unittest.skipIf(GTK4, "flags not in gtk4") def test_dialog_deprecation_stacklevels(self): # Test warning levels are setup to give the correct filename for # deprecations in different classes in the inheritance hierarchy. # Base class self.assertEqual(Gtk.Dialog, gi.overrides.Gtk.Dialog) with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") Gtk.Dialog(flags=Gtk.DialogFlags.MODAL) self.assertEqual(len(warn), 1) self.assertRegex(warn[0].filename, ".*test_overrides_gtk.*") # Validate overridden base with overridden sub-class. self.assertEqual(Gtk.MessageDialog, gi.overrides.Gtk.MessageDialog) with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") Gtk.MessageDialog(flags=Gtk.DialogFlags.MODAL) self.assertEqual(len(warn), 1) self.assertRegex(warn[0].filename, ".*test_overrides_gtk.*") # Validate overridden base with non-overridden sub-class. self.assertEqual(Gtk.AboutDialog, gi.repository.Gtk.AboutDialog) with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") Gtk.AboutDialog(flags=Gtk.DialogFlags.MODAL) self.assertEqual(len(warn), 1) self.assertRegex(warn[0].filename, ".*test_overrides_gtk.*") def test_dialog_add_buttons(self): if not GTK4: # The overloaded "buttons" keyword gives a warning when attempting # to use it for adding buttons as was available in PyGTK. with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") dialog = Gtk.Dialog( title="Foo", modal=True, buttons=("test-button1", 1) ) self.assertEqual(len(warn), 1) self.assertTrue(issubclass(warn[0].category, PyGTKDeprecationWarning)) self.assertRegex(str(warn[0].message), ".*ButtonsType.*add_buttons.*") else: dialog = Gtk.Dialog() dialog.add_buttons("test-button1", 1) dialog.add_buttons("test-button2", 2, "gtk-close", Gtk.ResponseType.CLOSE) button = dialog.get_widget_for_response(1) self.assertEqual("test-button1", button.get_label()) button = dialog.get_widget_for_response(2) self.assertEqual("test-button2", button.get_label()) button = dialog.get_widget_for_response(Gtk.ResponseType.CLOSE) self.assertEqual("gtk-close", button.get_label()) with pytest.raises(ValueError, match="even number"): dialog.add_buttons("test-button2", 2, "gtk-close") @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_dialog_deprecated_attributes(self): dialog = Gtk.Dialog() assert dialog.action_area == dialog.get_action_area() assert dialog.vbox == dialog.get_content_area() def test_about_dialog(self): dialog = Gtk.AboutDialog() self.assertTrue(isinstance(dialog, Gtk.Window)) if not GTK4: self.assertTrue(isinstance(dialog, Gtk.Dialog)) # AboutDialog is not sub-classed in overrides, make sure # the mro still injects the base class "add_buttons" override. self.assertTrue(hasattr(dialog, "add_buttons")) def test_message_dialog(self): dialog = Gtk.MessageDialog( title="message dialog test", modal=True, buttons=Gtk.ButtonsType.OK, text="dude!", ) self.assertTrue(isinstance(dialog, Gtk.Dialog)) self.assertTrue(isinstance(dialog, Gtk.Window)) self.assertEqual("message dialog test", dialog.get_title()) self.assertTrue(dialog.get_modal()) text = dialog.get_property("text") self.assertEqual("dude!", text) if not GTK4: dialog.format_secondary_text("2nd text") self.assertEqual(dialog.get_property("secondary-text"), "2nd text") self.assertFalse(dialog.get_property("secondary-use-markup")) dialog.format_secondary_markup("2nd markup") self.assertEqual(dialog.get_property("secondary-text"), "2nd markup") self.assertTrue(dialog.get_property("secondary-use-markup")) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_color_selection_dialog(self): dialog = Gtk.ColorSelectionDialog(title="color selection dialog test") self.assertTrue(isinstance(dialog, Gtk.Dialog)) self.assertTrue(isinstance(dialog, Gtk.Window)) self.assertEqual("color selection dialog test", dialog.get_title()) def test_file_chooser_dialog(self): # might cause a GVFS warning, do not break on this with capture_glib_warnings(allow_warnings=True): dialog = Gtk.FileChooserDialog( title="file chooser dialog test", action=Gtk.FileChooserAction.SAVE ) self.assertTrue(isinstance(dialog, Gtk.Dialog)) self.assertTrue(isinstance(dialog, Gtk.Window)) self.assertEqual("file chooser dialog test", dialog.get_title()) action = dialog.get_property("action") self.assertEqual(Gtk.FileChooserAction.SAVE, action) def test_file_chooser_dialog_default_action(self): # might cause a GVFS warning, do not break on this with capture_glib_warnings(allow_warnings=True): dialog = Gtk.FileChooserDialog(title="file chooser dialog test") action = dialog.get_property("action") self.assertEqual(Gtk.FileChooserAction.OPEN, action) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_font_selection_dialog(self): dialog = Gtk.FontSelectionDialog(title="font selection dialog test") self.assertTrue(isinstance(dialog, Gtk.Dialog)) self.assertTrue(isinstance(dialog, Gtk.Window)) self.assertEqual("font selection dialog test", dialog.get_title()) @unittest.skipIf(GTK4, "not in gtk4") def test_recent_chooser_dialog(self): test_manager = Gtk.RecentManager() dialog = Gtk.RecentChooserDialog( title="recent chooser dialog test", recent_manager=test_manager ) self.assertTrue(isinstance(dialog, Gtk.Dialog)) self.assertTrue(isinstance(dialog, Gtk.Window)) self.assertEqual("recent chooser dialog test", dialog.get_title()) class TestClass(GObject.GObject): __gtype_name__ = "GIOverrideTreeAPITest" def __init__(self, tester, int_value, string_value): super().__init__() self.tester = tester self.int_value = int_value self.string_value = string_value def check(self, int_value, string_value): self.tester.assertEqual(int_value, self.int_value) self.tester.assertEqual(string_value, self.string_value) def test_buttons(self): if not GTK4: self.assertEqual(Gtk.Button, gi.overrides.Gtk.Button) # test Gtk.Button button = Gtk.Button() self.assertTrue(isinstance(button, Gtk.Button)) if Gtk._version != "4.0": self.assertTrue(isinstance(button, Gtk.Container)) self.assertTrue(isinstance(button, Gtk.Widget)) if Gtk_version != "4.0": # Using stock items causes hard warning in devel versions of GTK. with capture_glib_warnings(allow_warnings=True): button = Gtk.Button.new_from_stock(Gtk.STOCK_CLOSE) self.assertEqual(Gtk.STOCK_CLOSE, button.get_label()) self.assertTrue(button.get_use_stock()) self.assertTrue(button.get_use_underline()) # test Gtk.Button use_stock button = Gtk.Button( label=Gtk.STOCK_CLOSE, use_stock=True, use_underline=True ) self.assertEqual(Gtk.STOCK_CLOSE, button.get_label()) self.assertTrue(button.get_use_stock()) self.assertTrue(button.get_use_underline()) # test Gtk.LinkButton button = Gtk.LinkButton(uri="http://www.Gtk.org", label="Gtk") self.assertTrue(isinstance(button, Gtk.Button)) if Gtk._version != "4.0": self.assertTrue(isinstance(button, Gtk.Container)) self.assertTrue(isinstance(button, Gtk.Widget)) self.assertEqual("http://www.Gtk.org", button.get_uri()) self.assertEqual("Gtk", button.get_label()) def test_inheritance(self): for name in gi.overrides.Gtk.__all__: over = getattr(gi.overrides.Gtk, name) for element in dir(Gtk): try: klass = getattr(Gtk, element) info = klass.__info__ except (NotImplementedError, AttributeError): continue # Get all parent classes and interfaces klass inherits from if isinstance(info, gi.types.ObjectInfo): classes = list(info.get_interfaces()) parent = info.get_parent() while parent is not None and parent.get_name() != "Object": classes.append(parent) parent = parent.get_parent() classes = [kl for kl in classes if kl.get_namespace() == "Gtk"] else: continue for kl in classes: if kl.get_name() == name: self.assertTrue( issubclass( klass, over, ), f"{klass!r} does not inherit from override {over!r}", ) def test_editable(self): self.assertEqual(Gtk.Editable, gi.overrides.Gtk.Editable) # need to use Gtk.Entry because Editable is an interface entry = Gtk.Entry() pos = entry.insert_text("HeWorld", 0) self.assertEqual(pos, 7) pos = entry.insert_text("llo ", 2) self.assertEqual(pos, 6) text = entry.get_chars(0, 11) self.assertEqual("Hello World", text) def test_label(self): label = Gtk.Label(label="Hello") self.assertTrue(isinstance(label, Gtk.Widget)) self.assertEqual(label.get_text(), "Hello") def adjustment_check( self, adjustment, value=0.0, lower=0.0, upper=0.0, step_increment=0.0, page_increment=0.0, page_size=0.0, ): self.assertEqual(adjustment.get_value(), value) self.assertEqual(adjustment.get_lower(), lower) self.assertEqual(adjustment.get_upper(), upper) self.assertEqual(adjustment.get_step_increment(), step_increment) self.assertEqual(adjustment.get_page_increment(), page_increment) self.assertEqual(adjustment.get_page_size(), page_size) def test_adjustment(self): adjustment = Gtk.Adjustment( value=1, lower=0, upper=6, step_increment=4, page_increment=5, page_size=3 ) self.adjustment_check( adjustment, value=1, lower=0, upper=6, step_increment=4, page_increment=5, page_size=3, ) adjustment = Gtk.Adjustment( value=1, lower=0, upper=6, step_increment=4, page_increment=5 ) self.adjustment_check( adjustment, value=1, lower=0, upper=6, step_increment=4, page_increment=5 ) adjustment = Gtk.Adjustment(value=1, lower=0, upper=6, step_increment=4) self.adjustment_check(adjustment, value=1, lower=0, upper=6, step_increment=4) adjustment = Gtk.Adjustment(value=1, lower=0, upper=6) self.adjustment_check(adjustment, value=1, lower=0, upper=6) adjustment = Gtk.Adjustment() self.adjustment_check(adjustment) if not GTK4: adjustment = Gtk.Adjustment(1, -1, 3, 0, 0, 0) self.adjustment_check(adjustment, value=1, lower=-1, upper=3) adjustment = Gtk.Adjustment(1, -1, 3, 0, 0, 0, value=2) self.adjustment_check(adjustment, value=2, lower=-1, upper=3) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_table(self): table = Gtk.Table() self.assertTrue(isinstance(table, Gtk.Table)) if Gtk._version != "4.0": self.assertTrue(isinstance(table, Gtk.Container)) self.assertTrue(isinstance(table, Gtk.Widget)) self.assertEqual(table.get_size(), (1, 1)) self.assertEqual(table.get_homogeneous(), False) table = Gtk.Table(n_rows=2, n_columns=3) self.assertEqual(table.get_size(), (2, 3)) self.assertEqual(table.get_homogeneous(), False) table = Gtk.Table(n_rows=2, n_columns=3, homogeneous=True) self.assertEqual(table.get_size(), (2, 3)) self.assertEqual(table.get_homogeneous(), True) label = Gtk.Label(label="Hello") self.assertTrue(isinstance(label, Gtk.Widget)) table.attach(label, 0, 1, 0, 1) self.assertEqual(label, table.get_children()[0]) def test_scrolledwindow(self): sw = Gtk.ScrolledWindow() self.assertTrue(isinstance(sw, Gtk.ScrolledWindow)) if Gtk._version != "4.0": self.assertTrue(isinstance(sw, Gtk.Container)) self.assertTrue(isinstance(sw, Gtk.Widget)) sb = sw.get_hscrollbar() self.assertEqual(sw.get_hadjustment(), sb.get_adjustment()) sb = sw.get_vscrollbar() self.assertEqual(sw.get_vadjustment(), sb.get_adjustment()) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_widget_drag_methods(self): widget = Gtk.Button() # here we are not checking functionality, only that the methods exist # and except the right number of arguments widget.drag_check_threshold(0, 0, 0, 0) # drag_dest_ methods widget.drag_dest_set(Gtk.DestDefaults.DROP, None, Gdk.DragAction.COPY) widget.drag_dest_add_image_targets() widget.drag_dest_add_text_targets() widget.drag_dest_add_uri_targets() widget.drag_dest_get_track_motion() widget.drag_dest_set_track_motion(True) widget.drag_dest_get_target_list() widget.drag_dest_set_target_list(None) widget.drag_dest_set_target_list( Gtk.TargetList.new([Gtk.TargetEntry.new("test", 0, 0)]) ) widget.drag_dest_unset() widget.drag_highlight() widget.drag_unhighlight() # drag_source_ methods widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, None, Gdk.DragAction.MOVE) widget.drag_source_add_image_targets() widget.drag_source_add_text_targets() widget.drag_source_add_uri_targets() widget.drag_source_set_icon_name("_About") widget.drag_source_set_icon_pixbuf(GdkPixbuf.Pixbuf()) widget.drag_source_set_icon_stock(Gtk.STOCK_ABOUT) widget.drag_source_get_target_list() widget.drag_source_set_target_list(None) widget.drag_source_set_target_list( Gtk.TargetList.new([Gtk.TargetEntry.new("test", 0, 0)]) ) widget.drag_source_unset() # these methods cannot be called because they require a valid drag on # a real GdkWindow. So we only check that they exist and are callable. self.assertTrue(hasattr(widget, "drag_dest_set_proxy")) self.assertTrue(hasattr(widget, "drag_get_data")) @unittest.skipIf(Gtk_version != "4.0", "gtk4 only") def test_widget_drag_methods_gtk4(self): widget = Gtk.Button() widget.drag_check_threshold(0, 0, 0, 0) # drag source drag_source = Gtk.DragSource() content = Gdk.ContentProvider.new_for_value("data") drag_source.set_content(content) drag_source.set_actions(Gdk.DragAction.COPY) image = Gtk.Image.new_from_icon_name("dialog-warning") drag_source.set_icon(image.get_paintable(), 0, 0) widget.add_controller(drag_source) # drop target drop_target = Gtk.DropTarget.new( Gdk.ContentFormats.new([]), Gdk.DragAction.COPY ) widget.add_controller(drop_target) widget.remove_controller(drag_source) widget.remove_controller(drop_target) @unittest.skipIf(sys.platform == "darwin", "crashes") @unittest.skipIf(GTK4, "uses lots of gtk3 only api") def test_tree_view_drag_target_list_gtk3(self): mixed_target_list = [ Gtk.TargetEntry.new("test0", 0, 0), ("test1", 1, 1), Gtk.TargetEntry.new("test2", 2, 2), ("test3", 3, 3), ] def _test_target_list(targets): for i, target in enumerate(targets): self.assertTrue(isinstance(target, Gtk.TargetEntry)) self.assertEqual(target.target, "test" + str(i)) self.assertEqual(target.flags, i) self.assertEqual(target.info, i) _test_target_list(Gtk._construct_target_list(mixed_target_list)) widget = Gtk.Button() widget.drag_dest_set(Gtk.DestDefaults.DROP, None, Gdk.DragAction.COPY) widget.drag_dest_set_target_list(mixed_target_list) widget.drag_dest_get_target_list() widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, None, Gdk.DragAction.MOVE) widget.drag_source_set_target_list(mixed_target_list) widget.drag_source_get_target_list() treeview = Gtk.TreeView() treeview.enable_model_drag_source( Gdk.ModifierType.BUTTON1_MASK, mixed_target_list, Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE, ) treeview.enable_model_drag_dest( mixed_target_list, Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE ) @unittest.skipUnless(GTK4, "gtk4 only") def test_tree_view_drag_content_formats_gtk4(self): content_formats = Gdk.ContentFormats.new( ["application/json", "GTK_TREE_MODEL_ROW"] ) treeview = Gtk.TreeView() treeview.enable_model_drag_source( Gdk.ModifierType.BUTTON1_MASK, content_formats, Gdk.DragAction.MOVE ) treeview.enable_model_drag_dest(content_formats, Gdk.DragAction.MOVE) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_scrollbar(self): adjustment = Gtk.Adjustment() hscrollbar = Gtk.HScrollbar() vscrollbar = Gtk.VScrollbar() self.assertNotEqual(hscrollbar.props.adjustment, adjustment) self.assertNotEqual(vscrollbar.props.adjustment, adjustment) hscrollbar = Gtk.HScrollbar(adjustment=adjustment) vscrollbar = Gtk.VScrollbar(adjustment=adjustment) self.assertEqual(hscrollbar.props.adjustment, adjustment) self.assertEqual(vscrollbar.props.adjustment, adjustment) def test_iconview(self): # PyGTK compat iconview = Gtk.IconView() self.assertEqual(iconview.props.model, None) model = Gtk.ListStore(str) iconview = Gtk.IconView(model=model) self.assertEqual(iconview.props.model, model) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_toolbutton(self): # PyGTK compat # Using stock items causes hard warning in devel versions of GTK. with capture_glib_warnings(allow_warnings=True): button = Gtk.ToolButton() self.assertEqual(button.props.stock_id, None) button = Gtk.ToolButton(stock_id="gtk-new") self.assertEqual(button.props.stock_id, "gtk-new") icon = Gtk.Image.new_from_stock(Gtk.STOCK_OPEN, Gtk.IconSize.SMALL_TOOLBAR) button = Gtk.ToolButton(label="mylabel", icon_widget=icon) self.assertEqual(button.props.label, "mylabel") self.assertEqual(button.props.icon_widget, icon) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_iconset(self): Gtk.IconSet() pixbuf = GdkPixbuf.Pixbuf() Gtk.IconSet.new_from_pixbuf(pixbuf) with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") Gtk.IconSet(pixbuf) assert issubclass(warn[0].category, PyGTKDeprecationWarning) def test_viewport(self): vadjustment = Gtk.Adjustment() hadjustment = Gtk.Adjustment() viewport = Gtk.Viewport(hadjustment=hadjustment, vadjustment=vadjustment) self.assertEqual(viewport.props.vadjustment, vadjustment) self.assertEqual(viewport.props.hadjustment, hadjustment) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_stock_lookup(self): stock_item = Gtk.stock_lookup("gtk-ok") self.assertEqual(type(stock_item), Gtk.StockItem) self.assertEqual(stock_item.stock_id, "gtk-ok") self.assertEqual(Gtk.stock_lookup("nosuchthing"), None) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_gtk_main(self): # with no arguments GLib.idle_add(Gtk.main_quit) Gtk.main() # overridden function ignores its arguments GLib.idle_add(Gtk.main_quit, "hello") Gtk.main() @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_widget_render_icon(self): button = Gtk.Button(label="OK") pixbuf = button.render_icon(Gtk.STOCK_OK, Gtk.IconSize.BUTTON) self.assertTrue(pixbuf is not None) @unittest.skipUnless( Gtk_version == "4.0", "GtkWidget prior to gtk4 is not iterable" ) def test_widget_iterable(self): widget = Gtk.Box() children = list(widget) self.assertEqual(len(children), 0) nr_children = 7 for i in range(nr_children): widget.append(Gtk.Label()) children = list(widget) self.assertEqual(len(children), nr_children) first_child = children[0] last_child = children[-1] self.assertEqual(first_child, widget.get_first_child()) self.assertEqual(last_child, widget.get_last_child()) self.assertTrue(first_child in widget) self.assertTrue(last_child in widget) widget.remove(first_child) self.assertTrue(first_child not in widget) self.assertTrue(last_child in widget) widget.remove(last_child) self.assertTrue(first_child not in widget) self.assertTrue(last_child not in widget) @unittest.skipUnless(Gtk, "Gtk not available") class TestWidget(unittest.TestCase): @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_style_get_property_gvalue(self): button = Gtk.Button() value = GObject.Value(int, -42) button.style_get_property("focus-padding", value) # Test only that the style property changed since we can't actuall # set it. self.assertNotEqual(value.get_int(), -42) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_style_get_property_return_with_explicit_gvalue(self): button = Gtk.Button() value = GObject.Value(int, -42) result = button.style_get_property("focus-padding", value) self.assertIsInstance(result, int) self.assertNotEqual(result, -42) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_style_get_property_return_with_implicit_gvalue(self): button = Gtk.Button() result = button.style_get_property("focus-padding") self.assertIsInstance(result, int) self.assertNotEqual(result, -42) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_style_get_property_error(self): button = Gtk.Button() with self.assertRaises(ValueError): button.style_get_property("not-a-valid-style-property") @unittest.skipIf(Gtk_version != "4.0", "only in gtk4") def test_translate_coordinates(self): box = Gtk.Box() child = Gtk.Button() box.append(child) with realized(box): assert box.translate_coordinates(child, 42, 24) == (42.0, 24.0) assert box.translate_coordinates(Gtk.Button(), 0, 0) is None @unittest.skipIf(sys.platform == "darwin", "hangs") @unittest.skipUnless(Gtk, "Gtk not available") class TestSignals(unittest.TestCase): def test_class_closure_override_with_aliased_type(self): class WindowWithSizeAllocOverride(Gtk.ScrolledWindow): if not GTK4: __gsignals__ = {"size-allocate": "override"} def __init__(self): Gtk.ScrolledWindow.__init__(self) self._alloc_called = False self._alloc_value = None self._alloc_error = None def do_size_allocate(self, *args): self._alloc_called = True self._alloc_value = args[0] try: Gtk.ScrolledWindow.do_size_allocate(self, *args) except Exception as e: self._alloc_error = e win = WindowWithSizeAllocOverride() rect = Gdk.Rectangle() rect.width = 100 rect.height = 100 with realized(win): win.show() win.get_preferred_size() if GTK4: win.size_allocate(rect, 0) else: win.size_allocate(rect) self.assertTrue(win._alloc_called) if GTK4: self.assertIsInstance(win._alloc_value, int) else: self.assertIsInstance(win._alloc_value, Gdk.Rectangle) self.assertTrue(win._alloc_error is None, win._alloc_error) @unittest.expectedFailure # https://bugzilla.gnome.org/show_bug.cgi?id=735693 def test_overlay_child_position(self): def get_child_position(overlay, widget, rect, user_data=None): rect.x = 1 rect.y = 2 rect.width = 3 rect.height = 4 return True overlay = Gtk.Overlay() overlay.connect("get-child-position", get_child_position) rect = Gdk.Rectangle() rect.x = -1 rect.y = -1 rect.width = -1 rect.height = -1 overlay.emit("get-child-position", None, rect) self.assertEqual(rect.x, 1) self.assertEqual(rect.y, 2) self.assertEqual(rect.width, 3) self.assertEqual(rect.height, 4) @unittest.skipUnless(Gtk, "Gtk not available") class TestBuilder(unittest.TestCase): class SignalTest(GObject.GObject): __gtype_name__ = "GIOverrideSignalTest" __gsignals__ = { "test-signal": (GObject.SignalFlags.RUN_FIRST, None, []), } class SignalTestObject(GObject.GObject): __gtype_name__ = "GIOverrideSignalTestObject" def test_add_from_string(self): builder = Gtk.Builder() with pytest.raises(TypeError): builder.add_from_string(object()) builder.add_from_string("") builder.add_from_string("") def get_example(string): return f"""\
{string}
""" builder.add_from_string(get_example("ä" * 1000)) builder = Gtk.Builder() builder.add_objects_from_string("", [""]) builder.add_objects_from_string("", [""]) builder.add_objects_from_string(get_example("ä" * 1000), [""]) with pytest.raises(TypeError): builder.add_objects_from_string(object(), []) def test_extract_handler_and_args_object(self): class Obj: pass obj = Obj() obj.foo = lambda: None handler, args = Gtk._extract_handler_and_args(obj, "foo") self.assertEqual(handler, obj.foo) self.assertEqual(len(args), 0) def test_extract_handler_and_args_dict(self): obj = {"foo": lambda: None} handler, args = Gtk._extract_handler_and_args(obj, "foo") self.assertEqual(handler, obj["foo"]) self.assertEqual(len(args), 0) def test_extract_handler_and_args_with_seq(self): obj = {"foo": (lambda: None, 1, 2)} handler, args = Gtk._extract_handler_and_args(obj, "foo") self.assertEqual(handler, obj["foo"][0]) self.assertSequenceEqual(args, [1, 2]) def test_extract_handler_and_args_no_handler_error(self): obj = {"foo": lambda: None} self.assertRaises( AttributeError, Gtk._extract_handler_and_args, obj, "not_a_handler" ) def test_extract_handler_and_args_type_mismatch(self): with pytest.raises(TypeError): Gtk._extract_handler_and_args({"foo": object()}, "foo") with pytest.raises(TypeError): Gtk._extract_handler_and_args({"foo": []}, "foo") def test_builder_with_handler_and_args(self): args_collector = [] def on_signal(*args): args_collector.append(args) signals_dict = {"on_signal1": (on_signal, 1, 2), "on_signal2": on_signal} builder = Gtk.Builder(signals_dict) if GTK4 else Gtk.Builder() builder.add_from_string(""" """) if not GTK4: builder.connect_signals(signals_dict) objects = builder.get_objects() self.assertEqual(len(objects), 1) (obj,) = objects obj.emit("test-signal") self.assertEqual(len(args_collector), 2) self.assertSequenceEqual(args_collector[0], (obj, 1, 2)) self.assertSequenceEqual(args_collector[1], (obj,)) def test_builder_with_handler_object(self): args_collector = [] def on_signal(*args): args_collector.append(args) signals_dict = {"on_signal1": (on_signal, 1, 2), "on_signal2": on_signal} builder = Gtk.Builder(signals_dict) if GTK4 else Gtk.Builder() builder.add_from_string(""" """) if not GTK4: builder.connect_signals(signals_dict) obj = builder.get_object("foo") emitter = builder.get_object("object_sig_test") emitter.emit("test-signal") assert len(args_collector) == 2 assert args_collector[0] == (obj, 1, 2) assert args_collector[1] == (obj,) def test_builder(self): self.assertEqual(Gtk.Builder, gi.overrides.Gtk.Builder) class SignalCheck: def __init__(self): self.sentinel = 0 self.after_sentinel = 0 def on_signal_1(self, *args): self.sentinel += 1 self.after_sentinel += 1 def on_signal_3(self, *args): self.sentinel += 3 def on_signal_after(self, *args): if self.after_sentinel == 1: self.after_sentinel += 1 signal_checker = SignalCheck() signal_checker = SignalCheck() builder = Gtk.Builder(signal_checker) if GTK4 else Gtk.Builder() # add object1 to the builder builder.add_from_string(""" """) # only add object3 to the builder builder.add_objects_from_string( """ """, ["object3"], ) # hook up signals for Gtk3 if not GTK4: builder.connect_signals(signal_checker) # call their notify signals and check sentinel objects = builder.get_objects() self.assertEqual(len(objects), 2) for obj in objects: obj.emit("test-signal") self.assertEqual(signal_checker.sentinel, 4) self.assertEqual(signal_checker.after_sentinel, 2) @unittest.skipUnless(Gtk, "Gtk not available") class TestTreeModelRow(unittest.TestCase): def test_tree_model_row(self): model = Gtk.TreeStore(int) iter_ = model.append(None, [42]) path = model.get_path(iter_) Gtk.TreeModelRow(model, iter_) row = Gtk.TreeModelRow(model, path) with pytest.raises(TypeError): row["foo"] with pytest.raises(TypeError): Gtk.TreeModelRow(model, 42) with pytest.raises(TypeError): Gtk.TreeModelRow(42, path) iter_ = model.append(None, [24]) row = Gtk.TreeModelRow(model, iter_) assert row.previous[0] == 42 assert row.get_previous()[0] == 42 assert row.previous.previous is None @unittest.skipUnless(Gtk, "Gtk not available") class TestCustomSorter: class Person(GObject.GObject): name = GObject.Property(type=str, default="") def __init__(self, name): super().__init__() self.props.name = name user_data = "user_data" def names_sort(self, name_a, name_b, user_data): assert user_data is None if name_a.props.name < name_b.props.name: return Gtk.Ordering.SMALLER if name_a.props.name > name_b.props.name: return Gtk.Ordering.LARGER return Gtk.Ordering.EQUAL def names_invert_sort(self, name_a, name_b, user_data): assert user_data == self.user_data if name_a.props.name < name_b.props.name: return Gtk.Ordering.LARGER if name_a.props.name > name_b.props.name: return Gtk.Ordering.SMALLER return Gtk.Ordering.EQUAL @unittest.skipIf(Gtk_version != "4.0", "gtk4 only") def test_custom_sorter_init(self): custom_sorter_empty = Gtk.CustomSorter() assert isinstance(custom_sorter_empty, Gtk.CustomSorter) custom_sorter_empty.set_sort_func(self.names_sort) assert isinstance(custom_sorter_empty, Gtk.CustomSorter) custom_sorter_empty.set_sort_func(self.names_invert_sort, self.user_data) assert isinstance(custom_sorter_empty, Gtk.CustomSorter) custom_sorter_empty_sort = Gtk.CustomSorter.new(None) assert isinstance(custom_sorter_empty_sort, Gtk.CustomSorter) custom_sorter_with_sort = Gtk.CustomSorter.new(self.names_sort, None) assert isinstance(custom_sorter_with_sort, Gtk.CustomSorter) custom_sorter_with_sort_ud = Gtk.CustomSorter.new( self.names_invert_sort, self.user_data ) assert isinstance(custom_sorter_with_sort_ud, Gtk.CustomSorter) @unittest.skipIf(Gtk_version != "4.0", "gtk4 only") def test_custom_sorter_with_model(self): model = Gio.ListStore.new(self.Person) sort_model = Gtk.SortListModel.new(model) assert sort_model.props.sorter is None empty_sorter = Gtk.CustomSorter() empty_sorter.set_sort_func(self.names_sort, None) sort_model.set_sorter(empty_sorter) assert sort_model.props.sorter is empty_sorter john = self.Person("john") bob = self.Person("bob") model.append(john) model.append(bob) assert sort_model[0] == bob assert sort_model[1] == john alice = self.Person("alice") model.append(alice) assert sort_model[0] == alice assert sort_model[2] == john new_model = Gio.ListStore.new(self.Person) new_sort_model = Gtk.SortListModel.new(new_model) assert new_sort_model.props.sorter is None invert_sorter = Gtk.CustomSorter.new(self.names_invert_sort, self.user_data) new_sort_model.set_sorter(invert_sorter) assert new_sort_model.props.sorter is invert_sorter beatles = ["john", "paul", "george", "ringo"] for member in beatles: new_model.append(self.Person(member)) expected_result = ["ringo", "paul", "john", "george"] for result, member in zip(new_sort_model, expected_result): assert result.props.name == member @unittest.skipUnless(Gtk, "Gtk not available") class TestListStore(unittest.TestCase): def test_insert_with_values(self): model = Gtk.ListStore(int) assert hasattr(model, "insert_with_values") iter_ = model.insert_with_values(0, (0,), [42]) assert isinstance(iter_, Gtk.TreeIter) assert hasattr(model, "insert_with_valuesv") iter_ = model.insert_with_valuesv(0, (0,), [43]) assert isinstance(iter_, Gtk.TreeIter) assert len(model) == 2 @ignore_gi_deprecation_warnings @unittest.skipUnless(Gtk, "Gtk not available") class TestTreeModel(unittest.TestCase): @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_tree_model_sort_new_with_model_old(self): # https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/1134 model = Gtk.TreeStore(int) sort_model = model.sort_new_with_model() assert isinstance(sort_model, Gtk.TreeModelSort) assert sort_model.get_model() == model def test_tree_model_sort_new_with_model_new(self): # https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/1134 model = Gtk.TreeStore(int) sort_model = Gtk.TreeModelSort.new_with_model(child_model=model) assert isinstance(sort_model, Gtk.TreeModelSort) assert sort_model.get_model() == model def test_tree_model_sort(self): if not GTK4: self.assertEqual(Gtk.TreeModelSort, gi.overrides.Gtk.TreeModelSort) model = Gtk.TreeStore(int, bool) model_sort = Gtk.TreeModelSort(model=model) self.assertEqual(model_sort.get_model(), model) def test_tree_store(self): self.assertEqual(Gtk.TreeStore, gi.overrides.Gtk.TreeStore) self.assertEqual(Gtk.ListStore, gi.overrides.Gtk.ListStore) self.assertEqual(Gtk.TreeModel, gi.overrides.Gtk.TreeModel) self.assertEqual(Gtk.TreeViewColumn, gi.overrides.Gtk.TreeViewColumn) class TestPyObject: pass test_pyobj = TestPyObject() test_pydict = {1: 1, "2": 2, "3": "3"} test_pylist = [1, "2", "3"] tree_store = Gtk.TreeStore( int, "gchararray", TestGtk.TestClass, GObject.TYPE_PYOBJECT, object, object, object, bool, bool, GObject.TYPE_UINT, GObject.TYPE_ULONG, GObject.TYPE_INT64, GObject.TYPE_UINT64, GObject.TYPE_UCHAR, GObject.TYPE_CHAR, ) parent = None for i in range(97): label = f"this is child #{i:d}" testobj = TestGtk.TestClass(self, i, label) parent = tree_store.append( parent, ( i, label, testobj, testobj, test_pyobj, test_pydict, test_pylist, i % 2, bool(i % 2), i, GLib.MAXULONG, GLib.MININT64, 0xFFFFFFFFFFFFFFFF, 254, b"a", ), ) # test set parent = tree_store.append(parent) i = 97 label = f"this is child #{i:d}" testobj = TestGtk.TestClass(self, i, label) tree_store.set( parent, 0, i, 2, testobj, 1, label, 3, testobj, 4, test_pyobj, 5, test_pydict, 6, test_pylist, 7, i % 2, 8, bool(i % 2), 9, i, 10, GLib.MAXULONG, 11, GLib.MININT64, 12, 0xFFFFFFFFFFFFFFFF, 13, 254, 14, b"a", ) parent = tree_store.append(parent) i = 98 label = f"this is child #{i:d}" testobj = TestGtk.TestClass(self, i, label) tree_store.set( parent, { 0: i, 2: testobj, 1: label, 3: testobj, 4: test_pyobj, 5: test_pydict, 6: test_pylist, 7: i % 2, 8: bool(i % 2), 9: i, 10: GLib.MAXULONG, 11: GLib.MININT64, 12: 0xFFFFFFFFFFFFFFFF, 13: 254, 14: b"a", }, ) parent = tree_store.append(parent) i = 99 label = f"this is child #{i:d}" testobj = TestGtk.TestClass(self, i, label) tree_store.set( parent, (0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14), ( i, testobj, label, testobj, test_pyobj, test_pydict, test_pylist, i % 2, bool(i % 2), i, GLib.MAXULONG, GLib.MININT64, 0xFFFFFFFFFFFFFFFF, 254, b"a", ), ) # len gets the number of children in the root node # since we kept appending to the previous node # there should only be one child of the root self.assertEqual(len(tree_store), 1) # walk the tree to see if the values were stored correctly parent = None i = 0 treeiter = tree_store.iter_children(parent) while treeiter: i = tree_store.get_value(treeiter, 0) s = tree_store.get_value(treeiter, 1) obj = tree_store.get_value(treeiter, 2) obj.check(i, s) obj2 = tree_store.get_value(treeiter, 3) self.assertEqual(obj, obj2) pyobj = tree_store.get_value(treeiter, 4) self.assertEqual(pyobj, test_pyobj) pydict = tree_store.get_value(treeiter, 5) self.assertEqual(pydict, test_pydict) pylist = tree_store.get_value(treeiter, 6) self.assertEqual(pylist, test_pylist) bool_1 = tree_store.get_value(treeiter, 7) bool_2 = tree_store.get_value(treeiter, 8) self.assertEqual(bool_1, bool_2) self.assertTrue(isinstance(bool_1, bool)) self.assertTrue(isinstance(bool_2, bool)) uint_ = tree_store.get_value(treeiter, 9) self.assertEqual(uint_, i) ulong_ = tree_store.get_value(treeiter, 10) self.assertEqual(ulong_, GLib.MAXULONG) int64_ = tree_store.get_value(treeiter, 11) self.assertEqual(int64_, GLib.MININT64) uint64_ = tree_store.get_value(treeiter, 12) self.assertEqual(uint64_, 0xFFFFFFFFFFFFFFFF) uchar_ = tree_store.get_value(treeiter, 13) self.assertEqual(ord(uchar_), 254) char_ = tree_store.get_value(treeiter, 14) self.assertEqual(char_, "a") parent = treeiter treeiter = tree_store.iter_children(parent) self.assertEqual(i, 99) def test_tree_store_signals(self): tree_store = Gtk.TreeStore(int, bool) def on_row_inserted(tree_store, tree_path, tree_iter, signal_list): signal_list.append("row-inserted") def on_row_changed(tree_store, tree_path, tree_iter, signal_list): signal_list.append("row-changed") signals = [] tree_store.connect("row-inserted", on_row_inserted, signals) tree_store.connect("row-changed", on_row_changed, signals) # adding rows with and without data should only call one signal tree_store.append(None, (0, False)) self.assertEqual(signals, ["row-inserted"]) signals.pop() tree_store.append(None) self.assertEqual(signals, ["row-inserted"]) signals.pop() tree_store.prepend(None, (0, False)) self.assertEqual(signals, ["row-inserted"]) signals.pop() tree_store.prepend(None) self.assertEqual(signals, ["row-inserted"]) signals.pop() tree_store.insert(None, 1, (0, False)) self.assertEqual(signals, ["row-inserted"]) signals.pop() tree_store.insert(None, 1) self.assertEqual(signals, ["row-inserted"]) # One set one signal signals.pop() tree_iter = tree_store.append(None, (10, False)) tree_store.set(tree_iter, (0, 1), (20, True)) self.assertEqual(signals, ["row-inserted", "row-changed"]) def test_list_store(self): class TestPyObject: pass test_pyobj = TestPyObject() test_pydict = {1: 1, "2": 2, "3": "3"} test_pylist = [1, "2", "3"] list_store = Gtk.ListStore( int, str, "GIOverrideTreeAPITest", object, object, object, bool, bool ) for i in range(1, 93): label = f"this is row #{i:d}" testobj = TestGtk.TestClass(self, i, label) list_store.append( ( i, label, testobj, test_pyobj, test_pydict, test_pylist, i % 2, bool(i % 2), ) ) i = 93 label = "this is row #93" treeiter = list_store.append() list_store.set_value(treeiter, 0, i) list_store.set_value(treeiter, 1, label) list_store.set_value(treeiter, 2, TestGtk.TestClass(self, i, label)) list_store.set_value(treeiter, 3, test_pyobj) list_store.set_value(treeiter, 4, test_pydict) list_store.set_value(treeiter, 5, test_pylist) list_store.set_value(treeiter, 6, 1) list_store.set_value(treeiter, 7, True) # test prepend label = "this is row #0" list_store.prepend( ( 0, label, TestGtk.TestClass(self, 0, label), test_pyobj, test_pydict, test_pylist, 0, False, ) ) # test automatic unicode->str conversion i = 94 label = "this is row #94" treeiter = list_store.append( ( i, label, TestGtk.TestClass(self, i, label), test_pyobj, test_pydict, test_pylist, 0, False, ) ) # add sorted items out of order to test insert* apis # also test sending in None to not set a column i = 97 label = "this is row #97" treeiter = list_store.append( (None, None, None, test_pyobj, None, test_pylist, 1, None) ) list_store.set_value(treeiter, 0, i) list_store.set_value(treeiter, 1, label) list_store.set_value(treeiter, 2, TestGtk.TestClass(self, i, label)) list_store.set_value(treeiter, 4, test_pydict) list_store.set_value(treeiter, 7, True) # this should append i = 99 label = "this is row #99" list_store.insert( 9999, ( i, label, TestGtk.TestClass(self, i, label), test_pyobj, test_pydict, test_pylist, 1, True, ), ) i = 96 label = "this is row #96" list_store.insert_before( treeiter, ( i, label, TestGtk.TestClass(self, i, label), test_pyobj, test_pydict, test_pylist, 0, False, ), ) i = 98 label = "this is row #98" list_store.insert_after( treeiter, ( i, label, TestGtk.TestClass(self, i, label), test_pyobj, test_pydict, test_pylist, 0, False, ), ) i = 95 label = "this is row #95" list_store.insert( 95, ( i, label, TestGtk.TestClass(self, i, label), test_pyobj, test_pydict, test_pylist, 1, True, ), ) i = 100 label = "this is row #100" treeiter = list_store.append() list_store.set( treeiter, 1, label, 0, i, 2, TestGtk.TestClass(self, i, label), 3, test_pyobj, 4, test_pydict, 5, test_pylist, 6, 0, 7, False, ) i = 101 label = "this is row #101" treeiter = list_store.append() list_store.set( treeiter, { 1: label, 0: i, 2: TestGtk.TestClass(self, i, label), 3: test_pyobj, 4: test_pydict, 5: test_pylist, 6: 1, 7: True, }, ) i = 102 label = "this is row #102" treeiter = list_store.append() list_store.set( treeiter, (1, 0, 2, 3, 4, 5, 6, 7), ( label, i, TestGtk.TestClass(self, i, label), test_pyobj, test_pydict, test_pylist, 0, False, ), ) self.assertEqual(len(list_store), 103) # walk the list to see if the values were stored correctly i = 0 treeiter = list_store.get_iter_first() counter = 0 while treeiter: i = list_store.get_value(treeiter, 0) self.assertEqual(i, counter) s = list_store.get_value(treeiter, 1) obj = list_store.get_value(treeiter, 2) obj.check(i, s) pyobj = list_store.get_value(treeiter, 3) self.assertEqual(pyobj, test_pyobj) pydict = list_store.get_value(treeiter, 4) self.assertEqual(pydict, test_pydict) pylist = list_store.get_value(treeiter, 5) self.assertEqual(pylist, test_pylist) bool_1 = list_store.get_value(treeiter, 6) bool_2 = list_store.get_value(treeiter, 7) self.assertEqual(bool_1, bool_2) self.assertTrue(isinstance(bool_1, bool)) self.assertTrue(isinstance(bool_2, bool)) treeiter = list_store.iter_next(treeiter) counter += 1 self.assertEqual(i, 102) def test_list_store_sort(self): def comp1(model, row1, row2, user_data): v1 = model[row1][1] v2 = model[row2][1] # make "m" smaller than anything else if v1.startswith("m") and not v2.startswith("m"): return -1 if v2.startswith("m") and not v1.startswith("m"): return 1 return (v1 > v2) - (v1 < v2) list_store = Gtk.ListStore(int, str) list_store.set_sort_func(2, comp1, None) list_store.append((1, "apples")) list_store.append((3, "oranges")) list_store.append((2, "mango")) # not sorted yet, should be original order self.assertEqual( [list(i) for i in list_store], [[1, "apples"], [3, "oranges"], [2, "mango"]] ) # sort with our custom function list_store.set_sort_column_id(2, Gtk.SortType.ASCENDING) self.assertEqual( [list(i) for i in list_store], [[2, "mango"], [1, "apples"], [3, "oranges"]] ) list_store.set_sort_column_id(2, Gtk.SortType.DESCENDING) self.assertEqual( [list(i) for i in list_store], [[3, "oranges"], [1, "apples"], [2, "mango"]] ) def test_list_store_signals(self): list_store = Gtk.ListStore(int, bool) def on_row_inserted(list_store, tree_path, tree_iter, signal_list): signal_list.append("row-inserted") def on_row_changed(list_store, tree_path, tree_iter, signal_list): signal_list.append("row-changed") signals = [] list_store.connect("row-inserted", on_row_inserted, signals) list_store.connect("row-changed", on_row_changed, signals) # adding rows with and without data should only call one signal list_store.append((0, False)) self.assertEqual(signals, ["row-inserted"]) signals.pop() list_store.append() self.assertEqual(signals, ["row-inserted"]) signals.pop() list_store.prepend((0, False)) self.assertEqual(signals, ["row-inserted"]) signals.pop() list_store.prepend() self.assertEqual(signals, ["row-inserted"]) signals.pop() list_store.insert(1, (0, False)) self.assertEqual(signals, ["row-inserted"]) signals.pop() list_store.insert(1) self.assertEqual(signals, ["row-inserted"]) # One set one signal signals.pop() tree_iter = list_store.append((10, False)) list_store.set(tree_iter, (0, 1), (20, True)) self.assertEqual(signals, ["row-inserted", "row-changed"]) def test_list_store_insert_before(self): store = Gtk.ListStore(object) signals = [] def on_row_inserted(store, tree_path, tree_iter, signal_list): signal_list.append("row-inserted") def on_row_changed(store, tree_path, tree_iter, signal_list): signal_list.append("row-changed") store.connect("row-inserted", on_row_inserted, signals) store.connect("row-changed", on_row_changed, signals) iter_ = store.append([0]) assert store.get_value(iter_, 0) == 0 assert signals == ["row-inserted"] del signals[:] # append empty iter_ = store.insert_before(None) assert store.get_path(iter_).get_indices() == [1] assert store.get_value(iter_, 0) is None assert signals == ["row-inserted"] del signals[:] # insert empty iter_ = store.insert_before(iter_) assert store.get_path(iter_).get_indices() == [1] assert store.get_value(iter_, 0) is None assert signals == ["row-inserted"] del signals[:] # append non-empty iter_ = store.insert_before(None, [1234]) assert store.get_path(iter_).get_indices() == [3] assert store.get_value(iter_, 0) == 1234 assert signals == ["row-inserted"] del signals[:] # insert non-empty iter_ = store.insert_before(iter_, [4321]) assert store.get_path(iter_).get_indices() == [3] assert store.get_value(iter_, 0) == 4321 assert signals == ["row-inserted"] del signals[:] assert [r[0] for r in store] == [0, None, None, 4321, 1234] def test_list_store_insert_after(self): store = Gtk.ListStore(object) signals = [] def on_row_inserted(store, tree_path, tree_iter, signal_list): signal_list.append("row-inserted") def on_row_changed(store, tree_path, tree_iter, signal_list): signal_list.append("row-changed") store.connect("row-inserted", on_row_inserted, signals) store.connect("row-changed", on_row_changed, signals) iter_ = store.append([0]) assert store.get_value(iter_, 0) == 0 assert signals == ["row-inserted"] del signals[:] # prepend empty iter_ = store.insert_after(None) assert store.get_path(iter_).get_indices() == [0] assert store.get_value(iter_, 0) is None assert signals == ["row-inserted"] del signals[:] # insert empty iter_ = store.insert_after(iter_) assert store.get_path(iter_).get_indices() == [1] assert store.get_value(iter_, 0) is None assert signals == ["row-inserted"] del signals[:] # prepend non-empty iter_ = store.insert_after(None, [1234]) assert store.get_path(iter_).get_indices() == [0] assert store.get_value(iter_, 0) == 1234 assert signals == ["row-inserted"] del signals[:] # insert non-empty iter_ = store.insert_after(iter_, [4321]) assert store.get_path(iter_).get_indices() == [1] assert store.get_value(iter_, 0) == 4321 assert signals == ["row-inserted"] del signals[:] assert [r[0] for r in store] == [1234, 4321, None, None, 0] def test_tree_store_insert_before(self): store = Gtk.TreeStore(object) signals = [] def on_row_inserted(store, tree_path, tree_iter, signal_list): signal_list.append("row-inserted") def on_row_changed(store, tree_path, tree_iter, signal_list): signal_list.append("row-changed") store.connect("row-inserted", on_row_inserted, signals) store.connect("row-changed", on_row_changed, signals) parent = store.append(None, [-1]) assert signals == ["row-inserted"] del signals[:] iter_ = store.append(parent, [0]) assert store.get_path(iter_).get_indices() == [0, 0] assert store.get_value(iter_, 0) == 0 assert signals == ["row-inserted"] del signals[:] # append empty iter_ = store.insert_before(parent, None) assert store.get_path(iter_).get_indices() == [0, 1] assert store.get_value(iter_, 0) is None assert signals == ["row-inserted"] del signals[:] # insert empty iter_ = store.insert_before(parent, iter_) assert store.get_path(iter_).get_indices() == [0, 1] assert store.get_value(iter_, 0) is None assert signals == ["row-inserted"] del signals[:] # append non-empty iter_ = store.insert_before(parent, None, [1234]) assert store.get_path(iter_).get_indices() == [0, 3] assert store.get_value(iter_, 0) == 1234 assert signals == ["row-inserted"] del signals[:] # insert non-empty iter_ = store.insert_before(parent, iter_, [4321]) assert store.get_path(iter_).get_indices() == [0, 3] assert store.get_value(iter_, 0) == 4321 assert signals == ["row-inserted"] del signals[:] def func(model, path, iter_, rows): rows.append((path.get_indices(), model[iter_][:])) rows = [] store.foreach(func, rows) assert rows == [ ([0], [-1]), ([0, 0], [0]), ([0, 1], [None]), ([0, 2], [None]), ([0, 3], [4321]), ([0, 4], [1234]), ] def test_tree_store_insert_before_none(self): store = Gtk.TreeStore(object) root = store.append(None) sub = store.append(root) iter_ = store.insert_before(None, None, [1]) assert store.get_path(iter_).get_indices() == [1] iter_ = store.insert_before(root, None, [1]) assert store.get_path(iter_).get_indices() == [0, 1] iter_ = store.insert_before(sub, None, [1]) assert store.get_path(iter_).get_indices() == [0, 0, 0] iter_ = store.insert_before(None, root, [1]) assert store.get_path(iter_).get_indices() == [0] iter_ = store.insert_before(None, sub, [1]) assert store.get_path(iter_).get_indices() == [1, 0] def test_tree_store_insert_after(self): store = Gtk.TreeStore(object) signals = [] def on_row_inserted(store, tree_path, tree_iter, signal_list): signal_list.append("row-inserted") def on_row_changed(store, tree_path, tree_iter, signal_list): signal_list.append("row-changed") store.connect("row-inserted", on_row_inserted, signals) store.connect("row-changed", on_row_changed, signals) parent = store.append(None, [-1]) assert signals == ["row-inserted"] del signals[:] iter_ = store.append(parent, [0]) assert store.get_path(iter_).get_indices() == [0, 0] assert store.get_value(iter_, 0) == 0 assert signals == ["row-inserted"] del signals[:] # append empty iter_ = store.insert_after(parent, None) assert store.get_path(iter_).get_indices() == [0, 0] assert store.get_value(iter_, 0) is None assert signals == ["row-inserted"] del signals[:] # insert empty iter_ = store.insert_after(parent, iter_) assert store.get_path(iter_).get_indices() == [0, 1] assert store.get_value(iter_, 0) is None assert signals == ["row-inserted"] del signals[:] # append non-empty iter_ = store.insert_after(parent, None, [1234]) assert store.get_path(iter_).get_indices() == [0, 0] assert store.get_value(iter_, 0) == 1234 assert signals == ["row-inserted"] del signals[:] # insert non-empty iter_ = store.insert_after(parent, iter_, [4321]) assert store.get_path(iter_).get_indices() == [0, 1] assert store.get_value(iter_, 0) == 4321 assert signals == ["row-inserted"] del signals[:] def func(model, path, iter_, rows): rows.append((path.get_indices(), model[iter_][:])) rows = [] store.foreach(func, rows) assert rows == [ ([0], [-1]), ([0, 0], [1234]), ([0, 1], [4321]), ([0, 2], [None]), ([0, 3], [None]), ([0, 4], [0]), ] def test_tree_store_insert_after_none(self): store = Gtk.TreeStore(object) root = store.append(None) sub = store.append(root) iter_ = store.insert_after(None, None, [1]) assert store.get_path(iter_).get_indices() == [0] iter_ = store.insert_after(root, None, [1]) assert store.get_path(iter_).get_indices() == [1, 0] iter_ = store.insert_after(sub, None, [1]) assert store.get_path(iter_).get_indices() == [1, 1, 0] iter_ = store.insert_after(None, root, [1]) assert store.get_path(iter_).get_indices() == [2] iter_ = store.insert_after(None, sub, [1]) assert store.get_path(iter_).get_indices() == [1, 2] def test_tree_path(self): p1 = Gtk.TreePath() p2 = Gtk.TreePath.new_first() self.assertEqual(p1, p2) self.assertEqual(str(p1), "0") self.assertEqual(len(p1), 1) p1 = Gtk.TreePath(2) p2 = Gtk.TreePath.new_from_string("2") self.assertEqual(p1, p2) self.assertEqual(str(p1), "2") self.assertEqual(len(p1), 1) p1 = Gtk.TreePath("1:2:3") p2 = Gtk.TreePath.new_from_string("1:2:3") self.assertEqual(p1, p2) self.assertEqual(str(p1), "1:2:3") self.assertEqual(len(p1), 3) p1 = Gtk.TreePath((1, 2, 3)) p2 = Gtk.TreePath.new_from_string("1:2:3") self.assertEqual(p1, p2) self.assertEqual(str(p1), "1:2:3") self.assertEqual(len(p1), 3) self.assertNotEqual(p1, None) self.assertTrue(p1 > None) self.assertTrue(p1 >= None) self.assertFalse(p1 < None) self.assertFalse(p1 <= None) self.assertEqual(tuple(p1), (1, 2, 3)) self.assertEqual(p1[0], 1) self.assertEqual(p1[1], 2) self.assertEqual(p1[2], 3) self.assertRaises(IndexError, p1.__getitem__, 3) def test_tree_path_empty(self): p1 = Gtk.TreePath.new() assert str(p1) == "" def test_tree_model(self): tree_store = Gtk.TreeStore(int, str) self.assertTrue(tree_store) self.assertEqual(len(tree_store), 0) self.assertEqual(tree_store.get_iter_first(), None) def get_by_index(row, col=None): if col: return tree_store[row][col] return tree_store[row] self.assertRaises(TypeError, get_by_index, None) self.assertRaises(TypeError, get_by_index, "") self.assertRaises(TypeError, get_by_index, ()) self.assertRaises(IndexError, get_by_index, "0") self.assertRaises(IndexError, get_by_index, 0) self.assertRaises(IndexError, get_by_index, (0,)) self.assertRaises(ValueError, tree_store.get_iter, "0") self.assertRaises(ValueError, tree_store.get_iter, 0) self.assertRaises(ValueError, tree_store.get_iter, (0,)) self.assertRaises(ValueError, tree_store.get_iter_from_string, "0") for row in tree_store: self.fail("Should not be reached") class DerivedIntType(int): pass class DerivedStrType(str): pass for i in range(100): label = f"this is row #{i:d}" parent = tree_store.append( None, ( DerivedIntType(i), DerivedStrType(label), ), ) self.assertNotEqual(parent, None) for j in range(20): label = f"this is child #{j:d} of node #{i:d}" child = tree_store.append( parent, ( j, label, ), ) self.assertNotEqual(child, None) self.assertTrue(tree_store) self.assertEqual(len(tree_store), 100) self.assertEqual(tree_store.iter_previous(tree_store.get_iter(0)), None) for i, row in enumerate(tree_store): self.assertEqual(row.model, tree_store) self.assertEqual(row.parent, None) self.assertEqual(tree_store[i].path, row.path) self.assertEqual(tree_store[str(i)].path, row.path) self.assertEqual(tree_store[i,].path, row.path) self.assertEqual(tree_store[i][0], i) self.assertEqual(tree_store[i][1], f"this is row #{i:d}") aiter = tree_store.get_iter(i) self.assertEqual(tree_store.get_path(aiter), row.path) aiter = tree_store.get_iter(str(i)) self.assertEqual(tree_store.get_path(aiter), row.path) aiter = tree_store.get_iter((i,)) self.assertEqual(tree_store.get_path(aiter), row.path) self.assertEqual(tree_store.iter_parent(aiter), row.parent) next = tree_store.iter_next(aiter) if i < len(tree_store) - 1: self.assertEqual(tree_store.get_path(next), row.next.path) self.assertEqual( tree_store.get_path(tree_store.iter_previous(next)), tree_store.get_path(aiter), ) else: self.assertEqual(next, None) self.assertEqual(tree_store.iter_n_children(row.iter), 20) child = tree_store.iter_children(row.iter) for j, childrow in enumerate(row.iterchildren()): child_path = tree_store.get_path(child) self.assertEqual(childrow.path, child_path) self.assertEqual(childrow.parent.path, row.path) self.assertEqual(childrow.path, tree_store[child].path) self.assertEqual(childrow.path, tree_store[child_path].path) self.assertEqual(childrow[0], tree_store[child][0]) self.assertEqual(childrow[0], j) self.assertEqual(childrow[1], tree_store[child][1]) self.assertEqual(childrow[1], f"this is child #{j:d} of node #{i:d}") self.assertRaises(IndexError, get_by_index, child, 2) tree_store[child][1] = f"this was child #{j:d} of node #{i:d}" self.assertEqual(childrow[1], f"this was child #{j:d} of node #{i:d}") nth_child = tree_store.iter_nth_child(row.iter, j) self.assertEqual(childrow.path, tree_store.get_path(nth_child)) childrow2 = tree_store[f"{i:d}:{j:d}"] self.assertEqual(childrow.path, childrow2.path) childrow2 = tree_store[ i, j, ] self.assertEqual(childrow.path, childrow2.path) child = tree_store.iter_next(child) if j < 19: self.assertEqual(childrow.next.path, tree_store.get_path(child)) else: self.assertEqual(child, childrow.next) self.assertEqual(child, None) self.assertEqual(j, 19) self.assertEqual(i, 99) # negative indices for i in range(-1, -100, -1): i_real = i + 100 self.assertEqual(tree_store[i][0], i_real) row = tree_store[i] for j in range(-1, -20, -1): j_real = j + 20 path = ( i_real, j_real, ) self.assertEqual(tree_store[path][-2], j_real) label = f"this was child #{j_real:d} of node #{i_real:d}" self.assertEqual(tree_store[path][-1], label) new_label = f"this still is child #{j_real:d} of node #{i_real:d}" tree_store[path][-1] = new_label self.assertEqual(tree_store[path][-1], new_label) self.assertRaises(IndexError, get_by_index, path, -3) self.assertRaises(IndexError, get_by_index, -101) last_row = tree_store[99] self.assertNotEqual(last_row, None) for i, childrow in enumerate(last_row.iterchildren()): if i < 19: self.assertTrue(tree_store.remove(childrow.iter)) else: self.assertFalse(tree_store.remove(childrow.iter)) self.assertEqual(i, 19) self.assertEqual(tree_store.iter_n_children(last_row.iter), 0) for childrow in last_row.iterchildren(): self.fail("Should not be reached") aiter = tree_store.get_iter(10) self.assertRaises(TypeError, tree_store.get, aiter, 1, "a") self.assertRaises(ValueError, tree_store.get, aiter, 1, -1) self.assertRaises(ValueError, tree_store.get, aiter, 1, 100) self.assertEqual(tree_store.get(aiter, 0, 1), (10, "this is row #10")) # check __delitem__ self.assertEqual(len(tree_store), 100) aiter = tree_store.get_iter(10) del tree_store[aiter] self.assertEqual(len(tree_store), 99) self.assertRaises(TypeError, tree_store.__delitem__, None) self.assertRaises(IndexError, tree_store.__delitem__, -101) self.assertRaises(IndexError, tree_store.__delitem__, 101) def test_tree_model_get_iter_fail(self): # TreeModel class with a failing get_iter() class MyTreeModel(GObject.GObject, Gtk.TreeModel): def do_get_iter(self, iter): return (False, None) tm = MyTreeModel() self.assertEqual(tm.get_iter_first(), None) def test_tree_model_edit(self): model = Gtk.ListStore(int, str, float) model.append([1, "one", -0.1]) model.append([2, "two", -0.2]) def set_row(value): model[1] = value self.assertRaises(TypeError, set_row, 3) self.assertRaises(TypeError, set_row, "three") self.assertRaises(ValueError, set_row, []) self.assertRaises(ValueError, set_row, [3, "three"]) model[0] = (3, "three", -0.3) def test_tree_row_slice(self): model = Gtk.ListStore(int, str, float) model.append([1, "one", -0.1]) self.assertEqual([1, "one", -0.1], model[0][:]) self.assertEqual([1, "one"], model[0][:2]) self.assertEqual(["one", -0.1], model[0][1:]) self.assertEqual(["one"], model[0][1:-1]) self.assertEqual([1], model[0][:-2]) self.assertEqual([], model[0][5:]) self.assertEqual([1, -0.1], model[0][0:3:2]) model[0][:] = (2, "two", -0.2) self.assertEqual([2, "two", -0.2], model[0][:]) model[0][:2] = (3, "three") self.assertEqual([3, "three", -0.2], model[0][:]) model[0][1:] = ("four", -0.4) self.assertEqual([3, "four", -0.4], model[0][:]) model[0][1:-1] = ("five",) self.assertEqual([3, "five", -0.4], model[0][:]) model[0][0:3:2] = (6, -0.6) self.assertEqual([6, "five", -0.6], model[0][:]) def set_row1(): model[0][5:] = ( "doesn't", "matter", ) self.assertRaises(ValueError, set_row1) def set_row2(): model[0][:1] = (0, "zero", 0) self.assertRaises(ValueError, set_row2) def set_row3(): model[0][:2] = ("0", 0) self.assertRaises(TypeError, set_row3) def test_tree_row_sequence(self): model = Gtk.ListStore(int, str, float) model.append([1, "one", -0.1]) self.assertEqual([1, "one", -0.1], model[0][0, 1, 2]) self.assertEqual([1, "one"], model[0][0, 1]) self.assertEqual(["one", -0.1], model[0][1, 2]) self.assertEqual("one", model[0][1]) self.assertEqual([1, -0.1], model[0][0, 2]) self.assertEqual([-0.1, 1], model[0][2, 0]) model[0][0, 1, 2] = (2, "two", -0.2) self.assertEqual([2, "two", -0.2], model[0][0, 1, 2]) model[0][0, 1] = (3, "three") self.assertEqual([3, "three"], model[0][0, 1]) model[0][1, 2] = ("four", -0.4) self.assertEqual(["four", -0.4], model[0][1, 2]) model[0][0, 2] = (5, -0.5) self.assertEqual([5, -0.5], model[0][0, 2]) model[0][0, 1, 2] = (6, "six", -0.6) self.assertEqual([-0.6, 6, "six"], model[0][2, 0, 1]) def set_row1(): model[0][4, 5] = ( "shouldn't", "work", ) self.assertRaises(IndexError, set_row1) def set_row2(): model[0][0, 1] = (0, "zero", 0) self.assertRaises(ValueError, set_row2) def set_row3(): model[0][0, 1] = ("shouldn't", 0) self.assertRaises(TypeError, set_row3) def set_row4(): model[0][0, "two"] = (0, "zero") self.assertRaises(TypeError, set_row4) def test_tree_model_set_value_to_none(self): # Tests allowing the usage of None to set an empty value on a model. store = Gtk.ListStore(str) row = store.append(["test"]) self.assertSequenceEqual(store[0][:], ["test"]) store.set_value(row, 0, None) self.assertSequenceEqual(store[0][:], [None]) def test_signal_emission_tree_path_coerce(self): class Model(GObject.Object, Gtk.TreeModel): pass model = Model() tree_paths = [] def on_any_signal(model, path, *args): tree_paths.append(path.to_string()) model.connect("row-changed", on_any_signal) model.connect("row-deleted", on_any_signal) model.connect("row-has-child-toggled", on_any_signal) model.connect("row-inserted", on_any_signal) model.row_changed("0", Gtk.TreeIter()) self.assertEqual(tree_paths[-1], "0") model.row_deleted("1") self.assertEqual(tree_paths[-1], "1") model.row_has_child_toggled("2", Gtk.TreeIter()) self.assertEqual(tree_paths[-1], "2") model.row_inserted("3", Gtk.TreeIter()) self.assertEqual(tree_paths[-1], "3") def test_tree_model_filter(self): model = Gtk.ListStore(int, str, float) model.append([1, "one", -0.1]) model.append([2, "two", -0.2]) filtered = Gtk.TreeModelFilter(child_model=model) self.assertEqual(filtered[0][1], "one") filtered[0][1] = "ONE" self.assertEqual(filtered[0][1], "ONE") def foo(store, iter_, data): assert data is None return False filtered.set_visible_func(foo) filtered.refilter() assert len(filtered) == 0 def test_list_store_performance(self): model = Gtk.ListStore(int, str) iterations = 2000 start = timeit.default_timer() i = iterations while i > 0: model.append([1, "hello"]) i -= 1 end = timeit.default_timer() sys.stderr.write("[%.0f μs/append] " % ((end - start) * 1000000 / iterations)) def test_filter_new_default(self): # Test filter_new accepts implicit default of None model = Gtk.ListStore(int) filt = model.filter_new() self.assertTrue(filt is not None) def test_tree_store_set(self): tree_store = Gtk.TreeStore(int, int) iter_ = tree_store.append(None) tree_store.set(iter_) assert tree_store.get_value(iter_, 0) == 0 tree_store.set(iter_, 0, 42) assert tree_store.get_value(iter_, 0) == 42 assert tree_store.get_value(iter_, 1) == 0 tree_store.set(iter_, 0, 42, 1, 24) assert tree_store.get_value(iter_, 1) == 24 tree_store.set(iter_, 1, 124) assert tree_store.get_value(iter_, 1) == 124 with pytest.raises(TypeError): tree_store.set(iter_, 0, 42, "foo", 24) with pytest.raises(TypeError): tree_store.set(iter_, "foo") with pytest.raises(TypeError): tree_store.set(iter_, [1, 2, 3]) with pytest.raises(TypeError): tree_store.set(iter_, 0, 42, 24) def test_list_store_set(self): list_store = Gtk.ListStore(int, int) iter_ = list_store.append() list_store.set(iter_) assert list_store.get_value(iter_, 0) == 0 list_store.set(iter_, 0, 42) assert list_store.get_value(iter_, 0) == 42 assert list_store.get_value(iter_, 1) == 0 list_store.set(iter_, 0, 42, 1, 24) assert list_store.get_value(iter_, 1) == 24 list_store.set(iter_, 1, 124) assert list_store.get_value(iter_, 1) == 124 with pytest.raises(TypeError): list_store.set(iter_, 0, 42, "foo", 24) with pytest.raises(TypeError): list_store.set(iter_, "foo") with pytest.raises(TypeError): list_store.set(iter_, [1, 2, 3]) with pytest.raises(TypeError): list_store.set(iter_, 0, 42, 24) def test_set_default_sort_func(self): list_store = Gtk.ListStore(int) list_store.append([2]) list_store.append([1]) def sort_func(store, iter1, iter2, data): assert data is None def cmp(a, b): return (a > b) - (a < b) return cmp(store[iter1][0], store[iter2][0]) list_store.set_default_sort_func(sort_func) list_store.set_sort_column_id( Gtk.TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, Gtk.SortType.ASCENDING ) assert [v[0] for v in list_store] == [1, 2] def test_model_rows_reordered(self): list_store = Gtk.ListStore(int) list_store.append([2]) list_store.append([1]) list_store.rows_reordered(Gtk.TreePath.new_first(), None, [0, 1]) list_store.rows_reordered(0, None, [0, 1]) def test_model_set_row(self): list_store = Gtk.ListStore(int, int) list_store.append([1, 2]) iter_ = list_store.get_iter_first() list_store.set_row(iter_, [3, 4]) assert list_store[0][:] == [3, 4] list_store.set_row(iter_, [None, 7]) assert list_store[0][:] == [3, 7] list_store.set_row(iter_, [None, GObject.Value(int, 9)]) assert list_store[0][:] == [3, 9] def test_model_set_row_skip_on_none(self): list_store = Gtk.ListStore(int, int, int, int) list_store.append([1, 2, 3, 4]) iter_ = list_store.get_iter_first() list_store.set_row(iter_, [None, 7, None, 9]) assert list_store[0][:] == [1, 7, 3, 9] @unittest.skipIf(sys.platform == "darwin", "hangs") @unittest.skipUnless(Gtk, "Gtk not available") class TestTreeView(unittest.TestCase): def test_tree_view(self): store = Gtk.ListStore(int, str) store.append((0, "foo")) store.append((1, "bar")) view = Gtk.TreeView() with realized(view): view.set_cursor(store[1].path) view.set_cursor(str(store[1].path)) view.get_cell_area(store[1].path) view.get_cell_area(str(store[1].path)) def test_tree_view_column(self): cell = Gtk.CellRendererText() col = Gtk.TreeViewColumn( title="This is just a test", cell_renderer=cell, text=0, style=2 ) # Regression test for: https://bugzilla.gnome.org/show_bug.cgi?id=711173 col.set_cell_data_func(cell, None, None) def test_tree_view_add_column_with_attributes(self): model = Gtk.ListStore(str, str, str) # deliberately use out-of-order sorting here; we assign column 0 to # model index 2, etc. model.append(["cell13", "cell11", "cell12"]) model.append(["cell23", "cell21", "cell22"]) tree = Gtk.TreeView(model=model) cell1 = Gtk.CellRendererText() cell2 = Gtk.CellRendererText() cell3 = Gtk.CellRendererText() cell4 = Gtk.CellRendererText() tree.insert_column_with_attributes(0, "Head2", cell2, text=2) tree.insert_column_with_attributes(0, "Head1", cell1, text=1) tree.insert_column_with_attributes(-1, "Head3", cell3, text=0) # unconnected tree.insert_column_with_attributes(-1, "Head4", cell4) with realized(tree): tree.set_cursor(model[0].path) if Gtk._version == "4.0": context = GLib.MainContext() while context.pending(): context.iteration(False) else: while Gtk.events_pending(): Gtk.main_iteration() self.assertEqual(tree.get_column(0).get_title(), "Head1") self.assertEqual(tree.get_column(1).get_title(), "Head2") self.assertEqual(tree.get_column(2).get_title(), "Head3") self.assertEqual(tree.get_column(3).get_title(), "Head4") # cursor should be at the first row if not GTK4: # not sure why this doesn't work with gtk4 self.assertEqual(cell1.props.text, "cell11") self.assertEqual(cell2.props.text, "cell12") self.assertEqual(cell3.props.text, "cell13") self.assertEqual(cell4.props.text, None) def test_tree_view_column_set_attributes(self): store = Gtk.ListStore(int, str) directors = ["Fellini", "Tarantino", "Tarkovskiy"] for i, director in enumerate(directors): store.append([i, director]) treeview = Gtk.TreeView() treeview.set_model(store) column = Gtk.TreeViewColumn() treeview.append_column(column) cell = Gtk.CellRendererText() column.pack_start(cell, expand=True) column.set_attributes(cell, text=1) with realized(treeview): if not GTK4: # not sure why this doesn't work with gtk4 self.assertTrue(cell.props.text in directors) def test_tree_selection(self): store = Gtk.ListStore(int, str) for i in range(10): store.append((i, "foo")) view = Gtk.TreeView() view.set_model(store) firstpath = store.get_path(store.get_iter_first()) sel = view.get_selection() sel.select_path(firstpath) (m, s) = sel.get_selected() self.assertEqual(m, store) self.assertEqual(store.get_path(s), firstpath) sel.select_path(0) (m, s) = sel.get_selected() self.assertEqual(m, store) self.assertEqual(store.get_path(s), firstpath) sel.select_path("0:0") (m, s) = sel.get_selected() self.assertEqual(m, store) self.assertEqual(store.get_path(s), firstpath) sel.select_path((0, 0)) (m, s) = sel.get_selected() self.assertEqual(m, store) self.assertEqual(store.get_path(s), firstpath) sel.unselect_all() (m, s) = sel.get_selected() assert s is None sel.select_path(0) m, r = sel.get_selected_rows() assert m == store assert len(r) == 1 assert r[0] == store[0].path def test_scroll_to_cell(self): store = Gtk.ListStore(int, str) store.append((0, "foo")) view = Gtk.TreeView() view.set_model(store) view.scroll_to_cell(store[0].path) view.scroll_to_cell(0) @unittest.skipUnless(Gtk, "Gtk not available") class TestTextBuffer(unittest.TestCase): def test_text_buffer(self): self.assertEqual(Gtk.TextBuffer, gi.overrides.Gtk.TextBuffer) buffer = Gtk.TextBuffer() assert buffer.get_tag_table() is not None tag = buffer.create_tag("title", font="Sans 18") self.assertEqual(tag.props.name, "title") self.assertEqual(tag.props.font, "Sans 18") (start, end) = buffer.get_bounds() mark = buffer.create_mark(None, start) self.assertFalse(mark.get_left_gravity()) buffer.set_text("Hello Jane Hello Bob") (start, end) = buffer.get_bounds() text = buffer.get_text(start, end, False) self.assertEqual(text, "Hello Jane Hello Bob") buffer.set_text("") (start, end) = buffer.get_bounds() text = buffer.get_text(start, end, False) self.assertEqual(text, "") buffer.insert(end, "HelloHello") buffer.insert(end, " Bob") cursor_iter = end.copy() cursor_iter.backward_chars(9) buffer.place_cursor(cursor_iter) buffer.insert_at_cursor(" Jane ") (start, end) = buffer.get_bounds() text = buffer.get_text(start, end, False) self.assertEqual(text, "Hello Jane Hello Bob") sel = buffer.get_selection_bounds() self.assertEqual(sel, ()) buffer.select_range(start, end) sel = buffer.get_selection_bounds() self.assertTrue(sel[0].equal(start)) self.assertTrue(sel[1].equal(end)) buffer.set_text("") buffer.insert_with_tags(buffer.get_start_iter(), "HelloHello") start, end = buffer.get_bounds() text = buffer.get_text(start, end, False) self.assertEqual(text, "HelloHello") buffer.set_text("") buffer.insert_with_tags_by_name(buffer.get_start_iter(), "HelloHello") start, end = buffer.get_bounds() text = buffer.get_text(start, end, False) self.assertEqual(text, "HelloHello") try: starts_tag = Gtk.TextIter.starts_tag except AttributeError: starts_tag = Gtk.TextIter.begins_tag buffer.set_text("") buffer.insert_with_tags(buffer.get_start_iter(), "HelloHello", tag) (start, end) = buffer.get_bounds() self.assertTrue(starts_tag(start, tag)) self.assertTrue(start.has_tag(tag)) buffer.set_text("") buffer.insert_with_tags_by_name(buffer.get_start_iter(), "HelloHello", "title") (start, end) = buffer.get_bounds() self.assertTrue(starts_tag(start, tag)) self.assertTrue(start.has_tag(tag)) self.assertRaises( ValueError, buffer.insert_with_tags_by_name, buffer.get_start_iter(), "HelloHello", "unknowntag", ) def test_insert(self): buffer = Gtk.TextBuffer() start = buffer.get_bounds()[0] with pytest.raises(TypeError): buffer.insert(start, 42) with pytest.raises(TypeError): buffer.insert_at_cursor(42) def test_text_iter(self): try: starts_tag = Gtk.TextIter.starts_tag except AttributeError: starts_tag = Gtk.TextIter.begins_tag self.assertEqual(Gtk.TextIter, gi.overrides.Gtk.TextIter) buffer = Gtk.TextBuffer() buffer.set_text("Hello Jane Hello Bob") tag = buffer.create_tag("title", font="Sans 18") (start, end) = buffer.get_bounds() start.forward_chars(10) buffer.apply_tag(tag, start, end) self.assertTrue(starts_tag(start)) self.assertTrue(end.ends_tag()) self.assertTrue(start.toggles_tag()) self.assertTrue(end.toggles_tag()) start.backward_chars(1) self.assertFalse(starts_tag(start)) self.assertFalse(start.ends_tag()) self.assertFalse(start.toggles_tag()) def test_text_buffer_search(self): buffer = Gtk.TextBuffer() buffer.set_text("Hello World Hello GNOME") i = buffer.get_iter_at_offset(0) self.assertTrue(isinstance(i, Gtk.TextIter)) self.assertEqual(i.forward_search("world", 0, None), None) (start, end) = i.forward_search("World", 0, None) self.assertEqual(start.get_offset(), 6) self.assertEqual(end.get_offset(), 11) (start, end) = i.forward_search( "world", Gtk.TextSearchFlags.CASE_INSENSITIVE, None ) self.assertEqual(start.get_offset(), 6) self.assertEqual(end.get_offset(), 11) def test_insert_text_signal_location_modification(self): # Regression test for: https://bugzilla.gnome.org/show_bug.cgi?id=736175 def callback(buffer, location, text, length): location.assign(buffer.get_end_iter()) buffer = Gtk.TextBuffer() buffer.set_text("first line\n") buffer.connect("insert-text", callback) # attempt insertion at the beginning of the buffer, the callback will # modify the insert location to the end. buffer.place_cursor(buffer.get_start_iter()) buffer.insert_at_cursor("second line\n") self.assertEqual(buffer.get_property("text"), "first line\nsecond line\n") @unittest.skipIf(gtkver() < (3, 20, 0), "broken with older gtk") def test_backward_find_char(self): buffer = Gtk.TextBuffer() buffer.set_text("abc") res = buffer.get_iter_at_line(99) end = res.iter if GTK4 else res values = [] def pred_func(ch, user_data): values.append(ch) return ch == "a" self.assertTrue(end.backward_find_char(pred_func)) self.assertEqual(values, ["c", "b", "a"]) @unittest.skipUnless(Gtk, "Gtk not available") @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") class TestPaned(unittest.TestCase): def test_pack_defaults(self): p = Gtk.Paned() l1 = Gtk.Label() l2 = Gtk.Label() p.pack1(l1) p.pack2(l2) assert p.get_children() == [l1, l2] @unittest.skipUnless(Gtk, "Gtk not available") class TestContainer(unittest.TestCase): @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_child_set_property(self): box = Gtk.Box() child = Gtk.Button() box.pack_start(child, expand=False, fill=True, padding=0) box.child_set_property(child, "padding", 42) value = GObject.Value(int) box.child_get_property(child, "padding", value) self.assertEqual(value.get_int(), 42) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_child_get_property_gvalue(self): box = Gtk.Box() child = Gtk.Button() box.pack_start(child, expand=False, fill=True, padding=42) value = GObject.Value(int) box.child_get_property(child, "padding", value) self.assertEqual(value.get_int(), 42) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_child_get_property_return_with_explicit_gvalue(self): box = Gtk.Box() child = Gtk.Button() box.pack_start(child, expand=False, fill=True, padding=42) value = GObject.Value(int) result = box.child_get_property(child, "padding", value) self.assertEqual(result, 42) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_child_get_property_return_with_implicit_gvalue(self): box = Gtk.Box() child = Gtk.Button() box.pack_start(child, expand=False, fill=True, padding=42) result = box.child_get_property(child, "padding") self.assertEqual(result, 42) @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_child_get_property_error(self): box = Gtk.Box() child = Gtk.Button() if Gtk_version == "4.0": box.add(child) else: box.pack_start(child, expand=False, fill=True, padding=42) with self.assertRaises(ValueError): box.child_get_property(child, "not-a-valid-child-property") @unittest.skipIf(Gtk_version == "4.0", "not in gtk4") def test_child_get_and_set(self): box = Gtk.Box() child = Gtk.Button() box.pack_start(child, expand=True, fill=True, padding=42) expand, fill, padding = box.child_get(child, "expand", "fill", "padding") self.assertEqual(expand, True) self.assertEqual(fill, True) self.assertEqual(padding, 42) box.child_set(child, expand=False, fill=False, padding=21, pack_type=1) expand, fill, padding, _pack_type = box.child_get( child, "expand", "fill", "padding", "pack-type" ) self.assertEqual(expand, False) self.assertEqual(fill, False) self.assertEqual(padding, 21) @pytest.mark.skipif(not Gtk, reason="Test requires GTK") def test_button_focus_on_click(): b = Gtk.Button() b.set_focus_on_click(True) assert b.get_focus_on_click() b.set_focus_on_click(False) assert not b.get_focus_on_click() @pytest.mark.skipif(not Gtk, reason="Test requires GTK") @pytest.mark.parametrize( "data", ["* { background: white; }", b"* { background: white; }"] ) def test_css_provider_load_from_data(data): provider = Gtk.CssProvider.new() provider.load_from_data(data) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_overrides_pango.py0000664000000000000000000000423515074673150020313 0ustar00rootrootimport unittest try: from gi.repository import Pango from gi.repository import PangoCairo except ImportError: Pango = None PangoCairo = None @unittest.skipUnless(Pango, "Pango not available") class TestPango(unittest.TestCase): def test_default_font_description(self): desc = Pango.FontDescription() self.assertEqual(desc.get_variant(), Pango.Variant.NORMAL) def test_font_description(self): desc = Pango.FontDescription("monospace") self.assertEqual(desc.get_family(), "monospace") self.assertEqual(desc.get_variant(), Pango.Variant.NORMAL) def test_layout(self): self.assertRaises(TypeError, Pango.Layout) context = Pango.Context() layout = Pango.Layout(context) self.assertEqual(layout.get_context(), context) layout.set_markup("Foobar") self.assertEqual(layout.get_text(), "Foobar") def test_layout_set_markup(self): context = Pango.Context() layout = Pango.Layout(context) layout.set_markup("abc") assert layout.get_text() == "abc" layout.set_markup("abc", -1) assert layout.get_text() == "abc" layout.set_markup("abc", 2) assert layout.get_text() == "ab" def test_layout_set_test(self): context = Pango.Context() layout = Pango.Layout(context) layout.set_text("abc") assert layout.get_text() == "abc" layout.set_text("abc", -1) assert layout.get_text() == "abc" layout.set_text("abc", 2) assert layout.get_text() == "ab" def test_break_keyword_escape(self): # https://bugzilla.gnome.org/show_bug.cgi?id=697363 self.assertTrue(hasattr(Pango, "break_")) self.assertTrue(Pango.break_ is not None) def test_context_get_metrics(self): # Test default "language" argument font_map = PangoCairo.font_map_get_default() context = font_map.create_context() desc = Pango.FontDescription("monospace") metrics1 = context.get_metrics(desc) metrics2 = context.get_metrics(desc, context.get_language()) self.assertEqual(metrics1.get_ascent(), metrics2.get_ascent()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_properties.py0000664000000000000000000015251215074673150017323 0ustar00rootrootimport os import gc import sys import struct import types import unittest import tempfile import pytest from gi.repository import GObject from gi.repository.GObject import ParamFlags, GType, new from gi.repository.GObject import ( TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_INT64, TYPE_UINT64, TYPE_GTYPE, TYPE_INVALID, TYPE_NONE, TYPE_STRV, TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR, TYPE_BOOLEAN, TYPE_FLOAT, TYPE_DOUBLE, TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, TYPE_STRING, TYPE_PYOBJECT, TYPE_VARIANT, ) from gi.repository.GLib import ( MININT, MAXINT, MAXUINT, MINLONG, MAXLONG, MAXULONG, MAXUINT64, MAXINT64, MININT64, ) from gi.repository import Gio from gi.repository import GLib from gi.repository import GIMarshallingTests from gi.repository import Regress from gi import _propertyhelper as propertyhelper from .helper import capture_glib_warnings class PropertyObject(GObject.GObject): normal = GObject.Property(type=str) construct = GObject.Property( type=str, flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT, default="default", ) construct_only = GObject.Property( type=str, flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT_ONLY, ) uint64 = GObject.Property( type=TYPE_UINT64, flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT, ) enum = GObject.Property(type=Gio.SocketType, default=Gio.SocketType.STREAM) boxed = GObject.Property( type=GLib.Regex, flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT, ) flags = GObject.Property( type=GIMarshallingTests.Flags, flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT, default=GIMarshallingTests.Flags.VALUE1, ) gtype = GObject.Property( type=TYPE_GTYPE, flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT, ) strings = GObject.Property( type=TYPE_STRV, flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT, ) variant = GObject.Property( type=TYPE_VARIANT, flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT, ) variant_def = GObject.Property( type=TYPE_VARIANT, flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT, default=GLib.Variant("i", 42), ) interface = GObject.Property( type=Gio.File, flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT, ) class PropertyInheritanceObject(Regress.TestObj): # override property from the base class, with a different type string = GObject.Property(type=int) # a property entirely defined at the Python level python_prop = GObject.Property(type=str) class PropertySubClassObject(PropertyInheritanceObject): # override property from the base class, with a different type python_prop = GObject.Property(type=int) class TestPropertyInheritanceObject(unittest.TestCase): def test_override_gi_property(self): self.assertNotEqual( Regress.TestObj.props.string.value_type, PropertyInheritanceObject.props.string.value_type, ) obj = PropertyInheritanceObject() self.assertEqual(type(obj.props.string), int) obj.props.string = 4 self.assertEqual(obj.props.string, 4) def test_override_python_property(self): obj = PropertySubClassObject() self.assertEqual(type(obj.props.python_prop), int) obj.props.python_prop = 5 self.assertEqual(obj.props.python_prop, 5) class TestPropertyObject(unittest.TestCase): def test_get_set(self): obj = PropertyObject() obj.props.normal = "value" self.assertEqual(obj.props.normal, "value") def test_hasattr_on_object(self): obj = PropertyObject() self.assertTrue(hasattr(obj.props, "normal")) def test_hasattr_on_class(self): self.assertTrue(hasattr(PropertyObject.props, "normal")) def test_set_on_class(self): def set(obj): obj.props.normal = "foobar" self.assertRaises(TypeError, set, PropertyObject) def test_iteration(self): for obj in (PropertyObject.props, PropertyObject().props): names = [] for pspec in obj: gtype = GType(pspec) self.assertEqual(gtype.parent.name, "GParam") names.append(pspec.name) names.sort() self.assertEqual( names, [ "boxed", "construct", "construct-only", "enum", "flags", "gtype", "interface", "normal", "strings", "uint64", "variant", "variant-def", ], ) def test_iterator_protocol_for_properties(self): action = Gio.SimpleAction() i = iter(action.props) assert i is iter(i) def test_normal(self): obj = new(PropertyObject, normal="123") self.assertEqual(obj.props.normal, "123") obj.set_property("normal", "456") self.assertEqual(obj.props.normal, "456") obj.props.normal = "789" self.assertEqual(obj.props.normal, "789") def test_construct(self): obj = new(PropertyObject, construct="123") self.assertEqual(obj.props.construct, "123") obj.set_property("construct", "456") self.assertEqual(obj.props.construct, "456") obj.props.construct = "789" self.assertEqual(obj.props.construct, "789") def test_utf8(self): test_utf8 = "♥" unicode_utf8 = "♥" obj = new(PropertyObject, construct_only=unicode_utf8) self.assertEqual(obj.props.construct_only, test_utf8) obj.set_property("construct", unicode_utf8) self.assertEqual(obj.props.construct, test_utf8) obj.props.normal = unicode_utf8 self.assertEqual(obj.props.normal, test_utf8) def test_utf8_lone_surrogate(self): obj = PropertyObject() with pytest.raises(TypeError): obj.set_property("construct", "\ud83d") def test_int_to_str(self): obj = new(PropertyObject, construct_only=1) self.assertEqual(obj.props.construct_only, "1") obj.set_property("construct", "2") self.assertEqual(obj.props.construct, "2") obj.props.normal = 3 self.assertEqual(obj.props.normal, "3") def test_construct_only(self): obj = new(PropertyObject, construct_only="123") self.assertEqual(obj.props.construct_only, "123") self.assertRaises(TypeError, setattr, obj.props, "construct_only", "456") self.assertRaises(TypeError, obj.set_property, "construct-only", "456") def test_uint64(self): obj = new(PropertyObject) self.assertEqual(obj.props.uint64, 0) obj.props.uint64 = 1 self.assertEqual(obj.props.uint64, 1) obj.props.uint64 = 1 self.assertEqual(obj.props.uint64, 1) self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", -1) self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", -1) def test_uint64_default_value(self): try: class TimeControl(GObject.GObject): __gproperties__ = { "time": ( TYPE_UINT64, "Time", "Time", 0, (1 << 64) - 1, 0, ParamFlags.READABLE, ) } except OverflowError: (_etype, ex) = sys.exc_info()[2:] self.fail(str(ex)) def test_enum(self): obj = new(PropertyObject) self.assertEqual(obj.props.enum, Gio.SocketType.STREAM) self.assertEqual(obj.enum, Gio.SocketType.STREAM) obj.enum = Gio.SocketType.DATAGRAM self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM) self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM) obj.props.enum = Gio.SocketType.STREAM self.assertEqual(obj.props.enum, Gio.SocketType.STREAM) self.assertEqual(obj.enum, Gio.SocketType.STREAM) obj.props.enum = 2 self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM) self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM) obj.enum = 1 self.assertEqual(obj.props.enum, Gio.SocketType.STREAM) self.assertEqual(obj.enum, Gio.SocketType.STREAM) self.assertRaises(TypeError, setattr, obj, "enum", "foo") self.assertRaises(TypeError, setattr, obj, "enum", object()) self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType) self.assertRaises( TypeError, GObject.Property, type=Gio.SocketType, default=Gio.SocketProtocol.TCP, ) self.assertRaises( TypeError, GObject.Property, type=Gio.SocketType, default=object() ) self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType, default=1) def test_repr(self): prop = GObject.Property(type=int) assert repr(prop) == "" def test_flags(self): obj = new(PropertyObject) self.assertEqual(obj.props.flags, GIMarshallingTests.Flags.VALUE1) self.assertEqual(obj.flags, GIMarshallingTests.Flags.VALUE1) obj.flags = GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3 self.assertEqual( obj.props.flags, GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3, ) self.assertEqual( obj.flags, GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3 ) self.assertRaises(TypeError, setattr, obj, "flags", "foo") self.assertRaises(TypeError, setattr, obj, "flags", object()) self.assertRaises(TypeError, setattr, obj, "flags", None) self.assertRaises( TypeError, GObject.Property, type=GIMarshallingTests.Flags, default="foo" ) self.assertRaises( TypeError, GObject.Property, type=GIMarshallingTests.Flags, default=object() ) self.assertRaises( TypeError, GObject.Property, type=GIMarshallingTests.Flags, default=None ) def test_gtype(self): obj = new(PropertyObject) self.assertEqual(obj.props.gtype, TYPE_NONE) self.assertEqual(obj.gtype, TYPE_NONE) obj.gtype = TYPE_UINT64 self.assertEqual(obj.props.gtype, TYPE_UINT64) self.assertEqual(obj.gtype, TYPE_UINT64) obj.gtype = TYPE_INVALID self.assertEqual(obj.props.gtype, TYPE_INVALID) self.assertEqual(obj.gtype, TYPE_INVALID) # GType parameters do not support defaults in GLib self.assertRaises( TypeError, GObject.Property, type=TYPE_GTYPE, default=TYPE_INT ) # incompatible type self.assertRaises(TypeError, setattr, obj, "gtype", "foo") self.assertRaises(TypeError, setattr, obj, "gtype", object()) self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE, default="foo") self.assertRaises( TypeError, GObject.Property, type=TYPE_GTYPE, default=object() ) # set in constructor obj = new(PropertyObject, gtype=TYPE_UINT) self.assertEqual(obj.props.gtype, TYPE_UINT) self.assertEqual(obj.gtype, TYPE_UINT) def test_boxed(self): obj = new(PropertyObject) regex = GLib.Regex.new("[a-z]*", 0, 0) obj.props.boxed = regex self.assertEqual(obj.props.boxed.get_pattern(), "[a-z]*") self.assertEqual(obj.boxed.get_pattern(), "[a-z]*") self.assertRaises(TypeError, setattr, obj, "boxed", "foo") self.assertRaises(TypeError, setattr, obj, "boxed", object()) def test_strings(self): obj = new(PropertyObject) # Should work with actual GStrv objects as well as # Python string lists class GStrv(list): __gtype__ = GObject.TYPE_STRV self.assertEqual(obj.props.strings, GStrv([])) self.assertEqual(obj.strings, GStrv([])) self.assertEqual(obj.props.strings, []) self.assertEqual(obj.strings, []) obj.strings = ["hello", "world"] self.assertEqual(obj.props.strings, ["hello", "world"]) self.assertEqual(obj.strings, ["hello", "world"]) obj.strings = GStrv(["hello", "world"]) self.assertEqual(obj.props.strings, GStrv(["hello", "world"])) self.assertEqual(obj.strings, GStrv(["hello", "world"])) obj.strings = [] self.assertEqual(obj.strings, []) obj.strings = GStrv([]) self.assertEqual(obj.strings, GStrv([])) p = GObject.Property(type=TYPE_STRV, default=["hello", "1"]) self.assertEqual(p.default, ["hello", "1"]) self.assertEqual(p.type, TYPE_STRV) p = GObject.Property(type=TYPE_STRV, default=GStrv(["hello", "1"])) self.assertEqual(p.default, ["hello", "1"]) self.assertEqual(p.type, TYPE_STRV) # set in constructor obj = new(PropertyObject, strings=["hello", "world"]) self.assertEqual(obj.props.strings, ["hello", "world"]) self.assertEqual(obj.strings, ["hello", "world"]) # wrong types self.assertRaises(TypeError, setattr, obj, "strings", 1) self.assertRaises(TypeError, setattr, obj, "strings", "foo") self.assertRaises(TypeError, setattr, obj, "strings", ["foo", 1]) self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV, default=1) self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV, default="foo") self.assertRaises( TypeError, GObject.Property, type=TYPE_STRV, default=["hello", 1] ) def test_variant(self): obj = new(PropertyObject) self.assertEqual(obj.props.variant, None) self.assertEqual(obj.variant, None) obj.variant = GLib.Variant("s", "hello") self.assertEqual(obj.variant.print_(True), "'hello'") obj.variant = GLib.Variant("b", True) self.assertEqual(obj.variant.print_(True), "true") obj.props.variant = GLib.Variant("y", 2) self.assertEqual(obj.variant.print_(True), "byte 0x02") obj.variant = None self.assertEqual(obj.variant, None) # set in constructor obj = new(PropertyObject, variant=GLib.Variant("u", 5)) self.assertEqual(obj.props.variant.print_(True), "uint32 5") GObject.Property(type=TYPE_VARIANT, default=GLib.Variant("i", 1)) # incompatible types self.assertRaises(TypeError, setattr, obj, "variant", "foo") self.assertRaises(TypeError, setattr, obj, "variant", 42) self.assertRaises(TypeError, GObject.Property, type=TYPE_VARIANT, default="foo") self.assertRaises( TypeError, GObject.Property, type=TYPE_VARIANT, default=object() ) def test_variant_default(self): obj = new(PropertyObject) self.assertEqual(obj.props.variant_def.print_(True), "42") self.assertEqual(obj.variant_def.print_(True), "42") obj.props.variant_def = GLib.Variant("y", 2) self.assertEqual(obj.variant_def.print_(True), "byte 0x02") # set in constructor obj = new(PropertyObject, variant_def=GLib.Variant("u", 5)) self.assertEqual(obj.props.variant_def.print_(True), "uint32 5") def test_interface(self): obj = new(PropertyObject) path = os.path.join(tempfile.gettempdir(), "some", "path") file = Gio.File.new_for_path(path) obj.props.interface = file self.assertEqual(obj.props.interface.get_path(), path) self.assertEqual(obj.interface.get_path(), path) self.assertRaises(TypeError, setattr, obj, "interface", "foo") self.assertRaises(TypeError, setattr, obj, "interface", object()) def test_range(self): # kiwi code def max(c): return 2 ** ((8 * struct.calcsize(c)) - 1) - 1 def umax(c): return 2 ** (8 * struct.calcsize(c)) - 1 maxint = max("i") minint = -maxint - 1 maxuint = umax("I") maxlong = max("l") minlong = -maxlong - 1 maxulong = umax("L") maxint64 = max("q") minint64 = -maxint64 - 1 maxuint64 = umax("Q") types_ = { "int": (TYPE_INT, minint, maxint), "uint": (TYPE_UINT, 0, maxuint), "long": (TYPE_LONG, minlong, maxlong), "ulong": (TYPE_ULONG, 0, maxulong), "int64": (TYPE_INT64, minint64, maxint64), "uint64": (TYPE_UINT64, 0, maxuint64), } def build_gproperties(types_): d = {} for key, (gtype, min, max) in types_.items(): d[key] = ( gtype, "blurb", "desc", min, max, 0, ParamFlags.READABLE | ParamFlags.WRITABLE, ) return d class RangeCheck(GObject.GObject): __gproperties__ = build_gproperties(types_) def __init__(self): self.values = {} GObject.GObject.__init__(self) def do_set_property(self, pspec, value): self.values[pspec.name] = value def do_get_property(self, pspec): return self.values.get(pspec.name, pspec.default_value) self.assertEqual(RangeCheck.props.int.minimum, minint) self.assertEqual(RangeCheck.props.int.maximum, maxint) self.assertEqual(RangeCheck.props.uint.minimum, 0) self.assertEqual(RangeCheck.props.uint.maximum, maxuint) self.assertEqual(RangeCheck.props.long.minimum, minlong) self.assertEqual(RangeCheck.props.long.maximum, maxlong) self.assertEqual(RangeCheck.props.ulong.minimum, 0) self.assertEqual(RangeCheck.props.ulong.maximum, maxulong) self.assertEqual(RangeCheck.props.int64.minimum, minint64) self.assertEqual(RangeCheck.props.int64.maximum, maxint64) self.assertEqual(RangeCheck.props.uint64.minimum, 0) self.assertEqual(RangeCheck.props.uint64.maximum, maxuint64) obj = RangeCheck() for key, (gtype, min, max) in types_.items(): self.assertEqual( obj.get_property(key), getattr(RangeCheck.props, key).default_value ) obj.set_property(key, min) self.assertEqual(obj.get_property(key), min) obj.set_property(key, max) self.assertEqual(obj.get_property(key), max) def test_multi(self): obj = PropertyObject() obj.set_properties(normal="foo", uint64=7) normal, uint64 = obj.get_properties("normal", "uint64") self.assertEqual(normal, "foo") self.assertEqual(uint64, 7) class TestProperty(unittest.TestCase): def test_simple(self): class C(GObject.GObject): str = GObject.Property(type=str) float = GObject.Property(type=float) long = GObject.Property(type=int) int = GObject.Property(type=int) self.assertTrue(hasattr(C.props, "str")) self.assertTrue(hasattr(C.props, "int")) self.assertTrue(hasattr(C.props, "float")) self.assertTrue(hasattr(C.props, "long")) o = C() self.assertEqual(o.str, "") o.str = "str" self.assertEqual(o.str, "str") self.assertEqual(o.int, 0) o.int = 1138 self.assertEqual(o.int, 1138) self.assertEqual(o.float, 0.0) o.float = 3.14 self.assertEqual(o.float, 3.14) self.assertEqual(o.long, 0) o.long = 100 self.assertEqual(o.long, 100) def test_custom_getter(self): class C(GObject.GObject): def get_prop(self): return "value" prop = GObject.Property(getter=get_prop) o = C() self.assertEqual(o.prop, "value") self.assertRaises(TypeError, setattr, o, "prop", "xxx") def test_getter_exception(self): class C(GObject.Object): @GObject.Property(type=int) def prop(self): raise ValueError("something bad happend") o = C() with self.assertRaisesRegex(ValueError, "something bad happend"): o.prop with self.assertRaisesRegex(ValueError, "something bad happend"): o.get_property("prop") with self.assertRaisesRegex(ValueError, "something bad happend"): o.props.prop def test_custom_setter(self): class C(GObject.GObject): def set_prop(self, value): self._value = value prop = GObject.Property(setter=set_prop) def __init__(self): self._value = None GObject.GObject.__init__(self) o = C() self.assertEqual(o._value, None) o.prop = "bar" self.assertEqual(o._value, "bar") self.assertRaises(TypeError, getattr, o, "prop") def test_decorator_default(self): class C(GObject.GObject): _value = "value" @GObject.Property def value(self): return self._value @value.setter def value_setter(self, value): self._value = value o = C() self.assertEqual(o.value, "value") o.value = "blah" self.assertEqual(o.value, "blah") self.assertEqual(o.props.value, "blah") def test_decorator_private_setter(self): class C(GObject.GObject): _value = "value" @GObject.Property def value(self): return self._value @value.setter def _set_value(self, value): self._value = value o = C() self.assertEqual(o.value, "value") o.value = "blah" self.assertEqual(o.value, "blah") self.assertEqual(o.props.value, "blah") def test_decorator_with_call(self): class C(GObject.GObject): _value = 1 @GObject.Property(type=int, default=1, minimum=1, maximum=10) def typedValue(self): return self._value @typedValue.setter def typedValue_setter(self, value): self._value = value o = C() self.assertEqual(o.typedValue, 1) o.typedValue = 5 self.assertEqual(o.typedValue, 5) self.assertEqual(o.props.typedValue, 5) def test_errors(self): self.assertRaises(TypeError, GObject.Property, type="str") self.assertRaises(TypeError, GObject.Property, nick=False) self.assertRaises(TypeError, GObject.Property, blurb=False) # this never fail while bool is a subclass of int # >>> bool.__bases__ # (,) # self.assertRaises(TypeError, GObject.Property, type=bool, default=0) self.assertRaises(TypeError, GObject.Property, type=bool, default="ciao mamma") self.assertRaises(TypeError, GObject.Property, type=bool) self.assertRaises(TypeError, GObject.Property, type=object, default=0) self.assertRaises(TypeError, GObject.Property, type=complex) def test_defaults(self): GObject.Property(type=bool, default=True) GObject.Property(type=bool, default=False) def test_name_with_underscore(self): class C(GObject.GObject): prop_name = GObject.Property(type=int) o = C() o.prop_name = 10 self.assertEqual(o.prop_name, 10) def test_range(self): types_ = [ (TYPE_INT, MININT, MAXINT), (TYPE_UINT, 0, MAXUINT), (TYPE_LONG, MINLONG, MAXLONG), (TYPE_ULONG, 0, MAXULONG), (TYPE_INT64, MININT64, MAXINT64), (TYPE_UINT64, 0, MAXUINT64), ] for gtype, min, max in types_: # Normal, everything is alright prop = GObject.Property(type=gtype, minimum=min, maximum=max) subtype = type("", (GObject.GObject,), {"prop": prop}) self.assertEqual(subtype.props.prop.minimum, min) self.assertEqual(subtype.props.prop.maximum, max) # Lower than minimum self.assertRaises( TypeError, GObject.Property, type=gtype, minimum=min - 1, maximum=max ) # Higher than maximum self.assertRaises( TypeError, GObject.Property, type=gtype, minimum=min, maximum=max + 1 ) def test_min_max(self): class C(GObject.GObject): prop_int = GObject.Property(type=int, minimum=1, maximum=100, default=1) prop_float = GObject.Property( type=float, minimum=0.1, maximum=10.5, default=1.1 ) def __init__(self): GObject.GObject.__init__(self) # we test known-bad values here which cause Gtk-WARNING logs. # Explicitly allow these for this test. with capture_glib_warnings(allow_warnings=True, allow_criticals=True): o = C() self.assertEqual(o.prop_int, 1) o.prop_int = 5 self.assertEqual(o.prop_int, 5) o.prop_int = 0 self.assertEqual(o.prop_int, 5) o.prop_int = 101 self.assertEqual(o.prop_int, 5) self.assertEqual(o.prop_float, 1.1) o.prop_float = 7.75 self.assertEqual(o.prop_float, 7.75) o.prop_float = 0.09 self.assertEqual(o.prop_float, 7.75) o.prop_float = 10.51 self.assertEqual(o.prop_float, 7.75) def test_multiple_instances(self): class C(GObject.GObject): prop = GObject.Property(type=str, default="default") o1 = C() o2 = C() self.assertEqual(o1.prop, "default") self.assertEqual(o2.prop, "default") o1.prop = "value" self.assertEqual(o1.prop, "value") self.assertEqual(o2.prop, "default") def test_object_property(self): class PropertyObject(GObject.GObject): obj = GObject.Property(type=GObject.GObject) pobj1 = PropertyObject() obj1_hash = hash(pobj1) pobj2 = PropertyObject() pobj2.obj = pobj1 del pobj1 pobj1 = pobj2.obj self.assertEqual(hash(pobj1), obj1_hash) def test_object_subclass_property(self): class ObjectSubclass(GObject.GObject): __gtype_name__ = "ObjectSubclass" class PropertyObjectSubclass(GObject.GObject): obj = GObject.Property(type=ObjectSubclass) PropertyObjectSubclass(obj=ObjectSubclass()) def test_property_subclass(self): # test for #470718 class A(GObject.GObject): prop1 = GObject.Property(type=int) class B(A): prop2 = GObject.Property(type=int) b = B() b.prop2 = 10 self.assertEqual(b.prop2, 10) b.prop1 = 20 self.assertEqual(b.prop1, 20) def test_property_subclass_c(self): class A(Regress.TestSubObj): prop1 = GObject.Property(type=int) a = A() a.prop1 = 10 self.assertEqual(a.prop1, 10) # also has parent properties a.props.int = 20 self.assertEqual(a.props.int, 20) # Some of which are unusable without introspection a.props.list = ("str1", "str2") self.assertEqual(a.props.list, ["str1", "str2"]) a.set_property("list", ("str3", "str4")) self.assertEqual(a.props.list, ["str3", "str4"]) def test_property_subclass_custom_setter(self): # test for #523352 class A(GObject.GObject): def get_first(self): return "first" first = GObject.Property(type=str, getter=get_first) class B(A): def get_second(self): return "second" second = GObject.Property(type=str, getter=get_second) a = A() self.assertEqual(a.first, "first") self.assertRaises(TypeError, setattr, a, "first", "foo") b = B() self.assertEqual(b.first, "first") self.assertRaises(TypeError, setattr, b, "first", "foo") self.assertEqual(b.second, "second") self.assertRaises(TypeError, setattr, b, "second", "foo") def test_property_subclass_custom_setter_error(self): try: class A(GObject.GObject): def get_first(self): return "first" first = GObject.Property(type=str, getter=get_first) def do_get_property(self, pspec): pass except TypeError: pass else: raise AssertionError # Bug 587637. def test_float_min(self): GObject.Property(type=float, minimum=-1) GObject.Property(type=GObject.TYPE_FLOAT, minimum=-1) GObject.Property(type=GObject.TYPE_DOUBLE, minimum=-1) # Bug 644039 @unittest.skipUnless(hasattr(sys, "getrefcount"), "no sys.getrefcount") def test_reference_count(self): # We can check directly if an object gets finalized, so we will # observe it indirectly through the refcount of a member object. # We create our dummy object and store its current refcount o = object() rc = sys.getrefcount(o) # We add our object as a member to our newly created object we # want to observe. Its refcount is increased by one. t = PropertyObject(normal="test") t.o = o self.assertEqual(sys.getrefcount(o), rc + 1) # Now we want to ensure we do not leak any references to our # object with properties. If no ref is leaked, then when deleting # the local reference to this object, its reference count shoud # drop to zero, and our dummy object should loose one reference. del t self.assertEqual(sys.getrefcount(o), rc) def test_doc_strings(self): class C(GObject.GObject): foo_blurbed = GObject.Property(type=int, blurb="foo_blurbed doc string") @GObject.Property def foo_getter(self): """foo_getter doc string""" return 0 self.assertEqual(C.foo_blurbed.blurb, "foo_blurbed doc string") self.assertEqual(C.foo_blurbed.__doc__, "foo_blurbed doc string") self.assertEqual(C.foo_getter.blurb, "foo_getter doc string") self.assertEqual(C.foo_getter.__doc__, "foo_getter doc string") def test_python_to_glib_type_mapping(self): tester = GObject.Property() self.assertEqual(tester._type_from_python(int), GObject.TYPE_INT) self.assertEqual(tester._type_from_python(bool), GObject.TYPE_BOOLEAN) self.assertEqual(tester._type_from_python(float), GObject.TYPE_DOUBLE) self.assertEqual(tester._type_from_python(str), GObject.TYPE_STRING) self.assertEqual(tester._type_from_python(object), GObject.TYPE_PYOBJECT) self.assertEqual( tester._type_from_python(GObject.GObject), GObject.GObject.__gtype__ ) self.assertEqual( tester._type_from_python(GObject.GEnum), GObject.GEnum.__gtype__ ) self.assertEqual( tester._type_from_python(GObject.GFlags), GObject.GFlags.__gtype__ ) self.assertEqual( tester._type_from_python(GObject.GBoxed), GObject.GBoxed.__gtype__ ) self.assertEqual( tester._type_from_python(GObject.GInterface), GObject.GInterface.__gtype__ ) for type_ in [ TYPE_NONE, TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR, TYPE_INT, TYPE_UINT, TYPE_BOOLEAN, TYPE_LONG, TYPE_ULONG, TYPE_INT64, TYPE_UINT64, TYPE_FLOAT, TYPE_DOUBLE, TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, TYPE_STRING, TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV, ]: self.assertEqual(tester._type_from_python(type_), type_) self.assertRaises(TypeError, tester._type_from_python, types.CodeType) class TestInstallProperties(unittest.TestCase): # These tests only test how signalhelper.install_signals works # with the __gsignals__ dict and therefore does not need to use # GObject as a base class because that would automatically call # install_signals within the meta-class. class Base: __gproperties__ = {"test": (0, "", "", 0, 0, 0, 0)} class Sub1(Base): pass class Sub2(Base): @GObject.Property(type=int) def sub2test(self): return 123 class ClassWithPropertyAndGetterVFunc: @GObject.Property(type=int) def sub2test(self): return 123 def do_get_property(self, name): return 321 class ClassWithPropertyRedefined: __gproperties__ = {"test": (0, "", "", 0, 0, 0, 0)} test = GObject.Property(type=int) def setUp(self): self.assertEqual(len(self.Base.__gproperties__), 1) propertyhelper.install_properties(self.Base) self.assertEqual(len(self.Base.__gproperties__), 1) def test_subclass_without_properties_is_not_modified(self): self.assertFalse("__gproperties__" in self.Sub1.__dict__) propertyhelper.install_properties(self.Sub1) self.assertFalse("__gproperties__" in self.Sub1.__dict__) def test_subclass_with_decorator_gets_gproperties_dict(self): # Sub2 has Property instances but will not have a __gproperties__ # until install_properties is called self.assertFalse("__gproperties__" in self.Sub2.__dict__) self.assertFalse("do_get_property" in self.Sub2.__dict__) self.assertFalse("do_set_property" in self.Sub2.__dict__) propertyhelper.install_properties(self.Sub2) self.assertTrue("__gproperties__" in self.Sub2.__dict__) self.assertEqual(len(self.Base.__gproperties__), 1) self.assertEqual(len(self.Sub2.__gproperties__), 1) self.assertTrue("sub2test" in self.Sub2.__gproperties__) # get/set vfuncs should have been added self.assertTrue("do_get_property" in self.Sub2.__dict__) self.assertTrue("do_set_property" in self.Sub2.__dict__) def test_object_with_property_and_do_get_property_vfunc_raises(self): self.assertRaises( TypeError, propertyhelper.install_properties, self.ClassWithPropertyAndGetterVFunc, ) def test_same_name_property_definitions_raises(self): self.assertRaises( ValueError, propertyhelper.install_properties, self.ClassWithPropertyRedefined, ) class CPropertiesTestBase: # Tests for properties implemented in C not Python. def setUp(self): self.obj = GIMarshallingTests.PropertiesObject() def get_prop(self, obj, name): raise NotImplementedError def set_prop(self, obj, name, value): raise NotImplementedError def test_flags(self): self.assertEqual( self.get_prop(self.obj, "some-flags"), GIMarshallingTests.Flags.VALUE1 ) self.set_prop(self.obj, "some-flags", GIMarshallingTests.Flags.VALUE2) self.assertEqual( self.get_prop(self.obj, "some-flags"), GIMarshallingTests.Flags.VALUE2 ) obj = GIMarshallingTests.PropertiesObject( some_flags=GIMarshallingTests.Flags.VALUE3 ) self.assertEqual( self.get_prop(obj, "some-flags"), GIMarshallingTests.Flags.VALUE3 ) def test_flags_values(self): prop = self.obj.find_property("some-flags") flags_class = prop.flags_class assert GIMarshallingTests.Flags.VALUE1 in flags_class assert GIMarshallingTests.Flags.VALUE2 in flags_class assert GIMarshallingTests.Flags.VALUE3 in flags_class def test_enum(self): self.assertEqual( self.get_prop(self.obj, "some-enum"), GIMarshallingTests.GEnum.VALUE1 ) self.set_prop(self.obj, "some-enum", GIMarshallingTests.GEnum.VALUE2) self.assertEqual( self.get_prop(self.obj, "some-enum"), GIMarshallingTests.GEnum.VALUE2 ) obj = GIMarshallingTests.PropertiesObject( some_enum=GIMarshallingTests.GEnum.VALUE3 ) self.assertEqual( self.get_prop(obj, "some-enum"), GIMarshallingTests.GEnum.VALUE3 ) def test_enum_values(self): prop = self.obj.find_property("some-enum") enum_class = prop.enum_class assert GIMarshallingTests.GEnum.VALUE1 in enum_class assert GIMarshallingTests.GEnum.VALUE2 in enum_class assert GIMarshallingTests.GEnum.VALUE3 in enum_class def test_boolean(self): self.assertEqual(self.get_prop(self.obj, "some-boolean"), False) self.set_prop(self.obj, "some-boolean", True) self.assertEqual(self.get_prop(self.obj, "some-boolean"), True) obj = GIMarshallingTests.PropertiesObject(some_boolean=True) self.assertEqual(self.get_prop(obj, "some-boolean"), True) def test_char(self): self.assertEqual(self.get_prop(self.obj, "some-char"), 0) self.set_prop(self.obj, "some-char", GLib.MAXINT8) self.assertEqual(self.get_prop(self.obj, "some-char"), GLib.MAXINT8) obj = GIMarshallingTests.PropertiesObject(some_char=-42) self.assertEqual(self.get_prop(obj, "some-char"), -42) with pytest.raises(OverflowError): self.set_prop(obj, "some-char", GLib.MAXINT8 + 1) with pytest.raises(OverflowError): self.set_prop(obj, "some-char", GLib.MININT8 - 1) self.set_prop(obj, "some-char", b"\x44") assert self.get_prop(obj, "some-char") == 0x44 self.set_prop(obj, "some-char", b"\xff") assert self.get_prop(obj, "some-char") == -1 obj = GIMarshallingTests.PropertiesObject(some_char="\x7f") assert self.get_prop(obj, "some-char") == 0x7F with pytest.raises(TypeError): GIMarshallingTests.PropertiesObject(some_char="€") with pytest.raises(TypeError): GIMarshallingTests.PropertiesObject(some_char="\ud83d") def test_uchar(self): self.assertEqual(self.get_prop(self.obj, "some-uchar"), 0) self.set_prop(self.obj, "some-uchar", GLib.MAXUINT8) self.assertEqual(self.get_prop(self.obj, "some-uchar"), GLib.MAXUINT8) obj = GIMarshallingTests.PropertiesObject(some_uchar=42) self.assertEqual(self.get_prop(obj, "some-uchar"), 42) with pytest.raises(OverflowError): self.set_prop(obj, "some-uchar", GLib.MAXUINT8 + 1) with pytest.raises(OverflowError): self.set_prop(obj, "some-uchar", -1) self.set_prop(obj, "some-uchar", b"\x57") assert self.get_prop(obj, "some-uchar") == 0x57 self.set_prop(obj, "some-uchar", b"\xff") assert self.get_prop(obj, "some-uchar") == 255 obj = GIMarshallingTests.PropertiesObject(some_uchar="\x7f") assert self.get_prop(obj, "some-uchar") == 127 with pytest.raises(TypeError): GIMarshallingTests.PropertiesObject(some_uchar="\x80") with pytest.raises(TypeError): GIMarshallingTests.PropertiesObject(some_uchar="\ud83d") def test_int(self): self.assertEqual(self.get_prop(self.obj, "some_int"), 0) self.set_prop(self.obj, "some-int", GLib.MAXINT) self.assertEqual(self.get_prop(self.obj, "some_int"), GLib.MAXINT) obj = GIMarshallingTests.PropertiesObject(some_int=-42) self.assertEqual(self.get_prop(obj, "some-int"), -42) self.assertRaises(TypeError, self.set_prop, self.obj, "some-int", "foo") self.assertRaises(TypeError, self.set_prop, self.obj, "some-int", None) self.assertEqual(self.get_prop(obj, "some-int"), -42) def test_uint(self): self.assertEqual(self.get_prop(self.obj, "some_uint"), 0) self.set_prop(self.obj, "some-uint", GLib.MAXUINT) self.assertEqual(self.get_prop(self.obj, "some_uint"), GLib.MAXUINT) obj = GIMarshallingTests.PropertiesObject(some_uint=42) self.assertEqual(self.get_prop(obj, "some-uint"), 42) self.assertRaises(TypeError, self.set_prop, self.obj, "some-uint", "foo") self.assertRaises(TypeError, self.set_prop, self.obj, "some-uint", None) self.assertEqual(self.get_prop(obj, "some-uint"), 42) def test_long(self): self.assertEqual(self.get_prop(self.obj, "some_long"), 0) self.set_prop(self.obj, "some-long", GLib.MAXLONG) self.assertEqual(self.get_prop(self.obj, "some_long"), GLib.MAXLONG) obj = GIMarshallingTests.PropertiesObject(some_long=-42) self.assertEqual(self.get_prop(obj, "some-long"), -42) self.assertRaises(TypeError, self.set_prop, self.obj, "some-long", "foo") self.assertRaises(TypeError, self.set_prop, self.obj, "some-long", None) self.assertEqual(self.get_prop(obj, "some-long"), -42) def test_ulong(self): self.assertEqual(self.get_prop(self.obj, "some_ulong"), 0) self.set_prop(self.obj, "some-ulong", GLib.MAXULONG) self.assertEqual(self.get_prop(self.obj, "some_ulong"), GLib.MAXULONG) obj = GIMarshallingTests.PropertiesObject(some_ulong=42) self.assertEqual(self.get_prop(obj, "some-ulong"), 42) self.assertRaises(TypeError, self.set_prop, self.obj, "some-ulong", "foo") self.assertRaises(TypeError, self.set_prop, self.obj, "some-ulong", None) self.assertEqual(self.get_prop(obj, "some-ulong"), 42) def test_int64(self): self.assertEqual(self.get_prop(self.obj, "some-int64"), 0) self.set_prop(self.obj, "some-int64", GLib.MAXINT64) self.assertEqual(self.get_prop(self.obj, "some-int64"), GLib.MAXINT64) obj = GIMarshallingTests.PropertiesObject(some_int64=-4200000000000000) self.assertEqual(self.get_prop(obj, "some-int64"), -4200000000000000) def test_uint64(self): self.assertEqual(self.get_prop(self.obj, "some-uint64"), 0) self.set_prop(self.obj, "some-uint64", GLib.MAXUINT64) self.assertEqual(self.get_prop(self.obj, "some-uint64"), GLib.MAXUINT64) obj = GIMarshallingTests.PropertiesObject(some_uint64=4200000000000000) self.assertEqual(self.get_prop(obj, "some-uint64"), 4200000000000000) def test_float(self): self.assertEqual(self.get_prop(self.obj, "some-float"), 0) self.set_prop(self.obj, "some-float", GLib.MAXFLOAT) self.assertEqual(self.get_prop(self.obj, "some-float"), GLib.MAXFLOAT) obj = GIMarshallingTests.PropertiesObject(some_float=42.42) self.assertAlmostEqual(self.get_prop(obj, "some-float"), 42.42, places=4) obj = GIMarshallingTests.PropertiesObject(some_float=42) self.assertAlmostEqual(self.get_prop(obj, "some-float"), 42.0, places=4) self.assertRaises(TypeError, self.set_prop, self.obj, "some-float", "foo") self.assertRaises(TypeError, self.set_prop, self.obj, "some-float", None) self.assertAlmostEqual(self.get_prop(obj, "some-float"), 42.0, places=4) def test_double(self): self.assertEqual(self.get_prop(self.obj, "some-double"), 0) self.set_prop(self.obj, "some-double", GLib.MAXDOUBLE) self.assertEqual(self.get_prop(self.obj, "some-double"), GLib.MAXDOUBLE) obj = GIMarshallingTests.PropertiesObject(some_double=42.42) self.assertAlmostEqual(self.get_prop(obj, "some-double"), 42.42) obj = GIMarshallingTests.PropertiesObject(some_double=42) self.assertAlmostEqual(self.get_prop(obj, "some-double"), 42.0) self.assertRaises(TypeError, self.set_prop, self.obj, "some-double", "foo") self.assertRaises(TypeError, self.set_prop, self.obj, "some-double", None) self.assertAlmostEqual(self.get_prop(obj, "some-double"), 42.0) def test_strv(self): self.assertEqual(self.get_prop(self.obj, "some-strv"), []) self.set_prop(self.obj, "some-strv", ["hello", "world"]) self.assertEqual(self.get_prop(self.obj, "some-strv"), ["hello", "world"]) self.assertRaises(TypeError, self.set_prop, self.obj, "some-strv", 1) self.assertRaises(TypeError, self.set_prop, self.obj, "some-strv", "foo") self.assertRaises(TypeError, self.set_prop, self.obj, "some-strv", [1, 2]) self.assertRaises(TypeError, self.set_prop, self.obj, "some-strv", ["foo", 1]) self.assertEqual(self.get_prop(self.obj, "some-strv"), ["hello", "world"]) obj = GIMarshallingTests.PropertiesObject(some_strv=["hello", "world"]) self.assertEqual(self.get_prop(obj, "some-strv"), ["hello", "world"]) # unicode on py2 obj = GIMarshallingTests.PropertiesObject(some_strv=["foo"]) self.assertEqual(self.get_prop(obj, "some-strv"), ["foo"]) self.assertRaises(TypeError, self.set_prop, self.obj, "some-strv", ["foo", 1]) def test_boxed_struct(self): self.assertEqual(self.get_prop(self.obj, "some-boxed-struct"), None) class GStrv(list): __gtype__ = GObject.TYPE_STRV struct1 = GIMarshallingTests.BoxedStruct() struct1.long_ = 1 self.set_prop(self.obj, "some-boxed-struct", struct1) self.assertEqual(self.get_prop(self.obj, "some-boxed-struct").long_, 1) self.assertEqual(self.obj.some_boxed_struct.long_, 1) self.assertRaises(TypeError, self.set_prop, self.obj, "some-boxed-struct", 1) self.assertRaises( TypeError, self.set_prop, self.obj, "some-boxed-struct", "foo" ) obj = GIMarshallingTests.PropertiesObject(some_boxed_struct=struct1) self.assertEqual(self.get_prop(obj, "some-boxed-struct").long_, 1) def test_boxed_glist(self): self.assertEqual(self.get_prop(self.obj, "some-boxed-glist"), []) list_ = [GLib.MININT, 42, GLib.MAXINT] self.set_prop(self.obj, "some-boxed-glist", list_) self.assertEqual(self.get_prop(self.obj, "some-boxed-glist"), list_) self.set_prop(self.obj, "some-boxed-glist", []) self.assertEqual(self.get_prop(self.obj, "some-boxed-glist"), []) self.assertRaises(TypeError, self.set_prop, self.obj, "some-boxed-glist", 1) self.assertRaises(TypeError, self.set_prop, self.obj, "some-boxed-glist", "foo") self.assertRaises(TypeError, self.set_prop, self.obj, "some-boxed-glist", ["a"]) def test_annotated_glist(self): obj = Regress.TestObj() self.assertEqual(self.get_prop(obj, "list"), []) self.set_prop(obj, "list", ["1", "2", "3"]) self.assertTrue(isinstance(self.get_prop(obj, "list"), list)) self.assertEqual(self.get_prop(obj, "list"), ["1", "2", "3"]) @unittest.expectedFailure def test_boxed_glist_ctor(self): list_ = [GLib.MININT, 42, GLib.MAXINT] obj = GIMarshallingTests.PropertiesObject(some_boxed_glist=list_) self.assertEqual(self.get_prop(obj, "some-boxed-glist"), list_) def test_variant(self): self.assertEqual(self.get_prop(self.obj, "some-variant"), None) self.set_prop(self.obj, "some-variant", GLib.Variant("o", "/myobj")) self.assertEqual(self.get_prop(self.obj, "some-variant").get_type_string(), "o") self.assertEqual( self.get_prop(self.obj, "some-variant").print_(False), "'/myobj'" ) self.set_prop(self.obj, "some-variant", None) self.assertEqual(self.get_prop(self.obj, "some-variant"), None) obj = GIMarshallingTests.PropertiesObject(some_variant=GLib.Variant("b", True)) self.assertEqual(self.get_prop(obj, "some-variant").get_type_string(), "b") self.assertEqual(self.get_prop(obj, "some-variant").get_boolean(), True) self.assertRaises(TypeError, self.set_prop, self.obj, "some-variant", "foo") self.assertRaises(TypeError, self.set_prop, self.obj, "some-variant", 23) self.assertEqual(self.get_prop(obj, "some-variant").get_type_string(), "b") self.assertEqual(self.get_prop(obj, "some-variant").get_boolean(), True) def test_setting_several_properties(self): obj = GIMarshallingTests.PropertiesObject() obj.set_properties(some_uchar=54, some_int=42) self.assertEqual(42, self.get_prop(obj, "some-int")) self.assertEqual(54, self.get_prop(obj, "some-uchar")) def test_gtype(self): obj = Regress.TestObj() self.assertEqual(self.get_prop(obj, "gtype"), GObject.TYPE_INVALID) self.set_prop(obj, "gtype", int) self.assertEqual(self.get_prop(obj, "gtype"), GObject.TYPE_INT) obj = Regress.TestObj(gtype=int) self.assertEqual(self.get_prop(obj, "gtype"), GObject.TYPE_INT) self.set_prop(obj, "gtype", str) self.assertEqual(self.get_prop(obj, "gtype"), GObject.TYPE_STRING) def test_hash_table(self): obj = Regress.TestObj() self.assertEqual(self.get_prop(obj, "hash-table"), None) self.set_prop(obj, "hash-table", {"mec": 56}) self.assertTrue(isinstance(self.get_prop(obj, "hash-table"), dict)) self.assertEqual( next(iter(self.get_prop(obj, "hash-table").items())), ("mec", 56) ) def test_parent_class(self): class A(Regress.TestObj): prop1 = GObject.Property(type=int) a = A() self.set_prop(a, "int", 20) self.assertEqual(self.get_prop(a, "int"), 20) # test parent property which needs introspection self.set_prop(a, "list", ("str1", "str2")) self.assertEqual(self.get_prop(a, "list"), ["str1", "str2"]) def test_held_object_ref_count_getter(self): holder = GIMarshallingTests.PropertiesObject() held = GObject.Object() self.assertEqual(holder.__grefcount__, 1) self.assertEqual(held.__grefcount__, 1) self.set_prop(holder, "some-object", held) self.assertEqual(holder.__grefcount__, 1) initial_ref_count = held.__grefcount__ self.get_prop(holder, "some-object") gc.collect() self.assertEqual(held.__grefcount__, initial_ref_count) def test_held_object_ref_count_setter(self): holder = GIMarshallingTests.PropertiesObject() held = GObject.Object() self.assertEqual(holder.__grefcount__, 1) self.assertEqual(held.__grefcount__, 1) # Setting property should only increase ref count by 1 self.set_prop(holder, "some-object", held) self.assertEqual(holder.__grefcount__, 1) self.assertEqual(held.__grefcount__, 2) # Clearing should pull it back down self.set_prop(holder, "some-object", None) self.assertEqual(held.__grefcount__, 1) def test_set_object_property_to_invalid_type(self): obj = GIMarshallingTests.PropertiesObject() self.assertRaises(TypeError, self.set_prop, obj, "some-object", "not_an_object") class TestCPropsAccessor(CPropertiesTestBase, unittest.TestCase): # C property tests using the "props" accessor. def get_prop(self, obj, name): return getattr(obj.props, name.replace("-", "_")) def set_prop(self, obj, name, value): setattr(obj.props, name.replace("-", "_"), value) def test_props_accessor_dir(self): # Test class props = dir(GIMarshallingTests.PropertiesObject.props) self.assertTrue("some_float" in props) self.assertTrue("some_double" in props) self.assertTrue("some_variant" in props) # Test instance obj = GIMarshallingTests.PropertiesObject() props = dir(obj.props) self.assertTrue("some_float" in props) self.assertTrue("some_double" in props) self.assertTrue("some_variant" in props) def test_param_spec_dir(self): attrs = dir(GIMarshallingTests.PropertiesObject.props.some_float) self.assertTrue("name" in attrs) self.assertTrue("nick" in attrs) self.assertTrue("blurb" in attrs) self.assertTrue("flags" in attrs) self.assertTrue("default_value" in attrs) self.assertTrue("minimum" in attrs) self.assertTrue("maximum" in attrs) class TestCGetPropertyMethod(CPropertiesTestBase, unittest.TestCase): # C property tests using the "props" accessor. def get_prop(self, obj, name): return obj.get_property(name) def set_prop(self, obj, name, value): obj.set_property(name, value) def test_gobject_inheritance_with_incomplete_initialization(): class Test: def __init__(self): # super().__init__() should have been called here pass class Bomb(Test, GObject.Object): def __init__(self): super().__init__() bomb = Bomb() with pytest.raises(RuntimeError, match="is not initialized"): bomb.qdata @pytest.mark.skipif( not hasattr(Regress, "AnnotationObject"), reason="no Regress.AnnotationObject" ) def test_get_function_property(): obj = Regress.AnnotationObject() with pytest.raises(TypeError): assert obj.props.function_property @pytest.mark.skipif( not hasattr(Regress, "AnnotationObject"), reason="no Regress.AnnotationObject" ) def test_set_function_property(): obj = Regress.AnnotationObject() with pytest.raises(TypeError): obj.props.function_property = lambda *x: x ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_pycapi.py0000664000000000000000000000206415074673150016410 0ustar00rootrootimport unittest import ctypes from ctypes import c_void_p, py_object, c_char_p import gi from gi.repository import Gio def get_capi(): if not hasattr(ctypes, "pythonapi"): return None class CAPI(ctypes.Structure): _fields_ = [ ("", c_void_p), ("", c_void_p), ("", c_void_p), ("newgobj", ctypes.PYFUNCTYPE(py_object, c_void_p)), ] api_obj = gi._gobject._PyGObject_API func_type = ctypes.PYFUNCTYPE(c_void_p, py_object, c_char_p) PyCapsule_GetPointer = func_type(("PyCapsule_GetPointer", ctypes.pythonapi)) ptr = PyCapsule_GetPointer(api_obj, b"gobject._PyGObject_API") ptr = ctypes.cast(ptr, ctypes.POINTER(CAPI)) return ptr.contents API = get_capi() @unittest.skipUnless(API, "no pythonapi support") class TestPythonCAPI(unittest.TestCase): def test_newgobj(self): w = Gio.FileInfo() # XXX: ugh :/ ptr = int(repr(w).split()[-1].split(")")[0], 16) capi = get_capi() new_w = capi.newgobj(ptr) assert w == new_w ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_pygtkcompat.py0000664000000000000000000000024215074673150017461 0ustar00rootrootimport pytest import pygtkcompat def test_pygtkcompat(): with pytest.raises(RuntimeError, match="pygtkcompat is deprecated"): pygtkcompat.enable() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_repository.py0000664000000000000000000004713115074673150017346 0ustar00rootroot# Copyright (C) 2013 Simon Feltman # # test_repository.py: Test for the GIRepository module # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import unittest from collections import abc import gi._gi as GIRepository from gi.module import repository as repo from gi.repository import GObject from gi.repository import GIRepository as IntrospectedRepository def find_child_info(info, getter_name, name): getter = getattr(info, getter_name) for child in getter(): if child.get_name() == name: return child else: raise ValueError(f"child info {name} not found") class Test(unittest.TestCase): def setUp(self): repo.require("GLib") repo.require("GObject") repo.require("GIMarshallingTests") def test_repo_get_dependencies(self): self.assertRaises(TypeError, repo.get_dependencies) self.assertEqual(repo.get_dependencies("GLib"), []) self.assertEqual(repo.get_dependencies("GObject"), ["GLib-2.0"]) def test_repo_is_registered(self): self.assertRaises(TypeError, repo.is_registered) self.assertRaises(TypeError, repo.is_registered, None) self.assertTrue(repo.is_registered("GIRepository")) self.assertTrue(repo.is_registered("GIRepository", None)) self.assertTrue(isinstance(repo.is_registered("GIRepository"), bool)) self.assertTrue(repo.is_registered("GIRepository", "3.0")) self.assertFalse(repo.is_registered("GIRepository", "")) self.assertFalse(repo.is_registered("GIRepository", "99.0")) self.assertFalse(repo.is_registered("GIRepository", "1.0")) def test_repo_get_immediate_dependencies(self): self.assertRaises(TypeError, repo.get_immediate_dependencies) self.assertEqual(repo.get_immediate_dependencies("GLib"), []) self.assertEqual(repo.get_immediate_dependencies("GObject"), ["GLib-2.0"]) self.assertEqual( repo.get_immediate_dependencies(namespace="GObject"), ["GLib-2.0"] ) self.assertEqual( repo.get_immediate_dependencies("GIMarshallingTests"), ["Gio-2.0"] ) def test_arg_info(self): func_info = repo.find_by_name("GIMarshallingTests", "array_fixed_out_struct") args = func_info.get_arguments() self.assertTrue(len(args), 1) arg = args[0] self.assertEqual(arg.get_container(), func_info) self.assertEqual(arg.get_direction(), GIRepository.Direction.OUT) self.assertEqual(arg.get_name(), "structs") self.assertEqual(arg.get_namespace(), "GIMarshallingTests") self.assertFalse(arg.is_caller_allocates()) self.assertFalse(arg.is_optional()) self.assertFalse(arg.is_return_value()) self.assertFalse(arg.may_be_null()) self.assertEqual(arg.get_destroy_index(), -1) self.assertEqual(arg.get_ownership_transfer(), GIRepository.Transfer.NOTHING) self.assertEqual(arg.get_scope(), GIRepository.ScopeType.INVALID) self.assertEqual(arg.get_type_info().get_tag(), GIRepository.TypeTag.ARRAY) def test_base_info(self): info = repo.find_by_name("GIMarshallingTests", "Object") self.assertEqual(info.__name__, "Object") self.assertEqual(info.get_name(), "Object") self.assertEqual(info.__module__, "gi.repository.GIMarshallingTests") self.assertEqual(info.get_name_unescaped(), "Object") self.assertEqual(info.get_namespace(), "GIMarshallingTests") self.assertEqual(info.get_container(), None) info2 = repo.find_by_name("GIMarshallingTests", "Object") self.assertFalse(info is info2) self.assertEqual(info, info2) self.assertTrue(info.equal(info2)) assert isinstance(info.is_deprecated(), bool) assert info.get_attribute("nopenope") is None def test_object_info(self): info = repo.find_by_name("GIMarshallingTests", "Object") self.assertEqual(info.get_parent(), repo.find_by_name("GObject", "Object")) self.assertTrue(isinstance(info.get_methods(), abc.Iterable)) self.assertTrue(isinstance(info.get_fields(), abc.Iterable)) self.assertTrue(isinstance(info.get_interfaces(), abc.Iterable)) self.assertTrue(isinstance(info.get_constants(), abc.Iterable)) self.assertTrue(isinstance(info.get_vfuncs(), abc.Iterable)) self.assertTrue(isinstance(info.get_properties(), abc.Iterable)) self.assertFalse(info.get_abstract()) self.assertEqual( info.get_class_struct(), repo.find_by_name("GIMarshallingTests", "ObjectClass"), ) self.assertEqual(info.get_type_name(), "GIMarshallingTestsObject") self.assertEqual(info.get_type_init(), "gi_marshalling_tests_object_get_type") self.assertFalse(info.get_fundamental()) self.assertEqual(info.get_parent(), repo.find_by_name("GObject", "Object")) assert info.find_vfunc("nopenope") is None vfunc = info.find_vfunc("method_int8_out") assert isinstance(vfunc, GIRepository.VFuncInfo) def test_callable_inheritance(self): self.assertTrue(issubclass(GIRepository.CallableInfo, GIRepository.BaseInfo)) self.assertTrue( issubclass(GIRepository.CallbackInfo, GIRepository.CallableInfo) ) self.assertTrue( issubclass(GIRepository.FunctionInfo, GIRepository.CallableInfo) ) self.assertTrue(issubclass(GIRepository.VFuncInfo, GIRepository.CallableInfo)) self.assertTrue(issubclass(GIRepository.SignalInfo, GIRepository.CallableInfo)) def test_registered_type_info(self): info = repo.find_by_name("GIMarshallingTests", "Object") # Call these from the class because GIObjectInfo overrides them self.assertEqual( GIRepository.RegisteredTypeInfo.get_g_type(info), GObject.type_from_name("GIMarshallingTestsObject"), ) self.assertEqual( GIRepository.RegisteredTypeInfo.get_type_name(info), "GIMarshallingTestsObject", ) self.assertEqual( GIRepository.RegisteredTypeInfo.get_type_init(info), "gi_marshalling_tests_object_get_type", ) def test_fundamental_object_info(self): repo.require("Regress") info = repo.find_by_name("Regress", "TestFundamentalObject") self.assertTrue(info.get_abstract()) self.assertTrue(info.get_fundamental()) self.assertEqual(info.get_ref_function(), "regress_test_fundamental_object_ref") self.assertEqual( info.get_unref_function(), "regress_test_fundamental_object_unref" ) self.assertEqual( info.get_get_value_function(), "regress_test_value_get_fundamental_object" ) self.assertEqual( info.get_set_value_function(), "regress_test_value_set_fundamental_object" ) def test_interface_info(self): info = repo.find_by_name("GIMarshallingTests", "Interface") self.assertTrue(isinstance(info.get_methods(), abc.Iterable)) self.assertTrue(isinstance(info.get_vfuncs(), abc.Iterable)) self.assertTrue(isinstance(info.get_constants(), abc.Iterable)) self.assertTrue(isinstance(info.get_prerequisites(), abc.Iterable)) self.assertTrue(isinstance(info.get_properties(), abc.Iterable)) self.assertTrue(isinstance(info.get_signals(), abc.Iterable)) method = info.find_method("test_int8_in") vfunc = info.find_vfunc("test_int8_in") self.assertEqual(method.get_name(), "test_int8_in") self.assertEqual(vfunc.get_invoker(), method) self.assertEqual(method.get_vfunc(), vfunc) iface = info.get_iface_struct() self.assertEqual( iface, repo.find_by_name("GIMarshallingTests", "InterfaceIface") ) assert info.find_signal("nopenope") is None def test_struct_info(self): info = repo.find_by_name("GIMarshallingTests", "InterfaceIface") self.assertTrue(isinstance(info, GIRepository.StructInfo)) self.assertTrue(isinstance(info.get_fields(), abc.Iterable)) self.assertTrue(isinstance(info.get_methods(), abc.Iterable)) self.assertTrue(isinstance(info.get_size(), int)) self.assertTrue(isinstance(info.get_alignment(), int)) self.assertTrue(info.is_gtype_struct()) self.assertFalse(info.is_foreign()) info = repo.find_by_name("GIMarshallingTests", "SimpleStruct") assert info.find_method("nope") is None assert isinstance(info.find_method("method"), GIRepository.FunctionInfo) assert info.find_field("nope") is None assert isinstance(info.find_field("int8"), GIRepository.FieldInfo) def test_enum_info(self): info = repo.find_by_name("GIMarshallingTests", "Enum") self.assertTrue(isinstance(info, GIRepository.EnumInfo)) self.assertTrue(isinstance(info.get_values(), abc.Iterable)) self.assertTrue(isinstance(info.get_methods(), abc.Iterable)) self.assertFalse(info.is_flags()) self.assertTrue(info.get_storage_type() > 0) # might be platform dependent def test_union_info(self): info = repo.find_by_name("GIMarshallingTests", "Union") self.assertTrue(isinstance(info, GIRepository.UnionInfo)) self.assertTrue(isinstance(info.get_fields(), abc.Iterable)) self.assertTrue(isinstance(info.get_methods(), abc.Iterable)) self.assertTrue(isinstance(info.get_size(), int)) self.assertTrue(isinstance(info.get_alignment(), int)) def test_type_info(self): func_info = repo.find_by_name("GIMarshallingTests", "array_fixed_out_struct") (arg_info,) = func_info.get_arguments() type_info = arg_info.get_type_info() self.assertTrue(type_info.is_pointer()) self.assertEqual(type_info.get_tag(), GIRepository.TypeTag.ARRAY) self.assertEqual(type_info.get_tag_as_string(), "array") self.assertEqual( type_info.get_param_type(0).get_tag(), GIRepository.TypeTag.INTERFACE ) self.assertEqual( type_info.get_param_type(0).get_interface(), repo.find_by_name("GIMarshallingTests", "SimpleStruct"), ) self.assertEqual(type_info.get_interface(), None) self.assertEqual(type_info.get_array_length_index(), -1) self.assertEqual(type_info.get_array_fixed_size(), 2) self.assertFalse(type_info.is_zero_terminated()) self.assertEqual(type_info.get_array_type(), GIRepository.ArrayType.C) def test_field_info(self): info = repo.find_by_name("GIMarshallingTests", "InterfaceIface") field = find_child_info(info, "get_fields", "test_int8_in") self.assertEqual(field.get_name(), "test_int8_in") self.assertTrue(field.get_flags() & GIRepository.FieldInfoFlags.IS_READABLE) self.assertFalse(field.get_flags() & GIRepository.FieldInfoFlags.IS_WRITABLE) self.assertEqual( field.get_type_info().get_tag(), GIRepository.TypeTag.INTERFACE ) # don't test actual values because that might fail with architecture differences self.assertTrue(isinstance(field.get_size(), int)) self.assertTrue(isinstance(field.get_offset(), int)) def test_property_info(self): info = repo.find_by_name("GIMarshallingTests", "PropertiesObject") prop = find_child_info(info, "get_properties", "some-object") flags = ( GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE | GObject.ParamFlags.CONSTRUCT ) self.assertEqual(prop.get_flags(), flags) self.assertEqual(prop.get_type_info().get_tag(), GIRepository.TypeTag.INTERFACE) self.assertEqual( prop.get_type_info().get_interface(), repo.find_by_name("GObject", "Object") ) self.assertEqual(prop.get_ownership_transfer(), GIRepository.Transfer.NOTHING) def test_callable_info(self): func_info = repo.find_by_name("GIMarshallingTests", "array_fixed_out_struct") self.assertTrue(hasattr(func_info, "invoke")) self.assertTrue(isinstance(func_info.get_arguments(), abc.Iterable)) self.assertEqual(func_info.get_caller_owns(), GIRepository.Transfer.NOTHING) self.assertFalse(func_info.may_return_null()) self.assertEqual( func_info.get_return_type().get_tag(), GIRepository.TypeTag.VOID ) self.assertRaises( AttributeError, func_info.get_return_attribute, "_not_an_attr" ) def test_signal_info(self): repo.require("Regress") info = repo.find_by_name("Regress", "TestObj") sig_info = find_child_info(info, "get_signals", "test") sig_flags = ( GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.NO_RECURSE | GObject.SignalFlags.NO_HOOKS ) self.assertTrue(sig_info is not None) self.assertTrue(isinstance(sig_info, GIRepository.CallableInfo)) self.assertTrue(isinstance(sig_info, GIRepository.SignalInfo)) self.assertEqual(sig_info.get_name(), "test") self.assertEqual(sig_info.get_class_closure(), None) self.assertFalse(sig_info.true_stops_emit()) self.assertEqual(sig_info.get_flags(), sig_flags) def test_notify_signal_info_with_obj(self): repo.require("Regress") info = repo.find_by_name("Regress", "TestObj") sig_info = find_child_info(info, "get_signals", "sig-with-array-prop") sig_flags = GObject.SignalFlags.RUN_LAST self.assertTrue(sig_info is not None) self.assertTrue(isinstance(sig_info, GIRepository.CallableInfo)) self.assertTrue(isinstance(sig_info, GIRepository.SignalInfo)) self.assertEqual(sig_info.get_name(), "sig-with-array-prop") self.assertEqual(sig_info.get_class_closure(), None) self.assertFalse(sig_info.true_stops_emit()) self.assertEqual(sig_info.get_flags(), sig_flags) def test_object_constructor(self): info = repo.find_by_name("GIMarshallingTests", "Object") method = find_child_info(info, "get_methods", "new") self.assertTrue(isinstance(method, GIRepository.CallableInfo)) self.assertTrue(isinstance(method, GIRepository.FunctionInfo)) self.assertTrue(method in info.get_methods()) self.assertEqual(method.get_name(), "new") self.assertFalse(method.is_method()) self.assertTrue(method.is_constructor()) self.assertEqual(method.get_symbol(), "gi_marshalling_tests_object_new") flags = method.get_flags() self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_METHOD) self.assertTrue(flags & GIRepository.FunctionInfoFlags.IS_CONSTRUCTOR) self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_GETTER) self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_SETTER) self.assertFalse(flags & GIRepository.FunctionInfoFlags.WRAPS_VFUNC) def test_method_info(self): info = repo.find_by_name("GIMarshallingTests", "Object") method = find_child_info(info, "get_methods", "vfunc_return_value_only") self.assertTrue(isinstance(method, GIRepository.CallableInfo)) self.assertTrue(isinstance(method, GIRepository.FunctionInfo)) self.assertTrue(method in info.get_methods()) self.assertEqual(method.get_name(), "vfunc_return_value_only") self.assertFalse(method.is_constructor()) self.assertEqual( method.get_symbol(), "gi_marshalling_tests_object_vfunc_return_value_only" ) self.assertTrue(method.is_method()) flags = method.get_flags() self.assertTrue(flags & GIRepository.FunctionInfoFlags.IS_METHOD) self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_CONSTRUCTOR) self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_GETTER) self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_SETTER) self.assertFalse(flags & GIRepository.FunctionInfoFlags.WRAPS_VFUNC) def test_method_finish_func(self): repo.require("Regress") info = repo.find_by_name("Regress", "TestObj") method = find_child_info(info, "get_methods", "function_finish") assert method.get_finish_func() is None def test_async_method_finish_func(self): repo.require("Regress") info = repo.find_by_name("Regress", "TestObj") method = find_child_info(info, "get_methods", "function_async") finish_func = method.get_finish_func() assert finish_func.get_name() == "function_finish" def test_vfunc_info(self): info = repo.find_by_name("GIMarshallingTests", "Object") invoker = find_child_info(info, "get_methods", "vfunc_return_value_only") vfunc = find_child_info(info, "get_vfuncs", "vfunc_return_value_only") self.assertTrue(isinstance(vfunc, GIRepository.CallableInfo)) self.assertTrue(isinstance(vfunc, GIRepository.VFuncInfo)) self.assertEqual(vfunc.get_name(), "vfunc_return_value_only") self.assertEqual(vfunc.get_invoker(), invoker) self.assertEqual(invoker, info.find_method("vfunc_return_value_only")) self.assertEqual(vfunc.get_flags(), 0) self.assertEqual(vfunc.get_offset(), 0xFFFF) # unknown offset self.assertEqual(vfunc.get_signal(), None) def test_callable_can_throw_gerror(self): info = repo.find_by_name("GIMarshallingTests", "Object") invoker = find_child_info(info, "get_methods", "vfunc_meth_with_error") vfunc = find_child_info(info, "get_vfuncs", "vfunc_meth_with_err") self.assertTrue(invoker.can_throw_gerror()) self.assertTrue(vfunc.can_throw_gerror()) # Test that args do not include the GError** self.assertEqual(len(invoker.get_arguments()), 1) self.assertEqual(len(vfunc.get_arguments()), 1) # Sanity check method that does not throw. invoker_no_throws = find_child_info(info, "get_methods", "method_int8_in") self.assertFalse(invoker_no_throws.can_throw_gerror()) def test_enums(self): self.assertTrue(hasattr(GIRepository, "Direction")) self.assertTrue(hasattr(GIRepository, "Transfer")) self.assertTrue(hasattr(GIRepository, "ArrayType")) self.assertTrue(hasattr(GIRepository, "ScopeType")) self.assertTrue(hasattr(GIRepository, "VFuncInfoFlags")) self.assertTrue(hasattr(GIRepository, "FieldInfoFlags")) self.assertTrue(hasattr(GIRepository, "FunctionInfoFlags")) self.assertTrue(hasattr(GIRepository, "TypeTag")) def test_introspected_argument_info(self): self.assertTrue( isinstance(IntrospectedRepository.Argument.__info__, GIRepository.UnionInfo) ) arg = IntrospectedRepository.Argument() self.assertTrue(isinstance(arg.__info__, GIRepository.UnionInfo)) old_info = IntrospectedRepository.Argument.__info__ IntrospectedRepository.Argument.__info__ = "not an info" self.assertRaises(TypeError, IntrospectedRepository.Argument) IntrospectedRepository.Argument.__info__ = old_info ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_resulttuple.py0000664000000000000000000000564715074673150017525 0ustar00rootroot# Copyright (C) 2015 Christoph Reiter # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import unittest import pickle import gi from gi.repository import GIMarshallingTests from gi.repository import Regress ResultTuple = gi._gi.ResultTuple class TestResultTuple(unittest.TestCase): def test_base(self): self.assertTrue(issubclass(ResultTuple, tuple)) def test_create(self): names = [None, "foo", None, "bar"] for i in range(10): new = ResultTuple._new_type(names) self.assertTrue(issubclass(new, ResultTuple)) def test_repr_dir(self): new = ResultTuple._new_type([None, "foo", None, "bar"]) inst = new([1, 2, 3, "a"]) self.assertEqual(repr(inst), "(1, foo=2, 3, bar='a')") self.assertTrue("foo" in dir(inst)) def test_repr_dir_empty(self): new = ResultTuple._new_type([]) inst = new() self.assertEqual(repr(inst), "()") dir(inst) def test_getatttr(self): new = ResultTuple._new_type([None, "foo", None, "bar"]) inst = new([1, 2, 3, "a"]) self.assertTrue(hasattr(inst, "foo")) self.assertEqual(inst.foo, inst[1]) self.assertRaises(AttributeError, getattr, inst, "nope") def test_pickle(self): new = ResultTuple._new_type([None, "foo", None, "bar"]) inst = new([1, 2, 3, "a"]) inst2 = pickle.loads(pickle.dumps(inst)) self.assertEqual(inst2, inst) self.assertTrue(isinstance(inst2, tuple)) self.assertFalse(isinstance(inst2, new)) def test_gi(self): res = GIMarshallingTests.init_function([]) self.assertEqual(repr(res), "(True, argv=[])") res = GIMarshallingTests.array_return_etc(5, 9) self.assertEqual(repr(res), "([5, 0, 1, 9], sum=14)") res = GIMarshallingTests.array_out_etc(-5, 9) self.assertEqual(repr(res), "(ints=[-5, 0, 1, 9], sum=4)") def cb(): return 1, 2 res = GIMarshallingTests.callback_multiple_out_parameters(cb) self.assertEqual(repr(res), "(a=1.0, b=2.0)") def test_regress(self): res = Regress.TestObj().skip_return_val(50, 42.0, 60, 2, 3) self.assertEqual(repr(res), "(out_b=51, inout_d=61, out_sum=32)") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_signal.py0000664000000000000000000015265115074673150016410 0ustar00rootrootimport gc import unittest import sys import weakref import threading import time from gi.repository import GObject, GLib, Regress, Gio from gi import _signalhelper as signalhelper from gi.module import repository as repo import testhelper from .helper import capture_glib_warnings, capture_gi_deprecation_warnings class C(GObject.GObject): __gsignals__ = { "my_signal": (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_INT,)) } def do_my_signal(self, arg): self.arg = arg class D(C): def do_my_signal(self, arg2): self.arg2 = arg2 C.do_my_signal(self, arg2) class TestSignalCreation(unittest.TestCase): # Bug 540376. def test_illegals(self): self.assertRaises( TypeError, lambda: GObject.signal_new("test", None, 0, None, (GObject.TYPE_LONG,)), ) class TestChaining(unittest.TestCase): def setUp(self): self.inst = C() self.inst.connect("my_signal", self.my_signal_handler_cb, 1, 2, 3) def my_signal_handler_cb(self, *args): assert len(args) == 5 assert isinstance(args[0], C) assert args[0] == self.inst assert isinstance(args[1], int) assert args[1] == 42 assert args[2:] == (1, 2, 3) def test_chaining(self): self.inst.emit("my_signal", 42) assert self.inst.arg == 42 def test_chaining2(self): inst2 = D() inst2.emit("my_signal", 44) assert inst2.arg == 44 assert inst2.arg2 == 44 # This is for bug 153718 class TestGSignalsError(unittest.TestCase): def test_invalid_type(self, *args): def foo(): class Foo(GObject.GObject): __gsignals__ = None self.assertRaises(TypeError, foo) gc.collect() def test_invalid_name(self, *args): def foo(): class Foo(GObject.GObject): __gsignals__ = {"not-exists": "override"} with capture_glib_warnings(allow_warnings=True): self.assertRaises(TypeError, foo) gc.collect() class TestGPropertyError(unittest.TestCase): def test_invalid_type(self, *args): def foo(): class Foo(GObject.GObject): __gproperties__ = None self.assertRaises(TypeError, foo) gc.collect() def test_invalid_name(self, *args): def foo(): class Foo(GObject.GObject): __gproperties__ = {None: None} self.assertRaises(TypeError, foo) gc.collect() class TestList(unittest.TestCase): def test_list_names(self): self.assertEqual(GObject.signal_list_names(C), ("my-signal",)) def my_accumulator(ihint, return_accu, handler_return, user_data): """An accumulator that stops emission when the sum of handler returned values reaches 3. """ assert user_data == "accum data" if return_accu >= 3: return False, return_accu return True, return_accu + handler_return class Foo(GObject.GObject): my_acc_signal = GObject.Signal( return_type=GObject.TYPE_INT, flags=GObject.SignalFlags.RUN_LAST, accumulator=my_accumulator, accu_data="accum data", ) my_other_acc_signal = GObject.Signal( return_type=GObject.TYPE_BOOLEAN, flags=GObject.SignalFlags.RUN_LAST, accumulator=GObject.signal_accumulator_true_handled, ) my_acc_first_wins = GObject.Signal( return_type=GObject.TYPE_BOOLEAN, flags=GObject.SignalFlags.RUN_LAST, accumulator=GObject.signal_accumulator_first_wins, ) class TestAccumulator(unittest.TestCase): def test_accumulator(self): inst = Foo() inst.my_acc_signal.connect(lambda obj: 1) inst.my_acc_signal.connect(lambda obj: 2) # the value returned in the following handler will not be # considered, because at this point the accumulator already # reached its limit. inst.my_acc_signal.connect(lambda obj: 3) retval = inst.my_acc_signal.emit() self.assertEqual(retval, 3) def test_accumulator_true_handled(self): inst = Foo() inst.my_other_acc_signal.connect(self._true_handler1) inst.my_other_acc_signal.connect(self._true_handler2) # the following handler will not be called because handler2 # returns True, so it should stop the emission. inst.my_other_acc_signal.connect(self._true_handler3) self.__true_val = None inst.my_other_acc_signal.emit() self.assertEqual(self.__true_val, 2) def test_accumulator_first_wins(self): # First signal hit will always win inst = Foo() inst.my_acc_first_wins.connect(self._true_handler3) inst.my_acc_first_wins.connect(self._true_handler1) inst.my_acc_first_wins.connect(self._true_handler2) self.__true_val = None inst.my_acc_first_wins.emit() self.assertEqual(self.__true_val, 3) def _true_handler1(self, obj): self.__true_val = 1 return False def _true_handler2(self, obj): self.__true_val = 2 return True def _true_handler3(self, obj): self.__true_val = 3 return False class E(GObject.GObject): __gsignals__ = {"signal": (GObject.SignalFlags.RUN_FIRST, None, ())} # Property used to test detailed signal prop = GObject.Property(type=int, default=0) def __init__(self): GObject.GObject.__init__(self) self.status = 0 def do_signal(self): assert self.status == 0 self.status = 1 class F(GObject.GObject): __gsignals__ = {"signal": (GObject.SignalFlags.RUN_FIRST, None, ())} def __init__(self): GObject.GObject.__init__(self) self.status = 0 def do_signal(self): self.status += 1 class TestEmissionHook(unittest.TestCase): def test_add(self): self.hook = True e = E() e.connect("signal", self._callback) GObject.add_emission_hook(E, "signal", self._emission_hook) e.emit("signal") self.assertEqual(e.status, 3) def test_remove(self): self.hook = False e = E() e.connect("signal", self._callback) hook_id = GObject.add_emission_hook(E, "signal", self._emission_hook) GObject.remove_emission_hook(E, "signal", hook_id) e.emit("signal") self.assertEqual(e.status, 3) def _emission_hook(self, e): self.assertEqual(e.status, 1) e.status = 2 def _callback(self, e): if self.hook: self.assertEqual(e.status, 2) else: self.assertEqual(e.status, 1) e.status = 3 def test_callback_return_false(self): self.hook = False obj = F() def _emission_hook(obj): obj.status += 1 return False GObject.add_emission_hook(obj, "signal", _emission_hook) obj.emit("signal") obj.emit("signal") self.assertEqual(obj.status, 3) def test_callback_return_true(self): self.hook = False obj = F() def _emission_hook(obj): obj.status += 1 return True hook_id = GObject.add_emission_hook(obj, "signal", _emission_hook) obj.emit("signal") obj.emit("signal") GObject.remove_emission_hook(obj, "signal", hook_id) self.assertEqual(obj.status, 4) def test_callback_return_true_but_remove(self): self.hook = False obj = F() def _emission_hook(obj): obj.status += 1 return True hook_id = GObject.add_emission_hook(obj, "signal", _emission_hook) obj.emit("signal") GObject.remove_emission_hook(obj, "signal", hook_id) obj.emit("signal") self.assertEqual(obj.status, 3) class TestMatching(unittest.TestCase): class Object(GObject.Object): status = 0 prop = GObject.Property(type=int, default=0) @GObject.Signal() def my_signal(self): pass @unittest.expectedFailure # https://bugzilla.gnome.org/show_bug.cgi?id=692918 def test_signal_handler_block_matching(self): def dummy(*args): """Hack to work around:""" def foo(obj): obj.status += 1 obj = self.Object() handler_id = GObject.signal_connect_closure(obj, "my-signal", foo, after=False) handler_id self.assertEqual(obj.status, 0) obj.emit("my-signal") self.assertEqual(obj.status, 1) # Blocking by match criteria disables the foo callback signal_id, detail = GObject.signal_parse_name("my-signal", obj, True) count = GObject.signal_handlers_block_matched( obj, GObject.SignalMatchType.ID | GObject.SignalMatchType.CLOSURE, signal_id=signal_id, detail=detail, closure=foo, func=dummy, data=dummy, ) self.assertEqual(count, 1) obj.emit("my-signal") self.assertEqual(obj.status, 1) # Unblocking by the same match criteria allows callback to work again count = GObject.signal_handlers_unblock_matched( obj, GObject.SignalMatchType.ID | GObject.SignalMatchType.CLOSURE, signal_id=signal_id, detail=detail, closure=foo, func=dummy, data=dummy, ) self.assertEqual(count, 1) obj.emit("my-signal") self.assertEqual(obj.status, 2) # Disconnecting by match criteria completely removes the handler count = GObject.signal_handlers_disconnect_matched( obj, GObject.SignalMatchType.ID | GObject.SignalMatchType.CLOSURE, signal_id=signal_id, detail=detail, closure=foo, func=dummy, data=dummy, ) self.assertEqual(count, 1) obj.emit("my-signal") self.assertEqual(obj.status, 2) def test_signal_handler_find(self): def foo(obj): obj.status += 1 obj = self.Object() handler_id = GObject.signal_connect_closure(obj, "my-signal", foo, after=False) signal_id, detail = GObject.signal_parse_name("my-signal", obj, True) found_id = GObject.signal_handler_find( obj, GObject.SignalMatchType.ID, signal_id=signal_id, detail=detail, closure=None, func=0, data=0, ) self.assertEqual(handler_id, found_id) class TestClosures(unittest.TestCase): def setUp(self): self.count = 0 self.emission_stopped = False self.emission_error = False self.handler_pending = False def _callback_handler_pending(self, e): signal_id, detail = GObject.signal_parse_name("signal", e, True) self.handler_pending = GObject.signal_has_handler_pending( e, signal_id, detail, may_be_blocked=False ) def _callback(self, e): self.count += 1 def _callback_stop_emission(self, obj, prop, stop_it): if stop_it: obj.stop_emission_by_name("notify::prop") self.emission_stopped = True else: self.count += 1 def _callback_invalid_stop_emission_name(self, obj, prop): with capture_glib_warnings(allow_warnings=True, allow_criticals=True) as warn: obj.stop_emission_by_name("notasignal::baddetail") self.emission_error = True self.assertTrue(warn) def test_disconnect_by_func(self): e = E() e.connect("signal", self._callback) e.disconnect_by_func(self._callback) e.emit("signal") self.assertEqual(self.count, 0) def test_disconnect(self): e = E() handler_id = e.connect("signal", self._callback) self.assertTrue(e.handler_is_connected(handler_id)) e.disconnect(handler_id) e.emit("signal") self.assertEqual(self.count, 0) self.assertFalse(e.handler_is_connected(handler_id)) def test_stop_emission_by_name(self): e = E() # Sandwich a callback that stops emission in between a callback that increments e.connect("notify::prop", self._callback_stop_emission, False) e.connect("notify::prop", self._callback_stop_emission, True) e.connect("notify::prop", self._callback_stop_emission, False) e.set_property("prop", 1234) self.assertEqual(e.get_property("prop"), 1234) self.assertEqual(self.count, 1) self.assertTrue(self.emission_stopped) def test_stop_emission_by_name_error(self): e = E() e.connect("notify::prop", self._callback_invalid_stop_emission_name) with capture_glib_warnings(): e.set_property("prop", 1234) self.assertTrue(self.emission_error) def test_handler_block(self): e = E() e.connect("signal", self._callback) e.handler_block_by_func(self._callback) e.emit("signal") self.assertEqual(self.count, 0) def test_handler_unblock(self): e = E() handler_id = e.connect("signal", self._callback) e.handler_block(handler_id) e.handler_unblock_by_func(self._callback) e.emit("signal") self.assertEqual(self.count, 1) def test_handler_block_method(self): # Filed as #375589 class A: def __init__(self): self.a = 0 def callback(self, o): self.a = 1 o.handler_block_by_func(self.callback) inst = A() e = E() e.connect("signal", inst.callback) e.emit("signal") self.assertEqual(inst.a, 1) gc.collect() def test_gstring(self): class C(GObject.GObject): __gsignals__ = { "my_signal": ( GObject.SignalFlags.RUN_LAST, GObject.TYPE_GSTRING, (GObject.TYPE_GSTRING,), ) } def __init__(self, test): GObject.GObject.__init__(self) self.test = test def do_my_signal(self, data): self.data = data self.test.assertEqual(len(data), 3) return "".join([data[2], data[1], data[0]]) c = C(self) data = c.emit("my_signal", "\01\00\02") self.assertEqual(data, "\02\00\01") def test_handler_pending(self): obj = F() obj.connect("signal", self._callback_handler_pending) obj.connect("signal", self._callback) self.assertEqual(self.count, 0) self.assertEqual(self.handler_pending, False) obj.emit("signal") self.assertEqual(self.count, 1) self.assertEqual(self.handler_pending, True) def test_signal_handlers_destroy(self): obj = F() obj.connect("signal", self._callback) obj.connect("signal", self._callback) obj.connect("signal", self._callback) obj.emit("signal") self.assertEqual(self.count, 3) # count should remain at 3 after all handlers are destroyed GObject.signal_handlers_destroy(obj) obj.emit("signal") self.assertEqual(self.count, 3) class SigPropClass(GObject.GObject): __gsignals__ = { "my_signal": (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_INT,)) } __gproperties__ = { "foo": ( str, None, None, "", GObject.ParamFlags.WRITABLE | GObject.ParamFlags.CONSTRUCT, ), } signal_emission_failed = False def do_my_signal(self, arg): self.arg = arg def do_set_property(self, pspec, value): if pspec.name == "foo": self._foo = value else: raise AttributeError(f"unknown property {pspec.name}") try: self.emit("my-signal", 1) except TypeError: self.signal_emission_failed = True class TestSigProp(unittest.TestCase): def test_emit_in_property_setter(self): obj = SigPropClass() self.assertFalse(obj.signal_emission_failed) class CM(GObject.GObject): __gsignals__ = { "test1": (GObject.SignalFlags.RUN_FIRST, None, ()), "test2": (GObject.SignalFlags.RUN_LAST, None, (str,)), "test3": (GObject.SignalFlags.RUN_LAST, int, (GObject.TYPE_DOUBLE,)), "test4": ( GObject.SignalFlags.RUN_FIRST, None, ( bool, int, GObject.TYPE_FLOAT, GObject.TYPE_DOUBLE, int, GObject.TYPE_UINT, GObject.TYPE_ULONG, ), ), "test_float": ( GObject.SignalFlags.RUN_LAST, GObject.TYPE_FLOAT, (GObject.TYPE_FLOAT,), ), "test_double": ( GObject.SignalFlags.RUN_LAST, GObject.TYPE_DOUBLE, (GObject.TYPE_DOUBLE,), ), "test_int64": ( GObject.SignalFlags.RUN_LAST, GObject.TYPE_INT64, (GObject.TYPE_INT64,), ), "test_string": (GObject.SignalFlags.RUN_LAST, str, (str,)), "test_object": (GObject.SignalFlags.RUN_LAST, object, (object,)), "test_paramspec": (GObject.SignalFlags.RUN_LAST, GObject.ParamSpec, ()), "test_paramspec_in": ( GObject.SignalFlags.RUN_LAST, GObject.ParamSpec, (GObject.ParamSpec,), ), "test_gvalue": (GObject.SignalFlags.RUN_LAST, GObject.Value, (GObject.Value,)), "test_gvalue_ret": ( GObject.SignalFlags.RUN_LAST, GObject.Value, (GObject.TYPE_GTYPE,), ), } testprop = GObject.Property(type=int) class _TestCMarshaller: def setUp(self): self.obj = CM() testhelper.connectcallbacks(self.obj) def test_test1(self): self.obj.emit("test1") def test_test2(self): self.obj.emit("test2", "string") def test_test3(self): rv = self.obj.emit("test3", 42.0) self.assertEqual(rv, 20) def test_test4(self): self.obj.emit("test4", True, 10, 3.14, 1.78, 20, 30, 31) def test_float(self): rv = self.obj.emit("test-float", 1.234) self.assertTrue(rv >= 1.233999 and rv <= 1.2400001, rv) def test_double(self): rv = self.obj.emit("test-double", 1.234) self.assertEqual(rv, 1.234) def test_int64(self): rv = self.obj.emit("test-int64", 102030405) self.assertEqual(rv, 102030405) rv = self.obj.emit("test-int64", GLib.MAXINT64) self.assertEqual(rv, GLib.MAXINT64 - 1) rv = self.obj.emit("test-int64", GLib.MININT64) self.assertEqual(rv, GLib.MININT64) def test_string(self): rv = self.obj.emit("test-string", "str") self.assertEqual(rv, "str") def test_object(self): rv = self.obj.emit("test-object", self) self.assertEqual(rv, self) def test_paramspec(self): rv = self.obj.emit("test-paramspec") self.assertEqual(rv.name, "test-param") self.assertEqual(rv.nick, "test") @unittest.skipUnless( hasattr(GObject, "param_spec_boolean"), "too old gobject-introspection" ) def test_paramspec_in(self): rv = GObject.param_spec_boolean( "mybool", "test-bool", "do something", True, GObject.ParamFlags.READABLE ) rv2 = self.obj.emit("test-paramspec-in", rv) self.assertEqual(type(rv), type(rv2)) self.assertEqual(rv2.name, "mybool") self.assertEqual(rv2.nick, "test-bool") def test_C_paramspec(self): self.notify_called = False def cb_notify(obj, prop): self.notify_called = True self.assertEqual(obj, self.obj) self.assertEqual(prop.name, "testprop") self.obj.connect("notify", cb_notify) self.obj.set_property("testprop", 42) self.assertTrue(self.notify_called) def test_gvalue(self): # implicit int rv = self.obj.emit("test-gvalue", 42) self.assertEqual(rv, 42) # explicit float v = GObject.Value(GObject.TYPE_FLOAT, 1.234) rv = self.obj.emit("test-gvalue", v) self.assertAlmostEqual(rv, 1.234, places=4) # implicit float rv = self.obj.emit("test-gvalue", 1.234) self.assertAlmostEqual(rv, 1.234, places=4) # explicit int64 v = GObject.Value(GObject.TYPE_INT64, GLib.MAXINT64) rv = self.obj.emit("test-gvalue", v) self.assertEqual(rv, GLib.MAXINT64) # explicit uint64 v = GObject.Value(GObject.TYPE_UINT64, GLib.MAXUINT64) rv = self.obj.emit("test-gvalue", v) self.assertEqual(rv, GLib.MAXUINT64) @unittest.expectedFailure # https://bugzilla.gnome.org/show_bug.cgi?id=705291 def test_gvalue_implicit_int64(self): # implicit int64 rv = self.obj.emit("test-gvalue", GLib.MAXINT64) self.assertEqual(rv, GLib.MAXINT64) # implicit uint64 rv = self.obj.emit("test-gvalue", GLib.MAXUINT64) self.assertEqual(rv, GLib.MAXUINT64) def test_gvalue_ret(self): self.assertEqual( self.obj.emit("test-gvalue-ret", GObject.TYPE_INT), GLib.MAXINT ) self.assertEqual( self.obj.emit("test-gvalue-ret", GObject.TYPE_UINT), GLib.MAXUINT ) self.assertEqual( self.obj.emit("test-gvalue-ret", GObject.TYPE_INT64), GLib.MAXINT64 ) self.assertEqual( self.obj.emit("test-gvalue-ret", GObject.TYPE_UINT64), GLib.MAXUINT64 ) self.assertEqual(self.obj.emit("test-gvalue-ret", GObject.TYPE_STRING), "hello") class TestCMarshaller(_TestCMarshaller, unittest.TestCase): pass # Test for 374653 class TestPyGValue(unittest.TestCase): def test_none_null_boxed_conversion(self): class C(GObject.GObject): __gsignals__ = { "my_boxed_signal": (GObject.SignalFlags.RUN_LAST, GObject.TYPE_STRV, ()) } obj = C() obj.connect("my-boxed-signal", lambda obj: None) sys.last_type = None obj.emit("my-boxed-signal") assert not sys.last_type class TestSignalDecorator(unittest.TestCase): class Decorated(GObject.GObject): value = 0 @GObject.Signal def pushed(self): """This will push.""" self.value += 1 @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST) def pulled(self): self.value -= 1 @GObject.Signal(flags=GObject.SignalFlags.DETAILED) def detailed(self): self.value -= 1 stomped = GObject.Signal("stomped", arg_types=(int,), doc="This will stomp.") unnamed = GObject.Signal() class DecoratedOverride(GObject.GObject): overridden_closure_called = False notify_called = False value = GObject.Property(type=int, default=0) @GObject.SignalOverride def notify(self, *args, **kargs): self.overridden_closure_called = True def on_notify(self, obj, prop): self.notify_called = True def setUp(self): self.unnamedCalled = False def onUnnamed(self, obj): self.unnamedCalled = True def test_disconnect(self): decorated = self.Decorated() id_ = decorated.pushed.connect(lambda *args: None) decorated.pushed.disconnect(id_) def test_signal_repr(self): decorated = self.Decorated() assert repr(decorated.pushed) == 'BoundSignal("pushed")' def test_signal_call(self): decorated = self.Decorated() assert decorated.value == 0 decorated.pushed() assert decorated.value == 1 def test_connect_detailed(self): decorated = self.Decorated() id_ = decorated.detailed.connect_detailed(lambda *args: None, "foo") decorated.pushed.disconnect(id_) def test_get_signal_args(self): self.assertEqual( self.Decorated.pushed.get_signal_args(), (GObject.SignalFlags.RUN_FIRST, None, (), None, None), ) self.assertEqual( self.Decorated.pulled.get_signal_args(), (GObject.SignalFlags.RUN_LAST, None, (), None, None), ) self.assertEqual( self.Decorated.stomped.get_signal_args(), (GObject.SignalFlags.RUN_FIRST, None, (int,), None, None), ) def test_closures_called(self): decorated = self.Decorated() self.assertEqual(decorated.value, 0) decorated.pushed.emit() self.assertEqual(decorated.value, 1) decorated.pulled.emit() self.assertEqual(decorated.value, 0) def test_signal_copy(self): blah = self.Decorated.stomped.copy("blah") self.assertEqual(str(blah), blah) self.assertEqual(blah.func, self.Decorated.stomped.func) self.assertEqual(blah.flags, self.Decorated.stomped.flags) self.assertEqual(blah.return_type, self.Decorated.stomped.return_type) self.assertEqual(blah.arg_types, self.Decorated.stomped.arg_types) self.assertEqual(blah.__doc__, self.Decorated.stomped.__doc__) def test_doc_string(self): # Test the two techniques for setting doc strings on the signals # class variables, through the "doc" keyword or as the getter doc string. self.assertEqual(self.Decorated.stomped.__doc__, "This will stomp.") self.assertEqual(self.Decorated.pushed.__doc__, "This will push.") def test_unnamed_signal_gets_named(self): self.assertEqual(str(self.Decorated.unnamed), "unnamed") def test_unnamed_signal_gets_called(self): obj = self.Decorated() obj.connect("unnamed", self.onUnnamed) self.assertEqual(self.unnamedCalled, False) obj.emit("unnamed") self.assertEqual(self.unnamedCalled, True) def test_overridden_signal(self): # Test that the pushed signal is called in with super and the override # which should both increment the "value" to 3 obj = self.DecoratedOverride() obj.connect("notify", obj.on_notify) self.assertEqual(obj.value, 0) obj.value = 1 self.assertEqual(obj.value, 1) self.assertTrue(obj.overridden_closure_called) self.assertTrue(obj.notify_called) class TestSignalConnectors(unittest.TestCase): class CustomButton(GObject.GObject): on_notify_called = False value = GObject.Property(type=int) @GObject.Signal(arg_types=(int,)) def clicked(self, value): self.value = value def setUp(self): self.obj = None self.value = None def on_clicked(self, obj, value): self.obj = obj self.value = value def test_signal_notify(self): def on_notify(obj, param): obj.on_notify_called = True obj = self.CustomButton() obj.connect("notify", on_notify) self.assertFalse(obj.on_notify_called) obj.notify("value") self.assertTrue(obj.on_notify_called) def test_signal_emit(self): # standard callback connection with different forms of emit. obj = self.CustomButton() obj.connect("clicked", self.on_clicked) # vanilla obj.emit("clicked", 1) self.assertEqual(obj.value, 1) self.assertEqual(obj, self.obj) self.assertEqual(self.value, 1) # using class signal as param self.obj = None self.value = None obj.emit(self.CustomButton.clicked, 1) self.assertEqual(obj, self.obj) self.assertEqual(self.value, 1) # using bound signal as param self.obj = None self.value = None obj.emit(obj.clicked, 1) self.assertEqual(obj, self.obj) self.assertEqual(self.value, 1) # using bound signal with emit self.obj = None self.value = None obj.clicked.emit(1) self.assertEqual(obj, self.obj) self.assertEqual(self.value, 1) def test_signal_class_connect(self): obj = self.CustomButton() obj.connect(self.CustomButton.clicked, self.on_clicked) obj.emit("clicked", 2) self.assertEqual(obj, self.obj) self.assertEqual(self.value, 2) def test_signal_bound_connect(self): obj = self.CustomButton() obj.clicked.connect(self.on_clicked) obj.emit("clicked", 3) self.assertEqual(obj, self.obj) self.assertEqual(self.value, 3) class _ConnectDataTestBase: # Notes: # - self.Object is overridden in sub-classes. # - Numeric suffixes indicate the number of user data args passed in. Object = None def run_connect_test(self, emit_args, user_data, flags=0): obj = self.Object() callback_args = [] def callback(*args): callback_args.append(args) return 0 obj.connect_data( "sig-with-int64-prop", callback, connect_flags=flags, *user_data ) obj.emit("sig-with-int64-prop", *emit_args) self.assertEqual(len(callback_args), 1) return callback_args[0] def test_0(self): obj, value = self.run_connect_test([GLib.MAXINT64], user_data=[]) self.assertIsInstance(obj, self.Object) self.assertEqual(value, GLib.MAXINT64) def test_1(self): obj, value, data = self.run_connect_test([GLib.MAXINT64], user_data=["mydata"]) self.assertIsInstance(obj, self.Object) self.assertEqual(value, GLib.MAXINT64) self.assertEqual(data, "mydata") def test_after_0(self): obj, value = self.run_connect_test( [GLib.MAXINT64], user_data=[], flags=GObject.ConnectFlags.AFTER ) self.assertIsInstance(obj, self.Object) self.assertEqual(value, GLib.MAXINT64) def test_after_1(self): obj, value, data = self.run_connect_test( [GLib.MAXINT64], user_data=["mydata"], flags=GObject.ConnectFlags.AFTER ) self.assertIsInstance(obj, self.Object) self.assertEqual(value, GLib.MAXINT64) self.assertEqual(data, "mydata") def test_swaped_0(self): # Swapped only works with a single user data argument. with self.assertRaises(ValueError): self.run_connect_test( [GLib.MAXINT64], user_data=[], flags=GObject.ConnectFlags.SWAPPED ) def test_swaped_1(self): # Notice obj and data are reversed in the return. data, value, obj = self.run_connect_test( [GLib.MAXINT64], user_data=["mydata"], flags=GObject.ConnectFlags.SWAPPED ) self.assertIsInstance(obj, self.Object) self.assertEqual(value, GLib.MAXINT64) self.assertEqual(data, "mydata") def test_swaped_2(self): # Swapped only works with a single user data argument. with self.assertRaises(ValueError): self.run_connect_test( [GLib.MAXINT64], user_data=[1, 2], flags=GObject.ConnectFlags.SWAPPED ) def test_after_and_swapped_0(self): # Swapped only works with a single user data argument. with self.assertRaises(ValueError): self.run_connect_test( [GLib.MAXINT64], user_data=[], flags=GObject.ConnectFlags.AFTER | GObject.ConnectFlags.SWAPPED, ) def test_after_and_swapped_1(self): # Notice obj and data are reversed in the return. data, value, obj = self.run_connect_test( [GLib.MAXINT64], user_data=["mydata"], flags=GObject.ConnectFlags.AFTER | GObject.ConnectFlags.SWAPPED, ) self.assertIsInstance(obj, self.Object) self.assertEqual(value, GLib.MAXINT64) self.assertEqual(data, "mydata") def test_after_and_swapped_2(self): # Swapped only works with a single user data argument. with self.assertRaises(ValueError): self.run_connect_test( [GLib.MAXINT64], user_data=[], flags=GObject.ConnectFlags.AFTER | GObject.ConnectFlags.SWAPPED, ) class TestConnectDataNonIntrospected(unittest.TestCase, _ConnectDataTestBase): # This tests connect_data with non-introspected signals # (created in Python in this case). class Object(GObject.Object): test = GObject.Signal() sig_with_int64_prop = GObject.Signal( return_type=GObject.TYPE_INT64, arg_types=[GObject.TYPE_INT64], flags=GObject.SignalFlags.RUN_LAST, ) class TestConnectDataIntrospected(unittest.TestCase, _ConnectDataTestBase): # This tests connect_data with introspected signals brought in from Regress. Object = Regress.TestObj class TestInstallSignals(unittest.TestCase): # These tests only test how signalhelper.install_signals works # with the __gsignals__ dict and therefore does not need to use # GObject as a base class because that would automatically call # install_signals within the meta-class. class Base: __gsignals__ = {"test": (0, None, ())} class Sub1(Base): pass class Sub2(Base): @GObject.Signal def sub2test(self): pass def setUp(self): self.assertEqual(len(self.Base.__gsignals__), 1) signalhelper.install_signals(self.Base) self.assertEqual(len(self.Base.__gsignals__), 1) def test_subclass_gets_empty_gsignals_dict(self): # Installing signals will add the __gsignals__ dict to a class # if it doesn't already exists. self.assertFalse("__gsignals__" in self.Sub1.__dict__) signalhelper.install_signals(self.Sub1) self.assertTrue("__gsignals__" in self.Sub1.__dict__) # Sub1 should only contain an empty signals dict, this tests: # https://bugzilla.gnome.org/show_bug.cgi?id=686496 self.assertEqual(self.Sub1.__dict__["__gsignals__"], {}) def test_subclass_with_decorator_gets_gsignals_dict(self): self.assertFalse("__gsignals__" in self.Sub2.__dict__) signalhelper.install_signals(self.Sub2) self.assertTrue("__gsignals__" in self.Sub2.__dict__) self.assertEqual(len(self.Base.__gsignals__), 1) self.assertEqual(len(self.Sub2.__gsignals__), 1) self.assertTrue("sub2test" in self.Sub2.__gsignals__) # Make sure the vfunc was added self.assertTrue(hasattr(self.Sub2, "do_sub2test")) class TestPython3Signals(unittest.TestCase): class AnnotatedClass(GObject.GObject): @GObject.Signal def sig1(self, a: int, b: float): pass @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST) def sig2_with_return(self, a: int, b: float) -> str: return "test" def test_annotations(self): self.assertEqual( signalhelper.get_signal_annotations(self.AnnotatedClass.sig1.func), (None, (int, float)), ) self.assertEqual( signalhelper.get_signal_annotations( self.AnnotatedClass.sig2_with_return.func ), (str, (int, float)), ) self.assertEqual( self.AnnotatedClass.sig2_with_return.get_signal_args(), (GObject.SignalFlags.RUN_LAST, str, (int, float), None, None), ) self.assertEqual(self.AnnotatedClass.sig2_with_return.arg_types, (int, float)) self.assertEqual(self.AnnotatedClass.sig2_with_return.return_type, str) def test_emit_return(self): obj = self.AnnotatedClass() self.assertEqual(obj.sig2_with_return.emit(1, 2.0), "test") class TestSignalModuleLevelFunctions(unittest.TestCase): def test_signal_list_ids_with_invalid_type(self): with self.assertRaisesRegex( TypeError, "type must be instantiable or an interface.*" ): GObject.signal_list_ids(GObject.TYPE_INVALID) def test_signal_list_ids(self): with self.assertRaisesRegex( TypeError, "type must be instantiable or an interface.*" ): GObject.signal_list_ids(GObject.TYPE_INT) ids = GObject.signal_list_ids(C) self.assertEqual(len(ids), 1) # Note canonicalized names self.assertEqual(GObject.signal_name(ids[0]), "my-signal") # There is no signal 0 in gobject self.assertEqual(GObject.signal_name(0), None) def test_signal_lookup_with_invalid_type(self): with self.assertRaisesRegex( TypeError, "type must be instantiable or an interface.*" ): GObject.signal_lookup("NOT_A_SIGNAL_NAME", GObject.TYPE_INVALID) def test_signal_lookup(self): ids = GObject.signal_list_ids(C) self.assertEqual(ids[0], GObject.signal_lookup("my_signal", C)) self.assertEqual(ids[0], GObject.signal_lookup("my-signal", C)) with self.assertRaisesRegex( TypeError, "type must be instantiable or an interface.*" ): GObject.signal_lookup("NOT_A_SIGNAL_NAME", GObject.TYPE_INT) # Invalid signal names return 0 instead of raising self.assertEqual(GObject.signal_lookup("NOT_A_SIGNAL_NAME", C), 0) def test_signal_query(self): (my_signal_id,) = GObject.signal_list_ids(C) # Form is: (id, name, gtype, arg_count, return_type, (arg_type1, ...)) my_signal_expected_query_result = [ my_signal_id, "my-signal", C.__gtype__, 1, GObject.TYPE_NONE, (GObject.TYPE_INT,), ] # signal_query(name, type) self.assertEqual( list(GObject.signal_query("my-signal", C)), my_signal_expected_query_result ) # signal_query(signal_id) self.assertEqual( list(GObject.signal_query(my_signal_id)), my_signal_expected_query_result ) # invalid query returns None instead of raising self.assertEqual(GObject.signal_query(0), None) self.assertEqual(GObject.signal_query("NOT_A_SIGNAL", C), None) class TestIntrospectedSignals(unittest.TestCase): def test_object_param_signal(self): obj = Regress.TestObj() def callback(obj, obj_param): self.assertEqual(obj_param.props.int, 3) self.assertGreater(obj_param.__grefcount__, 1) obj.called = True obj.called = False obj.connect("sig-with-obj", callback) obj.emit_sig_with_obj() self.assertTrue(obj.called) def test_connect_after(self): obj = Regress.TestObj() def callback(obj, obj_param): obj.called = True obj.called = False obj.connect_after("sig-with-obj", callback) obj.emit_sig_with_obj() self.assertTrue(obj.called) def test_int64_param_from_py(self): obj = Regress.TestObj() def callback(obj, i): obj.callback_i = i return i obj.callback_i = None obj.connect("sig-with-int64-prop", callback) rv = obj.emit("sig-with-int64-prop", GLib.MAXINT64) self.assertEqual(rv, GLib.MAXINT64) self.assertEqual(obj.callback_i, GLib.MAXINT64) def test_uint64_param_from_py(self): obj = Regress.TestObj() def callback(obj, i): obj.callback_i = i return i obj.callback_i = None obj.connect("sig-with-uint64-prop", callback) rv = obj.emit("sig-with-uint64-prop", GLib.MAXUINT64) self.assertEqual(rv, GLib.MAXUINT64) self.assertEqual(obj.callback_i, GLib.MAXUINT64) def test_int64_param_from_c(self): obj = Regress.TestObj() def callback(obj, i): obj.callback_i = i return i obj.callback_i = None obj.connect("sig-with-int64-prop", callback) obj.emit_sig_with_int64() self.assertEqual(obj.callback_i, GLib.MAXINT64) def test_uint64_param_from_c(self): obj = Regress.TestObj() def callback(obj, i): obj.callback_i = i return i obj.callback_i = None obj.connect("sig-with-uint64-prop", callback) obj.emit_sig_with_uint64() self.assertEqual(obj.callback_i, GLib.MAXUINT64) def test_intarray_ret(self): obj = Regress.TestObj() def callback(obj, i): obj.callback_i = i return [i, i + 1] obj.callback_i = None try: obj.connect("sig-with-intarray-ret", callback) except TypeError as e: # compat with g-i 1.34.x if "unknown signal" in str(e): return raise rv = obj.emit("sig-with-intarray-ret", 42) self.assertEqual(obj.callback_i, 42) self.assertEqual(type(rv), GLib.Array) self.assertEqual(rv.len, 2) @unittest.skip("https://bugzilla.gnome.org/show_bug.cgi?id=669496") def test_array_parm(self): obj = Regress.TestObj() def callback(obj, arr): obj.callback_arr = arr obj.connect("sig-with-array-prop", callback) obj.callback_arr = None self.assertEqual(obj.emit("sig-with-array-prop", [1, 2, GLib.MAXUINT]), None) self.assertEqual(obj.callback_arr, [1, 2, GLib.MAXUINT]) def test_held_struct_ref(self): held_structs = [] def callback(obj, struct): # The struct held by Python will become a copy after this callback exits. struct.some_int = 42 struct.some_int8 = 42 held_structs.append(struct) struct = Regress.TestSimpleBoxedA() obj = Regress.TestObj() self.assertEqual(struct.some_int, 0) self.assertEqual(struct.some_int8, 0) obj.connect("test-with-static-scope-arg", callback) obj.emit("test-with-static-scope-arg", struct) # The held struct will be a copy of the modified struct. self.assertEqual(len(held_structs), 1) held_struct = held_structs[0] self.assertEqual(held_struct.some_int, 42) self.assertEqual(held_struct.some_int8, 42) # Boxed equality checks pointers by default. self.assertNotEqual(struct, held_struct) def test_action(self): obj = Regress.TestAction() other_obj = obj.emit("action") self.assertEqual(other_obj.__grefcount__, 1) other_obj2 = obj.emit("action2") self.assertIsNone(other_obj2) class TestIntrospectedSignalsIssue158(unittest.TestCase): """The test for https://gitlab.gnome.org/GNOME/pygobject/issues/158.""" _obj_sig_names = [ sig.get_name() for sig in repo.find_by_name("Regress", "TestObj").get_signals() ] def __init__(self, *args): unittest.TestCase.__init__(self, *args) self._gc_thread_stop = False def _gc_thread(self): while not self._gc_thread_stop: gc.collect() time.sleep(0.010) def _callback(self, *args): pass def test_run(self): """Manually trigger GC from a different thread periodicaly while the main thread keeps connecting/disconnecting to/from signals. It takes a lot of time to reproduce the issue. It is possible to make it fail reliably by changing the code of pygobject_unwatch_closure slightly from: PyGObjectData *inst_data = data; inst_data->closures = g_slist_remove (inst_data->closures, closure); to PyGObjectData *inst_data = data; GSList *tmp = g_slist_remove (inst_data->closures, closure); g_usleep(G_USEC_PER_SEC/10); inst_data->closures = tmp; """ obj = Regress.TestObj() gc_thread = threading.Thread(target=self._gc_thread) gc_thread.start() for _ in range(8): handlers = [obj.connect(sig, self._callback) for sig in self._obj_sig_names] time.sleep(0.010) while len(handlers) > 0: obj.disconnect(handlers.pop()) self._gc_thread_stop = True gc_thread.join() class _ConnectObjectTestBase: # Notes: # - self.Object is overridden in sub-classes. # - Numeric suffixes indicate the number of user data args passed in. Object = None SwapObject = None def run_connect_test(self, emit_args, user_data, flags=0): obj = self.Object() callback_args = [] swap_obj = self.SwapObject() def callback(*args): callback_args.append(args) return 0 if flags & GObject.ConnectFlags.AFTER: connect_func = obj.connect_object_after else: connect_func = obj.connect_object with capture_gi_deprecation_warnings(): connect_func("sig-with-int64-prop", callback, swap_obj, *user_data) obj.emit("sig-with-int64-prop", *emit_args) self.assertEqual(len(callback_args), 1) return callback_args[0] def test_0(self): obj, value = self.run_connect_test([GLib.MAXINT64], user_data=[]) self.assertIsInstance(obj, self.SwapObject) self.assertEqual(value, GLib.MAXINT64) def test_1(self): obj, value, data = self.run_connect_test([GLib.MAXINT64], user_data=["mydata"]) self.assertIsInstance(obj, self.SwapObject) self.assertEqual(value, GLib.MAXINT64) self.assertEqual(data, "mydata") def test_2(self): obj, value, data1, data2 = self.run_connect_test( [GLib.MAXINT64], user_data=["mydata1", "mydata2"] ) self.assertIsInstance(obj, self.SwapObject) self.assertEqual(value, GLib.MAXINT64) self.assertEqual(data1, "mydata1") self.assertEqual(data2, "mydata2") def test_after_0(self): obj, value = self.run_connect_test( [GLib.MAXINT64], user_data=[], flags=GObject.ConnectFlags.AFTER ) self.assertIsInstance(obj, self.SwapObject) self.assertEqual(value, GLib.MAXINT64) def test_after_1(self): obj, value, data = self.run_connect_test( [GLib.MAXINT64], user_data=["mydata"], flags=GObject.ConnectFlags.AFTER ) self.assertIsInstance(obj, self.SwapObject) self.assertEqual(value, GLib.MAXINT64) self.assertEqual(data, "mydata") def test_after_2(self): obj, value, data1, data2 = self.run_connect_test( [GLib.MAXINT64], user_data=["mydata1", "mydata2"], flags=GObject.ConnectFlags.AFTER, ) self.assertIsInstance(obj, self.SwapObject) self.assertEqual(value, GLib.MAXINT64) self.assertEqual(data1, "mydata1") self.assertEqual(data2, "mydata2") class TestConnectGObjectNonIntrospected(unittest.TestCase, _ConnectObjectTestBase): # This tests connect_object with non-introspected signals # (created in Python in this case). class Object(GObject.Object): test = GObject.Signal() sig_with_int64_prop = GObject.Signal( return_type=GObject.TYPE_INT64, arg_types=[GObject.TYPE_INT64], flags=GObject.SignalFlags.RUN_LAST, ) # Object passed for swapping is GObject based. class SwapObject(GObject.Object): pass class TestConnectGObjectIntrospected(unittest.TestCase, _ConnectObjectTestBase): # This tests connect_object with introspected signals brought in from Regress. Object = Regress.TestObj # Object passed for swapping is GObject based. class SwapObject(GObject.Object): pass class TestConnectPyObjectNonIntrospected(unittest.TestCase, _ConnectObjectTestBase): # This tests connect_object with non-introspected signals # (created in Python in this case). class Object(GObject.Object): test = GObject.Signal() sig_with_int64_prop = GObject.Signal( return_type=GObject.TYPE_INT64, arg_types=[GObject.TYPE_INT64], flags=GObject.SignalFlags.RUN_LAST, ) # Object passed for swapping is pure Python SwapObject = object class TestConnectPyObjectIntrospected(unittest.TestCase, _ConnectObjectTestBase): # This tests connect_object with introspected signals brought in from Regress. Object = Regress.TestObj # Object passed for swapping is pure Python SwapObject = object class _RefCountTestBase: # NOTE: ref counts are always one more than expected because the getrefcount() # function adds a ref for the input argument. # Sub-classes set this Object = None class PyData: pass @unittest.skipUnless(hasattr(sys, "getrefcount"), "no sys.getrefcount") def test_callback_ref_count_del(self): def callback(obj, value): return value // 2 callback_ref = weakref.ref(callback) self.assertEqual( sys.getrefcount(callback), 2 if sys.version_info < (3, 14) else 1 ) obj = self.Object() obj.connect("sig-with-int64-prop", callback) self.assertEqual( sys.getrefcount(callback), 3 if sys.version_info < (3, 14) else 2 ) del callback self.assertEqual(sys.getrefcount(callback_ref()), 2) res = obj.emit("sig-with-int64-prop", 42) self.assertEqual(res, 21) self.assertEqual( sys.getrefcount(callback_ref), 2 if sys.version_info < (3, 14) else 1 ) del obj self.assertIsNone(callback_ref()) @unittest.skipUnless(hasattr(sys, "getrefcount"), "no sys.getrefcount") def test_callback_ref_count_disconnect(self): def callback(obj, value): return value // 2 callback_ref = weakref.ref(callback) self.assertEqual( sys.getrefcount(callback), 2 if sys.version_info < (3, 14) else 1 ) obj = self.Object() handler_id = obj.connect("sig-with-int64-prop", callback) self.assertEqual( sys.getrefcount(callback), 3 if sys.version_info < (3, 14) else 2 ) del callback self.assertEqual(sys.getrefcount(callback_ref()), 2) res = obj.emit("sig-with-int64-prop", 42) self.assertEqual(res, 21) self.assertEqual( sys.getrefcount(callback_ref), 2 if sys.version_info < (3, 14) else 1 ) obj.disconnect(handler_id) self.assertIsNone(callback_ref()) @unittest.skipUnless(hasattr(sys, "getrefcount"), "no sys.getrefcount") def test_callback_ref_count_disconnect_by_func(self): def callback(obj, value): return value // 2 callback_ref = weakref.ref(callback) self.assertEqual( sys.getrefcount(callback), 2 if sys.version_info < (3, 14) else 1 ) obj = self.Object() obj.connect("sig-with-int64-prop", callback) self.assertEqual( sys.getrefcount(callback), 3 if sys.version_info < (3, 14) else 2 ) del callback self.assertEqual(sys.getrefcount(callback_ref()), 2) res = obj.emit("sig-with-int64-prop", 42) self.assertEqual(res, 21) self.assertEqual( sys.getrefcount(callback_ref), 2 if sys.version_info < (3, 14) else 1 ) obj.disconnect_by_func(callback_ref()) self.assertIsNone(callback_ref()) @unittest.skipUnless(hasattr(sys, "getrefcount"), "no sys.getrefcount") def test_user_data_ref_count(self): def callback(obj, value, data): return value // 2 data = self.PyData() data_ref = weakref.ref(data) self.assertEqual(sys.getrefcount(data), 2 if sys.version_info < (3, 14) else 1) obj = self.Object() obj.connect("sig-with-int64-prop", callback, data) self.assertEqual(sys.getrefcount(data), 3 if sys.version_info < (3, 14) else 2) del data self.assertEqual(sys.getrefcount(data_ref()), 2) res = obj.emit("sig-with-int64-prop", 42) self.assertEqual(res, 21) self.assertEqual(sys.getrefcount(data_ref()), 2) del obj self.assertIsNone(data_ref()) @unittest.skipUnless(hasattr(sys, "getrefcount"), "no sys.getrefcount") @unittest.expectedFailure # https://bugzilla.gnome.org/show_bug.cgi?id=688064 def test_object_ref_count(self): # connect_object() should only weakly reference the object passed in # and auto-disconnect the signal when the object is destroyed. def callback(data, value): return value // 2 data = GObject.Object() data_ref = weakref.ref(data) self.assertEqual(sys.getrefcount(data), 2) obj = self.Object() handler_id = obj.connect_object("sig-with-int64-prop", callback, data) self.assertEqual(sys.getrefcount(data), 2) res = obj.emit("sig-with-int64-prop", 42) self.assertEqual(res, 21) self.assertEqual(sys.getrefcount(data), 2) del data self.assertIsNone(data_ref()) self.assertFalse(obj.handler_is_connected(handler_id)) class TestRefCountsNonIntrospected(unittest.TestCase, _RefCountTestBase): class Object(GObject.Object): sig_with_int64_prop = GObject.Signal( return_type=GObject.TYPE_INT64, arg_types=[GObject.TYPE_INT64], flags=GObject.SignalFlags.RUN_LAST, ) class TestRefCountsIntrospected(unittest.TestCase, _RefCountTestBase): Object = Regress.TestObj class TestClosureRefCycle(unittest.TestCase): def test_closure_ref_cycle_unreachable(self): # https://bugzilla.gnome.org/show_bug.cgi?id=731501 called = [] def on_add(store, *args): called.append(store) store = Gio.ListStore() store.connect_object("items-changed", on_add, store) # Remove all Python references to the object and keep it alive # on the C level. x = Gio.FileInfo() x.set_attribute_object("store", store) del store gc.collect() # get it back and trigger the signal x.get_attribute_object("store").append(Gio.FileInfo()) self.assertEqual(len(called), 1) self.assertTrue(called[0].__grefcount__ > 0) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_signature.py0000664000000000000000000002231215074673150017122 0ustar00rootrootimport inspect import typing import unittest from gi.repository import GIMarshallingTests, GLib, Gio, GObject class Test(unittest.TestCase): def test_signature_attr(self): func = GIMarshallingTests.Object.full_inout self.assertTrue(hasattr(func, "__signature__")) sig1 = func.__signature__ sig2 = inspect.signature(func) self.assertIsInstance(sig1, inspect.Signature) self.assertEqual(sig1, sig2) def assertSignatureEqual(self, first, second, msg=None): first_sig = inspect.signature(first) second_sig = inspect.signature(second) self.assertEqual(first_sig, second_sig, msg=msg) def test_allow_none_with_user_data_defaults(self): def expected( self, destination: Gio.File, flags: Gio.FileCopyFlags, cancellable: typing.Optional[Gio.Cancellable] = None, progress_callback: typing.Optional[ typing.Callable[[int, int, typing.Any], None] ] = None, progress_callback_data: typing.Any = None, ) -> bool: pass self.assertSignatureEqual(Gio.File.copy, expected) def test_init_function(self): def expected( argv: typing.Optional[list[str]] = None, ) -> tuple[bool, typing.Optional[list[str]]]: pass self.assertSignatureEqual(GIMarshallingTests.init_function, expected) def test_in_arg(self): def expected(ints: list[int]) -> None: pass self.assertSignatureEqual(GIMarshallingTests.array_in, expected) def test_inout_arg(self): def expected(ints: list[int]) -> list[int]: pass self.assertSignatureEqual(GIMarshallingTests.array_inout, expected) def test_out_arg(self): def expected() -> list[int]: pass self.assertSignatureEqual(GIMarshallingTests.array_out, expected) def test_arg_boolean(self): def expected(v: bool) -> None: pass self.assertSignatureEqual(GIMarshallingTests.boolean_in_true, expected) def test_arg_int8(self): def expected(v: int) -> None: pass self.assertSignatureEqual(GIMarshallingTests.int8_in_max, expected) def test_arg_uint8(self): def expected(v: int) -> None: pass self.assertSignatureEqual(GIMarshallingTests.uint8_in, expected) def test_arg_int16(self): def expected(v: int) -> None: pass self.assertSignatureEqual(GIMarshallingTests.int16_in_max, expected) def test_arg_uint16(self): def expected(v: int) -> None: pass self.assertSignatureEqual(GIMarshallingTests.uint16_in, expected) def test_arg_int32(self): def expected(v: int) -> None: pass self.assertSignatureEqual(GIMarshallingTests.int32_in_max, expected) def test_arg_uint32(self): def expected(v: int) -> None: pass self.assertSignatureEqual(GIMarshallingTests.uint32_in, expected) def test_arg_int64(self): def expected(v: int) -> None: pass self.assertSignatureEqual(GIMarshallingTests.int64_in_max, expected) def test_arg_uint64(self): def expected(v: int) -> None: pass self.assertSignatureEqual(GIMarshallingTests.uint64_in, expected) def test_arg_float(self): def expected(v: float) -> None: pass self.assertSignatureEqual(GIMarshallingTests.float_in, expected) def test_arg_double(self): def expected(v: float) -> None: pass self.assertSignatureEqual(GIMarshallingTests.double_in, expected) def test_arg_gtype(self): def expected(gtype: GObject.GType) -> None: pass self.assertSignatureEqual(GIMarshallingTests.gtype_in, expected) def test_arg_utf8(self): def expected(utf8: str) -> None: pass self.assertSignatureEqual(GIMarshallingTests.utf8_none_in, expected) def test_arg_filename(self): def expected(path: str) -> bool: pass self.assertSignatureEqual(GIMarshallingTests.filename_exists, expected) def test_arg_enum(self): def expected(v: GIMarshallingTests.Enum) -> None: pass self.assertSignatureEqual(GIMarshallingTests.enum_in, expected) def test_arg_genum(self): def expected(v: GIMarshallingTests.GEnum) -> None: pass self.assertSignatureEqual(GIMarshallingTests.genum_in, expected) def test_arg_flags(self): def expected(v: GIMarshallingTests.NoTypeFlags) -> None: pass self.assertSignatureEqual(GIMarshallingTests.no_type_flags_in, expected) def test_arg_gflags(self): def expected(v: GIMarshallingTests.Flags) -> None: pass self.assertSignatureEqual(GIMarshallingTests.flags_in, expected) def test_arg_array(self): def expected(ints: list[int]) -> None: pass self.assertSignatureEqual(GIMarshallingTests.array_fixed_int_in, expected) self.assertSignatureEqual(GIMarshallingTests.array_in, expected) def test_arg_garray(self): def expected(array_: list[int]) -> None: pass self.assertSignatureEqual(GIMarshallingTests.garray_int_none_in, expected) def test_arg_ptrarray(self): def expected(parray_: list[str]) -> None: pass self.assertSignatureEqual(GIMarshallingTests.gptrarray_utf8_none_in, expected) def test_arg_glist(self): def expected(list: list[int]) -> None: pass self.assertSignatureEqual(GIMarshallingTests.glist_int_none_in, expected) def test_arg_gslist(self): def expected(list: list[int]) -> None: pass self.assertSignatureEqual(GIMarshallingTests.gslist_int_none_in, expected) def test_arg_ghashtable(self): def expected(hash_table: dict[int, int]) -> None: pass self.assertSignatureEqual(GIMarshallingTests.ghashtable_int_none_in, expected) def test_arg_gvalue(self): def expected(value: GObject.Value) -> None: pass self.assertSignatureEqual(GIMarshallingTests.gvalue_in, expected) def test_arg_struct(self): def expected(structs: list[GIMarshallingTests.SimpleStruct]) -> None: pass self.assertSignatureEqual(GIMarshallingTests.array_simple_struct_in, expected) def test_arg_boxed(self): def expected(structs: list[GIMarshallingTests.BoxedStruct]) -> None: pass self.assertSignatureEqual(GIMarshallingTests.array_struct_in, expected) def test_return(self): def expected() -> int: pass self.assertSignatureEqual(GIMarshallingTests.int_return_max, expected) def test_return_multiple(self): def expected() -> tuple[int, int]: pass self.assertSignatureEqual(GIMarshallingTests.int_out_out, expected) self.assertSignatureEqual(GIMarshallingTests.int_return_out, expected) def test_object_full_inout(self): class A: @staticmethod def expected( object: GIMarshallingTests.Object, ) -> GIMarshallingTests.Object: pass self.assertSignatureEqual(GIMarshallingTests.Object.full_inout, A.expected) self.assertSignatureEqual(GIMarshallingTests.Object().full_inout, A().expected) def test_object_constructor(self): class A: @classmethod def expected(cls, int_: int) -> GIMarshallingTests.Object: pass self.assertSignatureEqual(GIMarshallingTests.Object.new, A.expected) self.assertSignatureEqual(GIMarshallingTests.Object().new, A().expected) def test_object_method(self): class A: def expected(self, ints: list[int]) -> None: pass self.assertSignatureEqual(GIMarshallingTests.Object.method_array_in, A.expected) self.assertSignatureEqual( GIMarshallingTests.Object().method_array_in, A().expected ) def test_object_static_method(self): class A: @staticmethod def expected() -> None: pass self.assertSignatureEqual(GIMarshallingTests.Object.static_method, A.expected) self.assertSignatureEqual( GIMarshallingTests.Object().static_method, A().expected ) def test_object_virtual_method(self): class A: @classmethod def expected(cls, self, object: GObject.GObject) -> None: pass self.assertSignatureEqual( GIMarshallingTests.Object.do_vfunc_in_object_transfer_none, A.expected ) self.assertSignatureEqual( GIMarshallingTests.Object().do_vfunc_in_object_transfer_none, A().expected ) def test_arg_conflict(self): class A: @classmethod def expected( type_, self, offset: int, type: GLib.SeekType, cancellable: typing.Optional[Gio.Cancellable] = None, ) -> bool: pass self.assertSignatureEqual(Gio.FileIOStream.do_seek, A.expected) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_source.py0000664000000000000000000003143115074673150016423 0ustar00rootrootimport sys import gc import unittest import warnings from gi.repository import GLib from gi import PyGIDeprecationWarning from .helper import capture_glib_warnings class Idle(GLib.Idle): def __init__(self, loop): GLib.Idle.__init__(self) self.count = 0 self.set_callback(self.callback, loop) def callback(self, loop): self.count += 1 return True class MySource(GLib.Source): def __init__(self): GLib.Source.__init__(self) def prepare(self): return True, 0 def check(self): return True def dispatch(self, callback, args): return callback(*args) class TestSource(unittest.TestCase): def timeout_callback(self, loop): loop.quit() def my_callback(self, loop): self.pos += 1 return True def setup_timeout(self, loop): timeout = GLib.Timeout(500) timeout.set_callback(self.timeout_callback, loop) timeout.attach() def test_sources(self): loop = GLib.MainLoop() self.setup_timeout(loop) idle = Idle(loop) self.assertEqual(idle.get_context(), None) idle.attach() self.assertEqual(idle.get_context(), GLib.main_context_default()) self.pos = 0 m = MySource() self.assertEqual(m.get_context(), None) m.set_callback(self.my_callback, loop) m.attach() self.assertEqual(m.get_context(), GLib.main_context_default()) loop.run() m.destroy() idle.destroy() self.assertGreater(self.pos, 0) self.assertGreaterEqual(idle.count, 0) self.assertTrue(m.is_destroyed()) self.assertTrue(idle.is_destroyed()) def test_source_prepare(self): # this test may not terminate if prepare() is wrapped incorrectly dispatched = [False] loop = GLib.MainLoop() class CustomTimeout(GLib.Source): def prepare(self): return (False, 10) def check(self): return True def dispatch(self, callback, args): dispatched[0] = True loop.quit() return False source = CustomTimeout() source.attach() source.set_callback(dir) loop.run() assert dispatched[0] def test_is_destroyed_simple(self): s = GLib.Source() self.assertFalse(s.is_destroyed()) s.destroy() self.assertTrue(s.is_destroyed()) c = GLib.MainContext() s = GLib.Source() s.attach(c) self.assertFalse(s.is_destroyed()) s.destroy() self.assertTrue(s.is_destroyed()) def test_is_destroyed_context(self): def f(): c = GLib.MainContext() s = GLib.Source() s.attach(c) return s s = f() gc.collect() gc.collect() self.assertTrue(s.is_destroyed()) def test_remove(self): s = GLib.idle_add(dir) self.assertEqual(GLib.source_remove(s), True) # Removing sources not found cause critical with capture_glib_warnings(allow_criticals=True): # s is now removed, should fail now self.assertEqual(GLib.source_remove(s), False) # accepts large source IDs (they are unsigned) self.assertEqual(GLib.source_remove(GLib.MAXINT32), False) self.assertEqual(GLib.source_remove(GLib.MAXINT32 + 1), False) self.assertEqual(GLib.source_remove(GLib.MAXUINT32), False) def test_recurse_property(self): s = GLib.Idle() self.assertTrue(s.can_recurse in [False, True]) s.can_recurse = False self.assertFalse(s.can_recurse) def test_priority(self): s = GLib.Idle() self.assertEqual(s.priority, GLib.PRIORITY_DEFAULT_IDLE) s.priority = GLib.PRIORITY_HIGH self.assertEqual(s.priority, GLib.PRIORITY_HIGH) s = GLib.Idle(GLib.PRIORITY_LOW) self.assertEqual(s.priority, GLib.PRIORITY_LOW) s = GLib.Timeout(1, GLib.PRIORITY_LOW) self.assertEqual(s.priority, GLib.PRIORITY_LOW) s = GLib.Source() self.assertEqual(s.priority, GLib.PRIORITY_DEFAULT) def test_get_current_time(self): # Note, deprecated API s = GLib.Idle() with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") time = s.get_current_time() self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning)) self.assertTrue(isinstance(time, float)) # plausibility check, and check magnitude of result self.assertGreater(time, 1300000000.0) self.assertLess(time, 2000000000.0) def test_add_remove_poll(self): # FIXME: very shallow test, only verifies the API signature pollfd = GLib.PollFD(99, GLib.IOCondition.IN | GLib.IOCondition.HUP) self.assertEqual(pollfd.fd, 99) source = GLib.Source() source.add_poll(pollfd) source.remove_poll(pollfd) def test_out_of_scope_before_dispatch(self): # https://bugzilla.gnome.org/show_bug.cgi?id=504337 GLib.Timeout(20) GLib.Idle() @unittest.skipIf(sys.platform == "darwin", "hangs") def test_finalize(self): self.dispatched = False self.finalized = False class S(GLib.Source): def prepare(s): return (True, 1) def dispatch(s, callback, args): self.dispatched = True return False def finalize(s): self.finalized = True source = S() source.attach() self.assertFalse(self.finalized) self.assertFalse(source.is_destroyed()) while source.get_context().iteration(False): pass source.destroy() self.assertTrue(self.dispatched) self.assertFalse(self.finalized) self.assertTrue(source.is_destroyed()) del source gc.collect() gc.collect() self.assertTrue(self.finalized) def test_python_unref_with_active_source(self): # Tests a Python derived Source which is free'd in the context of # Python, but which was attached to a MainContext (via source.attach()) self.dispatched = False self.finalized = False class S(GLib.Source): def prepare(s): return (True, 1) def check(s): pass def dispatch(s, callback, args): self.dispatched = True return False def finalize(s): self.finalized = True context = GLib.MainContext.new() source = S() id_ = source.attach(context) self.assertFalse(self.finalized) self.assertFalse(source.is_destroyed()) # Delete the source from Python, it should detach del source gc.collect() gc.collect() while context.iteration(may_block=False): pass assert self.finalized assert not self.dispatched assert context.find_source_by_id(id_) is None @unittest.skipIf( sys.implementation.name == "pypy", "PyPy doesn't __del__ immediately" ) def test_python_unref_during_dispatch(self): # Tests a Python derived Source which is free'd in the context of # Python, while being dispatched # NOTE: Finalize is explicitly called by __del__ for consistency self.dispatched = False self.finalized = False class S(GLib.Source): def __init__(s, func=None): s.func = func def prepare(s): return (True, 1) def check(s): pass def dispatch(s, callback, args): self.dispatched = True self.source = None return False def finalize(s): self.finalized = True context = GLib.MainContext.new() self.source = S() id_ = self.source.attach(context) while context.iteration(may_block=False): pass assert self.source is None assert context.find_source_by_id(id_) is None assert self.finalized assert self.dispatched def test_extra_init_args(self): class SourceWithInitArgs(GLib.Source): def __init__(self, arg, kwarg=None): super().__init__() self.arg = arg self.kwarg = kwarg source = SourceWithInitArgs(1, kwarg=2) self.assertEqual(source.arg, 1) self.assertEqual(source.kwarg, 2) @unittest.skipIf(sys.platform == "darwin", "hangs") class TestUserData(unittest.TestCase): def test_idle_no_data(self): ml = GLib.MainLoop() def cb(): ml.quit() id = GLib.idle_add(cb) self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_DEFAULT_IDLE ) ml.run() def test_timeout_no_data(self): ml = GLib.MainLoop() def cb(): ml.quit() id = GLib.timeout_add(1, cb) self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_DEFAULT ) ml.run() def test_idle_data(self): ml = GLib.MainLoop() def cb(data): data["called"] = True ml.quit() data = {} id = GLib.idle_add(cb, data) self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_DEFAULT_IDLE ) ml.run() self.assertTrue(data["called"]) def test_idle_multidata(self): ml = GLib.MainLoop() def cb(data, data2): data["called"] = True data["data2"] = data2 ml.quit() data = {} id = GLib.idle_add(cb, data, "hello") self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_DEFAULT_IDLE ) ml.run() self.assertTrue(data["called"]) self.assertEqual(data["data2"], "hello") def test_timeout_data(self): ml = GLib.MainLoop() def cb(data): data["called"] = True ml.quit() data = {} id = GLib.timeout_add(1, cb, data) self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_DEFAULT ) ml.run() self.assertTrue(data["called"]) def test_timeout_multidata(self): ml = GLib.MainLoop() def cb(data, data2): data["called"] = True data["data2"] = data2 ml.quit() data = {} id = GLib.timeout_add(1, cb, data, "hello") self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_DEFAULT ) ml.run() self.assertTrue(data["called"]) self.assertEqual(data["data2"], "hello") def test_idle_no_data_priority(self): ml = GLib.MainLoop() def cb(): ml.quit() id = GLib.idle_add(cb, priority=GLib.PRIORITY_HIGH) self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) ml.run() def test_timeout_no_data_priority(self): ml = GLib.MainLoop() def cb(): ml.quit() id = GLib.timeout_add(1, cb, priority=GLib.PRIORITY_HIGH) self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) ml.run() def test_idle_data_priority(self): ml = GLib.MainLoop() def cb(data): data["called"] = True ml.quit() data = {} id = GLib.idle_add(cb, data, priority=GLib.PRIORITY_HIGH) self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) ml.run() self.assertTrue(data["called"]) def test_timeout_data_priority(self): ml = GLib.MainLoop() def cb(data): data["called"] = True ml.quit() data = {} id = GLib.timeout_add(1, cb, data, priority=GLib.PRIORITY_HIGH) self.assertEqual( ml.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) ml.run() self.assertTrue(data["called"]) def cb_no_data(self): self.loop.quit() def test_idle_method_callback_no_data(self): self.loop = GLib.MainLoop() GLib.idle_add(self.cb_no_data) self.loop.run() def cb_with_data(self, data): data["called"] = True self.loop.quit() def test_idle_method_callback_with_data(self): self.loop = GLib.MainLoop() data = {} GLib.idle_add(self.cb_with_data, data) self.loop.run() self.assertTrue(data["called"]) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_subprocess.py0000664000000000000000000001524215074673150017315 0ustar00rootrootimport sys import os import unittest import warnings import pytest from gi.repository import GLib from gi import PyGIDeprecationWarning from .helper import capture_gi_deprecation_warnings def test_child_watch_add_get_args_various(): def cb(pid, status): return None get_args = GLib._child_watch_add_get_args pid = 42 with capture_gi_deprecation_warnings(): assert get_args(pid, cb, 2) == (0, pid, cb, (2,)) with pytest.raises(TypeError): get_args(pid, cb, 2, 3, 4) assert get_args(0, pid, 2, 3, function=cb) == (0, pid, cb, (2, 3)) assert get_args(0, pid, cb, 2, 3) == (0, pid, cb, (2, 3)) assert get_args(0, pid, cb, data=99) == (0, pid, cb, (99,)) with pytest.raises(TypeError): get_args(0, pid, 24) with pytest.raises(TypeError): get_args(0, pid, cb, 2, 3, data=99) @unittest.skipIf(os.name == "nt", "not on Windows") class TestProcess(unittest.TestCase): def test_deprecated_child_watch_no_data(self): def cb(pid, status): return None pid = object() with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") res = GLib._child_watch_add_get_args(pid, cb) self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning)) self.assertEqual(len(res), 4) self.assertEqual(res[0], GLib.PRIORITY_DEFAULT) self.assertEqual(res[1], pid) self.assertTrue(callable(cb)) self.assertSequenceEqual(res[3], []) def test_deprecated_child_watch_data_priority(self): def cb(pid, status): return None pid = object() with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") res = GLib._child_watch_add_get_args(pid, cb, 12345, GLib.PRIORITY_HIGH) self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning)) self.assertEqual(len(res), 4) self.assertEqual(res[0], GLib.PRIORITY_HIGH) self.assertEqual(res[1], pid) self.assertEqual(res[2], cb) self.assertSequenceEqual(res[3], [12345]) def test_deprecated_child_watch_data_priority_kwargs(self): def cb(pid, status): return None pid = object() with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") res = GLib._child_watch_add_get_args( pid, cb, priority=GLib.PRIORITY_HIGH, data=12345 ) self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning)) self.assertEqual(len(res), 4) self.assertEqual(res[0], GLib.PRIORITY_HIGH) self.assertEqual(res[1], pid) self.assertEqual(res[2], cb) self.assertSequenceEqual(res[3], [12345]) @unittest.expectedFailure # using keyword args is fully supported by PyGObject machinery def test_child_watch_all_kwargs(self): def cb(pid, status): return None pid = object() res = GLib._child_watch_add_get_args( priority=GLib.PRIORITY_HIGH, pid=pid, function=cb, data=12345 ) self.assertEqual(len(res), 4) self.assertEqual(res[0], GLib.PRIORITY_HIGH) self.assertEqual(res[1], pid) self.assertEqual(res[2], cb) self.assertSequenceEqual(res[3], [12345]) def test_child_watch_no_data(self): def cb(pid, status): self.status = status self.loop.quit() self.status = None self.loop = GLib.MainLoop() argv = [sys.executable, "-c", "import sys"] pid, _stdin, _stdout, _stderr = GLib.spawn_async( argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD ) pid.close() id = GLib.child_watch_add(GLib.PRIORITY_HIGH, pid, cb) self.assertEqual( self.loop.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) self.loop.run() self.assertEqual(self.status, 0) def test_child_watch_with_data(self): def cb(pid, status, data): self.status = status self.data = data self.loop.quit() self.data = None self.status = None self.loop = GLib.MainLoop() argv = [sys.executable, "-c", "import sys"] pid, stdin, stdout, stderr = GLib.spawn_async( argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD ) self.assertEqual(stdin, None) self.assertEqual(stdout, None) self.assertEqual(stderr, None) self.assertNotEqual(pid, 0) pid.close() id = GLib.child_watch_add(GLib.PRIORITY_HIGH, pid, cb, 12345) self.assertEqual( self.loop.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH ) self.loop.run() self.assertEqual(self.data, 12345) self.assertEqual(self.status, 0) def test_spawn_async_fds(self): pid, stdin, stdout, stderr = GLib.spawn_async( ["cat"], flags=GLib.SpawnFlags.SEARCH_PATH, standard_input=True, standard_output=True, standard_error=True, ) os.write(stdin, b"hello world!\n") os.close(stdin) out = os.read(stdout, 50) os.close(stdout) err = os.read(stderr, 50) os.close(stderr) pid.close() self.assertEqual(out, b"hello world!\n") self.assertEqual(err, b"") def test_spawn_async_with_pipes(self): _res, pid, stdin, stdout, stderr = GLib.spawn_async_with_pipes( working_directory=None, argv=["cat"], envp=None, flags=GLib.SpawnFlags.SEARCH_PATH, ) os.write(stdin, b"hello world!\n") os.close(stdin) out = os.read(stdout, 50) os.close(stdout) err = os.read(stderr, 50) os.close(stderr) GLib.spawn_close_pid(pid) self.assertEqual(out, b"hello world!\n") self.assertEqual(err, b"") def test_spawn_async_envp(self): pid, stdin, stdout, stderr = GLib.spawn_async( ["sh", "-c", "echo $TEST_VAR"], ["TEST_VAR=moo!"], flags=GLib.SpawnFlags.SEARCH_PATH, standard_output=True, ) self.assertEqual(stdin, None) self.assertEqual(stderr, None) out = os.read(stdout, 50) os.close(stdout) pid.close() self.assertEqual(out, b"moo!\n") def test_backwards_compat_flags(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", PyGIDeprecationWarning) self.assertEqual( GLib.SpawnFlags.DO_NOT_REAP_CHILD, GLib.SPAWN_DO_NOT_REAP_CHILD ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_thread.py0000664000000000000000000000144415074673150016373 0ustar00rootrootimport unittest from gi.repository import GLib import testhelper class TestThread(unittest.TestCase): def setUp(self): self.main = GLib.MainLoop() self.called = False def from_thread_cb(self, test, enum): assert test == self.obj assert int(enum) == 0 assert type(enum) is not int self.called = True GLib.idle_add(self.timeout_cb) def idle_cb(self): self.obj = testhelper.get_test_thread() self.obj.connect("from-thread", self.from_thread_cb) self.obj.emit("emit-signal") def test_extension_module(self): GLib.idle_add(self.idle_cb) GLib.timeout_add(2000, self.timeout_cb) self.main.run() self.assertTrue(self.called) def timeout_cb(self): self.main.quit() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_typeclass.py0000664000000000000000000000561715074673150017141 0ustar00rootroot# test_typeclass.py: Tests for GTypeClass related methods and marshalling. # # Copyright (C) 2014 Simon Feltman # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA import unittest from gi.repository import GObject from gi.repository import GIMarshallingTests class TestCoercion(unittest.TestCase): def test_coerce_from_class(self): prop = GObject.ObjectClass.find_property( GIMarshallingTests.PropertiesObject, "some-int" ) self.assertIsInstance(prop, GObject.ParamSpec) self.assertEqual(prop.name, "some-int") self.assertEqual(prop.value_type, GObject.TYPE_INT) self.assertEqual(prop.owner_type, GIMarshallingTests.PropertiesObject.__gtype__) def test_coerce_from_gtype(self): gtype = GIMarshallingTests.PropertiesObject.__gtype__ prop = GObject.ObjectClass.find_property(gtype, "some-int") self.assertIsInstance(prop, GObject.ParamSpec) self.assertEqual(prop.name, "some-int") self.assertEqual(prop.value_type, GObject.TYPE_INT) self.assertEqual(prop.owner_type, gtype) def test_coerce_from_instance(self): obj = GIMarshallingTests.PropertiesObject() prop = GObject.ObjectClass.find_property(obj, "some-int") self.assertIsInstance(prop, GObject.ParamSpec) self.assertEqual(prop.name, "some-int") self.assertEqual(prop.value_type, GObject.TYPE_INT) self.assertEqual(prop.owner_type, obj.__gtype__) def test_marshalling_error(self): with self.assertRaises(TypeError): GObject.ObjectClass.find_property(object, "some-int") with self.assertRaises(TypeError): GObject.ObjectClass.find_property(42, "some-int") class TestTypeClassMethodsMovedToClass(unittest.TestCase): def test_list_child_properties(self): pspecs = GIMarshallingTests.PropertiesObject.list_properties() pnames = [pspec.name for pspec in pspecs] self.assertTrue("some-int" in pnames) self.assertTrue("some-float" in pnames) self.assertTrue("some-char" in pnames) def test_find_child_property(self): pspec = GIMarshallingTests.PropertiesObject.find_property("some-int") self.assertEqual(pspec.name, "some-int") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/test_unknown.py0000664000000000000000000000154515074673150016625 0ustar00rootrootimport unittest from gi.repository import GObject import testhelper TestInterface = GObject.GType.from_name("TestInterface") class TestUnknown(unittest.TestCase): def test_unknown_interface(self): obj = testhelper.get_unknown() TestUnknownGType = GObject.GType.from_name("TestUnknown") TestUnknown = GObject.new(TestUnknownGType).__class__ assert isinstance(obj, testhelper.Interface) assert isinstance(obj, TestUnknown) def test_property(self): obj = testhelper.get_unknown() self.assertEqual(obj.get_property("some-property"), None) obj.set_property("some-property", "foo") def test_unknown_property(self): obj = testhelper.get_unknown() self.assertRaises(TypeError, obj.get_property, "unknown") self.assertRaises(TypeError, obj.set_property, "unknown", "1") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/testhelpermodule.c0000664000000000000000000005652415074673150017255 0ustar00rootroot#include #include #include #include #include "pygobject.h" #include "test-floating.h" #include "test-thread.h" #include "test-unknown.h" #define PYGI_DEFINE_TYPE(typename, symbol, csymbol) \ PyTypeObject symbol = { PyVarObject_HEAD_INIT (NULL, 0) typename, \ sizeof (csymbol) }; static PyObject *_wrap_TestInterface__do_iface_method (PyObject *cls, PyObject *args, PyObject *kwargs); static GType test_type_get_type (void) { static GType gtype = 0; GType parent_type; if (gtype == 0) { GTypeInfo *type_info; GTypeQuery query; parent_type = g_type_from_name ("PyGObject"); if (parent_type == 0) g_error ("could not get PyGObject from testmodule"); type_info = (GTypeInfo *)g_new0 (GTypeInfo, 1); g_type_query (parent_type, &query); type_info->class_size = (guint16)query.class_size; type_info->instance_size = (guint16)query.instance_size; gtype = g_type_register_static (parent_type, "TestType", type_info, 0); if (!gtype) g_error ("Could not register TestType"); } return gtype; } #define TYPE_TEST (test_type_get_type ()) static PyObject * _wrap_get_test_thread (PyObject *self) { GObject *obj; test_thread_get_type (); g_assert (g_type_is_a (TEST_TYPE_THREAD, G_TYPE_OBJECT)); obj = g_object_new (TEST_TYPE_THREAD, NULL); g_assert (obj != NULL); return pygobject_new (obj); } static PyObject * _wrap_get_unknown (PyObject *self) { GObject *obj; obj = g_object_new (TEST_TYPE_UNKNOWN, NULL); return pygobject_new (obj); } static PyObject * _wrap_create_test_type (PyObject *self) { GObject *obj; PyObject *rv; obj = g_object_new (TYPE_TEST, NULL); rv = pygobject_new (obj); g_object_unref (obj); return rv; } static PyObject * _wrap_test_g_object_new (PyObject *self) { GObject *obj; PyObject *rv; obj = g_object_new (g_type_from_name ("PyGObject"), NULL); rv = PyLong_FromLong (obj->ref_count); /* should be == 2 at this point */ g_object_unref (obj); return rv; } /* TestUnknown */ static PyObject * _wrap_test_interface_iface_method (PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, ":", kwlist)) return NULL; test_interface_iface_method (TEST_INTERFACE (self->obj)); Py_RETURN_NONE; } static const PyMethodDef _PyTestInterface_methods[] = { { "iface_method", (PyCFunction)_wrap_test_interface_iface_method, METH_VARARGS | METH_KEYWORDS, NULL }, { "do_iface_method", (PyCFunction)_wrap_TestInterface__do_iface_method, METH_VARARGS | METH_KEYWORDS | METH_CLASS, NULL }, { NULL, NULL, 0, NULL } }; /* TestInterface */ PYGI_DEFINE_TYPE ("test.Interface", PyTestInterface_Type, PyObject); static PyObject * _wrap_TestInterface__do_iface_method (PyObject *cls, PyObject *args, PyObject *kwargs) { TestInterfaceIface *iface; static char *kwlist[] = { "self", NULL }; PyGObject *self; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O!:TestInterface.iface_method", kwlist, &PyTestInterface_Type, &self)) return NULL; iface = g_type_interface_peek ( g_type_class_peek (pyg_type_from_object (cls)), TEST_TYPE_INTERFACE); if (iface->iface_method) iface->iface_method (TEST_INTERFACE (self->obj)); else { PyErr_SetString ( PyExc_NotImplementedError, "interface method TestInterface.iface_method not implemented"); return NULL; } Py_RETURN_NONE; } PYGI_DEFINE_TYPE ("testhelper.Unknown", PyTestUnknown_Type, PyGObject); static void _wrap_TestInterface__proxy_do_iface_method (TestInterface *self) { PyGILState_STATE __py_state; PyObject *py_self; PyObject *py_retval; PyObject *py_args; PyObject *py_method; __py_state = PyGILState_Ensure (); py_self = pygobject_new ((GObject *)self); if (!py_self) { if (PyErr_Occurred ()) PyErr_Print (); PyGILState_Release (__py_state); return; } py_args = PyTuple_New (0); py_method = PyObject_GetAttrString (py_self, "do_iface_method"); if (!py_method) { if (PyErr_Occurred ()) PyErr_Print (); Py_DECREF (py_args); Py_DECREF (py_self); PyGILState_Release (__py_state); return; } py_retval = PyObject_CallObject (py_method, py_args); if (!py_retval) { if (PyErr_Occurred ()) PyErr_Print (); Py_DECREF (py_method); Py_DECREF (py_args); Py_DECREF (py_self); PyGILState_Release (__py_state); return; } if (!Py_IsNone (py_retval)) { if (PyErr_Occurred ()) PyErr_Print (); PyErr_SetString (PyExc_TypeError, "retval should be None"); Py_DECREF (py_retval); Py_DECREF (py_method); Py_DECREF (py_args); Py_DECREF (py_self); PyGILState_Release (__py_state); return; } Py_DECREF (py_retval); Py_DECREF (py_method); Py_DECREF (py_args); Py_DECREF (py_self); PyGILState_Release (__py_state); } static void __TestInterface__interface_init (TestInterfaceIface *iface, PyTypeObject *pytype) { TestInterfaceIface *parent_iface = g_type_interface_peek_parent (iface); PyObject *py_method; py_method = pytype ? PyObject_GetAttrString ((PyObject *)pytype, "do_iface_method") : NULL; if (py_method && !PyObject_TypeCheck (py_method, &PyCFunction_Type)) { iface->iface_method = _wrap_TestInterface__proxy_do_iface_method; } else { PyErr_Clear (); if (parent_iface) { iface->iface_method = parent_iface->iface_method; } Py_XDECREF (py_method); } } static const GInterfaceInfo __TestInterface__iinfo = { (GInterfaceInitFunc)__TestInterface__interface_init, NULL, NULL }; /* TestFloating */ PYGI_DEFINE_TYPE ("testhelper.Floating", PyTestFloating_Type, PyGObject); /* TestOwnedByLibrary */ PYGI_DEFINE_TYPE ("testhelper.OwnedByLibrary", PyTestOwnedByLibrary_Type, PyGObject); static PyObject * _wrap_test_owned_by_library_release (PyGObject *self) { test_owned_by_library_release (TEST_OWNED_BY_LIBRARY (self->obj)); return Py_None; } static const PyMethodDef _PyTestOwnedByLibrary_methods[] = { { "release", (PyCFunction)_wrap_test_owned_by_library_release, METH_NOARGS, NULL }, { NULL, NULL, 0, NULL } }; /* TestFloatingAndSunk */ PYGI_DEFINE_TYPE ("testhelper.FloatingAndSunk", PyTestFloatingAndSunk_Type, PyGObject); static PyObject * _wrap_test_floating_and_sunk_release (PyGObject *self) { test_floating_and_sunk_release (TEST_FLOATING_AND_SUNK (self->obj)); return Py_None; } static const PyMethodDef _PyTestFloatingAndSunk_methods[] = { { "release", (PyCFunction)_wrap_test_floating_and_sunk_release, METH_NOARGS, NULL }, { NULL, NULL, 0, NULL } }; static void test1_callback (GObject *object, char *data) { g_return_if_fail (G_IS_OBJECT (object)); g_return_if_fail (!strcmp (data, "user-data")); } static void test1_callback_swapped (char *data, GObject *object) { g_return_if_fail (G_IS_OBJECT (object)); g_return_if_fail (!strcmp (data, "user-data")); } static void test2_callback (GObject *object, char *string) { g_return_if_fail (G_IS_OBJECT (object)); g_return_if_fail (!strcmp (string, "string")); } static int test3_callback (GObject *object, double d) { g_return_val_if_fail (G_IS_OBJECT (object), -1); g_return_val_if_fail (d == 42.0, -1); return 20; } static void test4_callback (GObject *object, gboolean b, long l, float f, double d, guint uint, gulong ulong, gpointer user_data) { g_return_if_fail (b == TRUE); g_return_if_fail (l == 10L); g_return_if_fail (f <= 3.14001 && f >= 3.13999); g_return_if_fail (d <= 1.78001 && d >= 1.77999); g_return_if_fail (uint == 20); g_return_if_fail (ulong == 30L); } static float test_float_callback (GObject *object, float f) { g_return_val_if_fail (G_IS_OBJECT (object), -1); g_return_val_if_fail (f <= 1.234001 && f >= 1.123999, -1); return f; } static double test_double_callback (GObject *object, double d) { g_return_val_if_fail (G_IS_OBJECT (object), -1); g_return_val_if_fail (d <= 1.234001 && d >= 1.123999, -1); return d; } static gint64 test_int64_callback (GObject *object, gint64 i) { g_return_val_if_fail (G_IS_OBJECT (object), -1); if (i == G_MAXINT64) return i - 1; return i; } static char * test_string_callback (GObject *object, char *s) { g_return_val_if_fail (G_IS_OBJECT (object), NULL); g_return_val_if_fail (!strcmp (s, "str"), NULL); return g_strdup (s); } static GObject * test_object_callback (GObject *object, GObject *o) { g_return_val_if_fail (G_IS_OBJECT (object), NULL); return o; } static GParamSpec * test_paramspec_callback (GObject *object) { g_return_val_if_fail (G_IS_OBJECT (object), NULL); return g_param_spec_boolean ("test-param", "test", "test boolean", TRUE, G_PARAM_READABLE); } static GValue * test_gvalue_callback (GObject *object, const GValue *v) { GValue *ret; g_return_val_if_fail (G_IS_OBJECT (object), NULL); g_return_val_if_fail (G_IS_VALUE (v), NULL); ret = g_malloc0 (sizeof (GValue)); g_value_init (ret, G_VALUE_TYPE (v)); g_value_copy (v, ret); return ret; } static GValue * test_gvalue_ret_callback (GObject *object, GType type) { GValue *ret; g_return_val_if_fail (G_IS_OBJECT (object), NULL); ret = g_malloc0 (sizeof (GValue)); g_value_init (ret, type); switch (type) { case G_TYPE_INT: g_value_set_int (ret, G_MAXINT); break; case G_TYPE_INT64: g_value_set_int64 (ret, G_MAXINT64); break; case G_TYPE_UINT: g_value_set_uint (ret, G_MAXUINT); break; case G_TYPE_UINT64: g_value_set_uint64 (ret, G_MAXUINT64); break; case G_TYPE_STRING: g_value_set_string (ret, "hello"); break; default: g_critical ("test_gvalue_ret_callback() does not support type %s", g_type_name (type)); } return ret; } static GParamSpec * test_paramspec_in_callback (GObject *object, GParamSpec *p) { g_return_val_if_fail (G_IS_OBJECT (object), NULL); g_return_val_if_fail (G_IS_PARAM_SPEC (p), NULL); return p; } static void connectcallbacks (GObject *object) { gchar *data = "user-data"; g_signal_connect (G_OBJECT (object), "test1", G_CALLBACK (test1_callback), data); g_signal_connect_swapped (G_OBJECT (object), "test1", G_CALLBACK (test1_callback_swapped), data); g_signal_connect (G_OBJECT (object), "test2", G_CALLBACK (test2_callback), NULL); g_signal_connect (G_OBJECT (object), "test3", G_CALLBACK (test3_callback), NULL); g_signal_connect (G_OBJECT (object), "test4", G_CALLBACK (test4_callback), NULL); g_signal_connect (G_OBJECT (object), "test_float", G_CALLBACK (test_float_callback), NULL); g_signal_connect (G_OBJECT (object), "test_double", G_CALLBACK (test_double_callback), NULL); g_signal_connect (G_OBJECT (object), "test_int64", G_CALLBACK (test_int64_callback), NULL); g_signal_connect (G_OBJECT (object), "test_string", G_CALLBACK (test_string_callback), NULL); g_signal_connect (G_OBJECT (object), "test_object", G_CALLBACK (test_object_callback), NULL); g_signal_connect (G_OBJECT (object), "test_paramspec", G_CALLBACK (test_paramspec_callback), NULL); g_signal_connect (G_OBJECT (object), "test_gvalue", G_CALLBACK (test_gvalue_callback), NULL); g_signal_connect (G_OBJECT (object), "test_gvalue_ret", G_CALLBACK (test_gvalue_ret_callback), NULL); g_signal_connect (G_OBJECT (object), "test_paramspec_in", G_CALLBACK (test_paramspec_in_callback), NULL); } static PyObject * _wrap_connectcallbacks (PyObject *self, PyObject *args) { PyGObject *obj; if (!PyArg_ParseTuple (args, "O", &obj)) return NULL; connectcallbacks (G_OBJECT (obj->obj)); Py_RETURN_NONE; } static PyObject * _wrap_test_value (PyObject *self, PyObject *args) { GValue tvalue = {0,}, *value = &tvalue; PyObject *obj; if (!PyArg_ParseTuple (args, "O", &obj)) return NULL; g_value_init (value, G_TYPE_VALUE); if (pyg_value_from_pyobject (value, obj)) { PyErr_SetString (PyExc_TypeError, "Could not convert to GValue"); return NULL; } return pyg_value_as_pyobject (value, FALSE); } static PyObject * _wrap_test_state_ensure_release (PyObject *self, PyObject *args) { int state = pyg_gil_state_ensure (); pyg_gil_state_release (state); Py_RETURN_NONE; } #define PYGI_TYPE_VALUE_ARRAY (g_value_array_get_type ()) static PyObject * _wrap_test_value_array (PyObject *self, PyObject *args) { GValue tvalue = {0,}, *value = &tvalue; PyObject *obj; if (!PyArg_ParseTuple (args, "O", &obj)) return NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_value_init (value, PYGI_TYPE_VALUE_ARRAY); G_GNUC_END_IGNORE_DEPRECATIONS if (pyg_value_from_pyobject (value, obj)) { PyErr_SetString (PyExc_TypeError, "Could not convert to GValueArray"); return NULL; } return pyg_value_as_pyobject (value, FALSE); } static PyObject * _wrap_value_array_get_nth_type (PyObject *self, PyObject *args) { guint n; GType type; GValue *nth; GValueArray *arr; PyObject *obj; if (!PyArg_ParseTuple (args, "OI", &obj, &n)) return NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS if (pyg_boxed_check (obj, G_TYPE_VALUE) && G_VALUE_HOLDS (pyg_boxed_get (obj, GValue), PYGI_TYPE_VALUE_ARRAY)) { arr = g_value_get_boxed (pyg_boxed_get (obj, GValue)); } else if (pyg_boxed_check (obj, PYGI_TYPE_VALUE_ARRAY)) { arr = pyg_boxed_get (obj, GValueArray); } else { PyErr_SetString (PyExc_TypeError, "First argument is not GValueArray"); return NULL; } if (n >= arr->n_values) { PyErr_SetString (PyExc_TypeError, "Index is out of bounds"); return NULL; } nth = g_value_array_get_nth (arr, n); type = G_VALUE_TYPE (nth); G_GNUC_END_IGNORE_DEPRECATIONS return pyg_type_wrapper_new (type); } static PyObject * _wrap_constant_strip_prefix (PyObject *self, PyObject *args) { const char *name, *strip_prefix; const gchar *result; if (!PyArg_ParseTuple (args, "ss", &name, &strip_prefix)) return NULL; result = pyg_constant_strip_prefix (name, strip_prefix); return PyUnicode_FromString (result); } static PyObject * _wrap_test_gerror_exception (PyObject *self, PyObject *args) { PyObject *py_method; PyObject *py_args; PyObject *py_ret; GError *err = NULL; if (!PyArg_ParseTuple (args, "O", &py_method)) return NULL; py_args = PyTuple_New (0); py_ret = PyObject_CallObject (py_method, py_args); if (pyg_gerror_exception_check (&err)) { pyg_error_check (&err); return NULL; } Py_DECREF (py_args); Py_DECREF (py_ret); Py_RETURN_NONE; } static PyObject * _wrap_test_owned_by_library_get_instance_list (PyObject *self) { PyObject *py_list, *py_obj; GSList *list, *tmp; list = test_owned_by_library_get_instance_list (); if ((py_list = PyList_New (0)) == NULL) { return NULL; } for (tmp = list; tmp != NULL; tmp = tmp->next) { py_obj = pygobject_new (G_OBJECT (tmp->data)); if (py_obj == NULL) { Py_DECREF (py_list); return NULL; } PyList_Append (py_list, py_obj); Py_DECREF (py_obj); } return py_list; } static PyObject * _wrap_test_floating_and_sunk_get_instance_list (PyObject *self) { PyObject *py_list, *py_obj; GSList *list, *tmp; list = test_floating_and_sunk_get_instance_list (); if ((py_list = PyList_New (0)) == NULL) { return NULL; } for (tmp = list; tmp != NULL; tmp = tmp->next) { py_obj = pygobject_new (G_OBJECT (tmp->data)); if (py_obj == NULL) { Py_DECREF (py_list); return NULL; } PyList_Append (py_list, py_obj); Py_DECREF (py_obj); } return py_list; } static PyObject * _wrap_force_g_object_ref (PyObject *self, PyObject *args) { PyGObject *obj; if (!PyArg_ParseTuple (args, "O", &obj)) return NULL; g_assert (G_IS_OBJECT (obj->obj)); g_object_ref (obj->obj); Py_RETURN_NONE; } static PyObject * _wrap_force_g_object_unref (PyObject *self, PyObject *args) { PyGObject *obj; if (!PyArg_ParseTuple (args, "O", &obj)) return NULL; g_assert (G_IS_OBJECT (obj->obj)); g_object_unref (obj->obj); Py_RETURN_NONE; } G_GNUC_BEGIN_IGNORE_DEPRECATIONS static PyObject * _wrap_test_parse_constructor_args (PyObject *self, PyObject *args) { char *arg_names[] = { "label", NULL }; char *prop_names[] = { "label", NULL }; GParameter params[1] = { { 0 } }; PyObject *parsed_args[1]; guint nparams = 0; if (!PyArg_ParseTuple (args, "O", &(parsed_args[0]))) return NULL; if (!pyg_parse_constructor_args (TYPE_TEST, arg_names, prop_names, params, &nparams, parsed_args)) { return NULL; } return PyLong_FromLong (nparams); } G_GNUC_END_IGNORE_DEPRECATIONS static PyObject * _wrap_test_to_unichar_conv (PyObject *self, PyObject *args) { PyObject *obj; gunichar result; if (!PyArg_ParseTuple (args, "O", &obj)) return NULL; if (!pyg_pyobj_to_unichar_conv (obj, &result)) return NULL; return PyLong_FromLong (result); } static PyMethodDef testhelper_functions[] = { { "force_g_object_ref", (PyCFunction)_wrap_force_g_object_ref, METH_VARARGS }, { "force_g_object_unref", (PyCFunction)_wrap_force_g_object_unref, METH_VARARGS }, { "test_parse_constructor_args", (PyCFunction)_wrap_test_parse_constructor_args, METH_VARARGS }, { "get_test_thread", (PyCFunction)_wrap_get_test_thread, METH_NOARGS }, { "test_to_unichar_conv", (PyCFunction)_wrap_test_to_unichar_conv, METH_VARARGS }, { "get_unknown", (PyCFunction)_wrap_get_unknown, METH_NOARGS }, { "create_test_type", (PyCFunction)_wrap_create_test_type, METH_NOARGS }, { "test_state_ensure_release", (PyCFunction)_wrap_test_state_ensure_release, METH_NOARGS }, { "test_g_object_new", (PyCFunction)_wrap_test_g_object_new, METH_NOARGS }, { "connectcallbacks", (PyCFunction)_wrap_connectcallbacks, METH_VARARGS }, { "test_value", (PyCFunction)_wrap_test_value, METH_VARARGS }, { "test_value_array", (PyCFunction)_wrap_test_value_array, METH_VARARGS }, { "value_array_get_nth_type", (PyCFunction)_wrap_value_array_get_nth_type, METH_VARARGS }, { "constant_strip_prefix", (PyCFunction)_wrap_constant_strip_prefix, METH_VARARGS }, { "test_gerror_exception", (PyCFunction)_wrap_test_gerror_exception, METH_VARARGS }, { "owned_by_library_get_instance_list", (PyCFunction)_wrap_test_owned_by_library_get_instance_list, METH_NOARGS }, { "floating_and_sunk_get_instance_list", (PyCFunction)_wrap_test_floating_and_sunk_get_instance_list, METH_NOARGS }, { NULL, NULL } }; static struct PyModuleDef _testhelpermodule = { PyModuleDef_HEAD_INIT, "testhelper", NULL, -1, testhelper_functions, NULL, NULL, NULL, NULL }; #ifdef __GNUC__ #define PYGI_MODINIT_FUNC \ __attribute__ ((visibility ("default"))) PyMODINIT_FUNC #else #define PYGI_MODINIT_FUNC PyMODINIT_FUNC #endif PYGI_MODINIT_FUNC PyInit_testhelper (void); PYGI_MODINIT_FUNC PyInit_testhelper (void) { PyObject *module; PyObject *gobject_module; PyObject *m, *d; module = PyModule_Create (&_testhelpermodule); if ((gobject_module = pygobject_init (-1, -1, -1)) == NULL) return NULL; Py_DECREF (gobject_module); d = PyModule_GetDict (module); if ((m = PyImport_ImportModule ("gi.repository.GObject")) == NULL) { PyErr_SetString (PyExc_ImportError, "could not import gobject"); return NULL; } /* TestInterface */ PyTestInterface_Type.tp_methods = (struct PyMethodDef *)_PyTestInterface_methods; PyTestInterface_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); pyg_register_interface (d, "Interface", TEST_TYPE_INTERFACE, &PyTestInterface_Type); pyg_register_interface_info (TEST_TYPE_INTERFACE, &__TestInterface__iinfo); /* TestUnknown */ PyTestUnknown_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); PyTestUnknown_Type.tp_weaklistoffset = offsetof (PyGObject, weakreflist); PyTestUnknown_Type.tp_dictoffset = offsetof (PyGObject, inst_dict); pygobject_register_class ( d, "Unknown", TEST_TYPE_UNKNOWN, &PyTestUnknown_Type, Py_BuildValue ("(O)", &PyGObject_Type, &PyTestInterface_Type)); /* TestFloating */ PyTestFloating_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); PyTestFloating_Type.tp_weaklistoffset = offsetof (PyGObject, weakreflist); PyTestFloating_Type.tp_dictoffset = offsetof (PyGObject, inst_dict); pygobject_register_class (d, "Floating", TEST_TYPE_FLOATING, &PyTestFloating_Type, Py_BuildValue ("(O)", &PyGObject_Type)); /* TestOwnedByLibrary */ PyTestOwnedByLibrary_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); PyTestOwnedByLibrary_Type.tp_methods = (struct PyMethodDef *)_PyTestOwnedByLibrary_methods; PyTestOwnedByLibrary_Type.tp_weaklistoffset = offsetof (PyGObject, weakreflist); PyTestOwnedByLibrary_Type.tp_dictoffset = offsetof (PyGObject, inst_dict); pygobject_register_class (d, "OwnedByLibrary", TEST_TYPE_OWNED_BY_LIBRARY, &PyTestOwnedByLibrary_Type, Py_BuildValue ("(O)", &PyGObject_Type)); /* TestFloatingAndSunk */ PyTestFloatingAndSunk_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); PyTestFloatingAndSunk_Type.tp_methods = (struct PyMethodDef *)_PyTestFloatingAndSunk_methods; PyTestFloatingAndSunk_Type.tp_weaklistoffset = offsetof (PyGObject, weakreflist); PyTestFloatingAndSunk_Type.tp_dictoffset = offsetof (PyGObject, inst_dict); pygobject_register_class ( d, "FloatingAndSunk", TEST_TYPE_FLOATING_AND_SUNK, &PyTestFloatingAndSunk_Type, Py_BuildValue ("(O)", &PyGObject_Type)); return module; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tests/valgrind.supp0000664000000000000000000000076015074673150016232 0ustar00rootroot# https://bugzilla.redhat.com/show_bug.cgi?id=1538073 { Memcheck:Cond fun:__wcsnlen_sse4_1 fun:wcsrtombs fun:wcstombs fun:wcstombs fun:encode_current_locale* } { Memcheck:Leak match-leak-kinds: definite fun:malloc fun:FcPatternObjectInsertElt fun:FcPatternObjectAddWithBinding } { Memcheck:Leak match-leak-kinds: definite fun:malloc fun:FcPatternCreate fun:FcParsePattern fun:FcEndElement } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tools/mkmetadata.py0000664000000000000000000000076015074673150016173 0ustar00rootrootimport tomllib from pyproject_metadata import StandardMetadata def update_metadata_in(): with open("pyproject.toml", "rb") as fd: pyproject = tomllib.load(fd) metadata = StandardMetadata.from_pyproject(pyproject, allow_extra_keys=False) metadata.version = "@VERSION@" del metadata.readme del metadata.dependencies[:] with open("METADATA.in", "wb") as fd: fd.write(metadata.as_rfc822().as_bytes()) if __name__ == "__main__": update_metadata_in() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1760786024.0 pygobject-3.54.5/tools/pygi-convert.sh0000775000000000000000000005163615074673150016506 0ustar00rootroot#!/bin/bash if [ -n "$1" ]; then FILES_TO_CONVERT=( "$@" ) else FILES_TO_CONVERT=( "$(find . -name '*.py')" ) fi for f in "${FILES_TO_CONVERT[@]}"; do perl -i -0 \ -pe "s/import gconf\n/from gi.repository import GConf\n/g;" \ -pe "s/gconf\./GConf\./g;" \ -pe "s/GConf\.client_get_default/GConf.Client.get_default/g;" \ -pe "s/GConf\.CLIENT_/GConf.ClientPreloadType./g;" \ -pe "s/GConf\.VALUE_/GConf.ValueType./g;" \ -pe "s/gconf_client.notify_add\('\/desktop\/sugar\/collaboration\/publish_gadget',/return;gconf_client.notify_add\('\/desktop\/sugar\/collaboration\/publish_gadget',/g;" \ \ -pe "s/import pygtk/import gi/g;" \ -pe "s/pygtk.require\('2.0'\)/gi.require_version\('Gtk', '3.0'\)/g;" \ -pe "s/pygtk.require\(\"2.0\"\)/gi.require_version\(\"Gtk\", \"3.0\"\)/g;" \ -pe "s/import gtk\n/from gi.repository import Gtk\n/g;" \ -pe "s/(? 0/self._content.get_children\(\)/g;" \ -pe "s/len\(self.menu.get_children\(\)\) > 0/self.menu.get_children\(\)/g;" \ -pe "s/import gobject\n/from gi.repository import GObject\n/g;" \ -pe "s/Gtk\..*\.__init__/gobject.GObject.__init__/g;" \ \ -pe "s/rsvg.Handle\s*\(data=([^,\)]+)\)/Rsvg.Handle.new_from_data(\1)/g;" \ \ -pe "s/from gtk import gdk\n/from gi.repository import Gdk\n/g;" \ -pe "s/import gtk.gdk as gdk\n/from gi.repository import Gdk\n/g;" \ -pe "s/Gtk.gdk.x11_/GdkX11.x11_/g;" \ -pe "s/Gtk.gdk\./Gdk\./g;" \ -pe "s/(? Maintainer-Email: Christoph Reiter , Arjan Molenaar , Dan Yeaw , Ignacio Casal Quinteiro License: GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Operating System :: POSIX Classifier: Operating System :: Microsoft :: Windows Classifier: Programming Language :: C Classifier: Programming Language :: Python Classifier: Topic :: Software Development :: Libraries :: Python Modules Project-URL: Homepage, https://pygobject.gnome.org Project-URL: Repository, https://gitlab.gnome.org/GNOME/pygobject.git Project-URL: Changelog, https://gitlab.gnome.org/GNOME/pygobject/-/blob/main/NEWS Requires-Python: >=3.9 Requires-Dist: pycairo>=1.16 Description-Content-Type: text/x-rst .. image:: https://gitlab.gnome.org/GNOME/pygobject/-/raw/main/docs/images/pygobject.svg?ref_type=heads :align: center :width: 400px :height: 98px | **PyGObject** is a Python package which provides bindings for `GObject `__ based libraries such as `GTK `__, `GStreamer `__, `WebKitGTK `__, `GLib `__, `GIO `__ and many more. It supports Linux, Windows, and macOS and works with **Python 3.9+** and **PyPy3**. PyGObject, including this documentation, is licensed under the **LGPLv2.1+**. Homepage -------- https://pygobject.gnome.org Installation ------------ The latest version from PyGObject can be installed from `PyPI `__: pip install PyGObject PyGObject is only distributed as source distribution, so you need a C compiler installed on your host. Please have a look at our `Getting Started `__ documentation for OS specific installation instructions. Development ~~~~~~~~~~~ Our website contains instructions on how to `set up a development environment `__. Default branch renamed to ``main`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The default development branch of PyGObject has been renamed to ``main``. To update your local checkout, use:: git checkout master git branch -m master main git fetch git branch --unset-upstream git branch -u origin/main git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main